Replace boost::serialization.

Boost::serialization and the corresponding internal configuration structure are
replace with a protocol buffer message.

Dropped support for writing old configuration files. Only the new format can be
written. A password change will write a newly formatted configuration file, but
does not delete the old file.

Version bumped to 1.8


git-svn-id: http://encfs.googlecode.com/svn/trunk@80 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
Valient Gough 2012-04-26 02:34:15 +00:00
parent 67821fb209
commit 67c72dfe99
40 changed files with 1028 additions and 960 deletions

View File

@ -1,3 +1,31 @@
Thu Mar 22 2012 Valient Gough <vgough@pobox.com>
* skip name collision test
* bump version to 1.8.0
* drop boost serialization from requirements
Sun Mar 4 2012 Valient Gough <vgough@pobox.com>
* bump ld version
* replace EncFSConfig with protocol buffer
Fri Mar 2 2012 Valient Gough <vgough@pobox.com>
* replace boost serialization with protocol buffer support
Wed Feb 29 2012 Valient Gough <vgough@pobox.com>
* switch to OpenSSL B64 decode to be comptible with boost serialization
* implement v6 config reader using XML reader based on tinyxml
Mon Jan 2 2012 Valient Gough <vgough@pobox.com>
* test for name case collisions in b64 coding
Thu Dec 29 2011 Valient Gough <vgough@pobox.com>
* add base32 support for name encoding
Thu Mar 3 2011 Valient Gough <vgough@pobox.com>
* update copyright on BlockNameIO
Thu Dec 29 2011 Valient Gough <vgough@pobox.com>
* revert fuse_unmount change, wasn't working
Wed Dec 28 2011 Valient Gough <vgough@pobox.com>
* remove m4-local
* bump version to 1.7.5

View File

@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(encfs/encfs.h) dnl a source file from your sub dir
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE(encfs, 1.7.5) dnl searches for some needed programs
AM_INIT_AUTOMAKE(encfs, 1.8.0) dnl searches for some needed programs
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST
@ -48,7 +48,6 @@ AX_PTHREAD
AX_BOOST_BASE([1.34])
AX_BOOST_SYSTEM
AX_BOOST_SERIALIZATION
AX_BOOST_FILESYSTEM
dnl Need to include any user specified flags in the tests below, as they might
@ -203,6 +202,21 @@ if test "$with_rlog" = "test" && test "x$RLOG_LIBS" = "x"; then
[AC_MSG_ERROR([EncFS depends on librlog])])
fi
# find Protocol Buffers
PKG_CHECK_MODULES(PROTOBUF, protobuf >= 2.0)
AC_PATH_PROG(PROTOC, protoc, [no])
if test "$PROTOC" == "no"; then
AC_MSG_FAILURE([Protocol Buffers compiler 'protoc' is required to build.])
fi
# find TinyXML
AC_LANG_PUSH([C++])
CPPFLAGS="$CPPFLAGS -DTIXML_USE_STL"
AC_CHECK_HEADER([tinyxml.h],,[AC_MSG_ERROR([tinyxml.h not found])])
AC_CHECK_LIB([tinyxml],[main],,
[AC_MSG_ERROR([you must install libtinyxml dev])])
AC_LANG_POP([C++])
# look for pod2man program for building man pages
AC_PATH_PROG(POD2MAN, pod2man, [no])
AC_PATH_PROG(POD2HTML, pod2html, [no])

View File

@ -18,6 +18,7 @@
#include "BlockFileIO.h"
#include "MemoryPool.h"
#include "config.pb.h"
#include <cstring>
#include <rlog/rlog.h>
@ -38,7 +39,7 @@ static void clearCache( IORequest &req, int blockSize )
BlockFileIO::BlockFileIO( int blockSize, const FSConfigPtr &cfg )
: _blockSize( blockSize )
, _allowHoles( cfg->config->allowHoles )
, _allowHoles( cfg->config->allow_holes() )
{
rAssert( _blockSize > 1 );
_cache.data = new unsigned char [ _blockSize ];

View File

@ -31,7 +31,6 @@
#include "i18n.h"
using namespace rlog;
using namespace rel;
using namespace boost;
static RLogChannel * Info = DEF_CHANNEL( "info/nameio", Log_Info );
@ -94,16 +93,16 @@ Interface BlockNameIO::CurrentInterface(bool caseSensitive)
{
// implement major version 4 plus support for two prior versions
if (caseSensitive)
return Interface("nameio/block32", 4, 0, 2);
return makeInterface("nameio/block32", 4, 0, 2);
else
return Interface("nameio/block", 4, 0, 2);
return makeInterface("nameio/block", 4, 0, 2);
}
BlockNameIO::BlockNameIO( const rel::Interface &iface,
BlockNameIO::BlockNameIO( const Interface &iface,
const shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize,
bool caseSensitiveEncoding )
: _interface( iface.current() )
: _interface( iface.major() )
, _bs( blockSize )
, _cipher( cipher )
, _key( key )

View File

@ -33,15 +33,15 @@ class Cipher;
class BlockNameIO : public NameIO
{
public:
static rel::Interface CurrentInterface(bool caseSensitive = false);
static Interface CurrentInterface(bool caseSensitive = false);
BlockNameIO( const rel::Interface &iface,
BlockNameIO( const Interface &iface,
const boost::shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize,
bool caseSensitiveEncoding = false );
virtual ~BlockNameIO();
virtual rel::Interface interface() const;
virtual Interface interface() const;
virtual int maxEncodedNameLen( int plaintextNameLen ) const;
virtual int maxDecodedNameLen( int encodedNameLen ) const;

View File

@ -34,7 +34,6 @@
#include "SSL_Cipher.h"
using namespace std;
using namespace rel;
using boost::shared_ptr;
#define REF_MODULE(TYPE) \
@ -150,7 +149,7 @@ shared_ptr<Cipher> Cipher::New( const Interface &iface, int keyLen )
for(it = gCipherMap->begin(); it != mapEnd; ++it)
{
// TODO: we should look for the newest implementation..
if( it->second.iface.implements( iface ) )
if( implements(it->second.iface, iface) )
{
CipherConstructor fn = it->second.constructor;
// pass in requested interface..

View File

@ -42,14 +42,14 @@ class Cipher
public:
// if no key length was indicated when cipher was registered, then keyLen
// <= 0 will be used.
typedef boost::shared_ptr<Cipher> (*CipherConstructor)( const rel::Interface &iface,
typedef boost::shared_ptr<Cipher> (*CipherConstructor)( const Interface &iface,
int keyLenBits );
struct CipherAlgorithm
{
std::string name;
std::string description;
rel::Interface iface;
Interface iface;
Range keyLength;
Range blockSize;
};
@ -59,7 +59,7 @@ public:
static AlgorithmList GetAlgorithmList( bool includeHidden = false );
static boost::shared_ptr<Cipher> New( const rel::Interface &iface,
static boost::shared_ptr<Cipher> New( const Interface &iface,
int keyLen = -1);
static boost::shared_ptr<Cipher> New( const std::string &cipherName,
int keyLen = -1 );
@ -67,12 +67,12 @@ public:
static bool Register(const char *cipherName,
const char *description,
const rel::Interface &iface,
const Interface &iface,
CipherConstructor constructor,
bool hidden = false);
static bool Register(const char *cipherName,
const char *description,
const rel::Interface &iface,
const Interface &iface,
const Range &keyLength, const Range &blockSize,
CipherConstructor constructor,
bool hidden = false);
@ -81,7 +81,7 @@ public:
Cipher();
virtual ~Cipher();
virtual rel::Interface interface() const =0;
virtual Interface interface() const =0;
// create a new key based on a password
// if iterationCount == 0, then iteration count will be determined

View File

@ -19,6 +19,7 @@
#include "Cipher.h"
#include "MemoryPool.h"
#include "config.pb.h"
#include <rlog/rlog.h>
#include <rlog/Error.h>
@ -34,7 +35,7 @@ using boost::shared_ptr;
filesystem at the filesystem configuration level.
When headers are disabled, 2:0 is compatible with version 1:0.
*/
static rel::Interface CipherFileIO_iface("FileIO/Cipher", 2, 0, 1);
static Interface CipherFileIO_iface = makeInterface("FileIO/Cipher", 2, 0, 1);
const int HEADER_SIZE = 8; // 64 bit initialization vector..
@ -51,9 +52,9 @@ static bool checkSize( int fsBlockSize, int cipherBlockSize )
CipherFileIO::CipherFileIO( const shared_ptr<FileIO> &_base,
const FSConfigPtr &cfg)
: BlockFileIO( cfg->config->blockSize, cfg )
: BlockFileIO( cfg->config->block_size(), cfg )
, base( _base )
, haveHeader( cfg->config->uniqueIV )
, haveHeader( cfg->config->unique_iv() )
, externalIV( 0 )
, fileIV( 0 )
, lastFlags( 0 )
@ -65,7 +66,7 @@ CipherFileIO::CipherFileIO( const shared_ptr<FileIO> &_base,
static bool warnOnce = false;
if(!warnOnce)
warnOnce = checkSize( fsConfig->config->blockSize,
warnOnce = checkSize( fsConfig->config->block_size(),
fsConfig->cipher->cipherBlockSize() );
}
@ -73,7 +74,7 @@ CipherFileIO::~CipherFileIO()
{
}
rel::Interface CipherFileIO::interface() const
Interface CipherFileIO::interface() const
{
return CipherFileIO_iface;
}

View File

@ -38,7 +38,7 @@ public:
const FSConfigPtr &cfg);
virtual ~CipherFileIO();
virtual rel::Interface interface() const;
virtual Interface interface() const;
virtual void setFileName( const char *fileName );
virtual const char *getFileName() const;

View File

@ -690,7 +690,7 @@ int DirNode::link( const char *from, const char *to )
rLog(Info, "link %s -> %s", fromCName.c_str(), toCName.c_str());
int res = -EPERM;
if( fsConfig->config->externalIVChaining )
if( fsConfig->config->external_iv() )
{
rLog(Info, "hard links not supported with external IV chaining!");
} else
@ -756,7 +756,7 @@ shared_ptr<FileNode> DirNode::findOrCreate( const char *plainName)
plainName,
(rootDir + cipherName).c_str()));
if(fsConfig->config->externalIVChaining)
if(fsConfig->config->external_iv())
node->setName(0, 0, iv);
rLog(Info, "created FileNode for %s", node->cipherName());

View File

@ -32,88 +32,37 @@ enum ConfigType
{
Config_None = 0,
Config_Prehistoric,
Config_V3,
Config_V4,
Config_V5,
Config_V6
Config_V3 = 3,
Config_V4 = 4,
Config_V5 = 5,
Config_V6 = 6,
Config_V7 = 7
};
class EncFS_Opts;
class Cipher;
class NameIO;
class EncfsConfig;
struct EncFSConfig
{
ConfigType cfgType;
std::string creator;
int subVersion;
// interface of cipher
rel::Interface cipherIface;
// interface used for file name coding
rel::Interface nameIface;
int keySize; // reported in bits
int blockSize; // reported in bytes
std::vector<unsigned char> keyData;
std::vector<unsigned char> salt;
int kdfIterations;
long desiredKDFDuration;
int blockMACBytes; // MAC headers on blocks..
int blockMACRandBytes; // number of random bytes in the block header
bool uniqueIV; // per-file Initialization Vector
bool externalIVChaining; // IV seeding by filename IV chaining
bool chainedNameIV; // filename IV chaining
bool allowHoles; // allow holes in files (implicit zero blocks)
EncFSConfig()
: keyData()
, salt()
{
cfgType = Config_None;
subVersion = 0;
blockMACBytes = 0;
blockMACRandBytes = 0;
uniqueIV = false;
externalIVChaining = false;
chainedNameIV = false;
allowHoles = false;
kdfIterations = 0;
desiredKDFDuration = 500;
}
CipherKey getUserKey(bool useStdin);
CipherKey getUserKey(const std::string &passwordProgram,
CipherKey getUserKey(const EncfsConfig &config, bool useStdin);
CipherKey getUserKey(const EncfsConfig &config,
const std::string &passwordProgram,
const std::string &rootDir);
CipherKey getNewUserKey();
boost::shared_ptr<Cipher> getCipher() const;
CipherKey getNewUserKey(EncfsConfig &config, bool useStdin,
const std::string &program, const std::string &rootDir);
// deprecated
void assignKeyData(const std::string &in);
void assignKeyData(unsigned char *data, int length);
void assignSaltData(unsigned char *data, int length);
unsigned char *getKeyData() const;
unsigned char *getSaltData() const;
private:
CipherKey makeKey(const char *password, int passwdLen);
};
boost::shared_ptr<Cipher> getCipher(const EncfsConfig &cfg);
boost::shared_ptr<Cipher> getCipher(const Interface &iface, int keySize);
// helpers for serializing to/from a stream
std::ostream &operator << (std::ostream &os, const EncFSConfig &cfg);
std::istream &operator >> (std::istream &os, EncFSConfig &cfg);
std::ostream &operator << (std::ostream &os, const EncfsConfig &cfg);
std::istream &operator >> (std::istream &os, EncfsConfig &cfg);
// Filesystem state
struct FSConfig
{
boost::shared_ptr<EncFSConfig> config;
boost::shared_ptr<EncfsConfig> config;
boost::shared_ptr<EncFS_Opts> opts;
boost::shared_ptr<Cipher> cipher;

View File

@ -48,7 +48,7 @@ public:
FileIO();
virtual ~FileIO();
virtual rel::Interface interface() const =0;
virtual Interface interface() const =0;
// default implementation returns 1, meaning this is not block oriented.
virtual int blockSize() const;

View File

@ -80,7 +80,7 @@ FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
shared_ptr<FileIO> rawIO( new RawFileIO( _cname ) );
io = shared_ptr<FileIO>( new CipherFileIO( rawIO, fsConfig ));
if(cfg->config->blockMACBytes || cfg->config->blockMACRandBytes)
if(cfg->config->block_mac_bytes() || cfg->config->block_mac_rand_bytes())
io = shared_ptr<FileIO>(new MACFileIO(io, fsConfig));
}
@ -127,7 +127,7 @@ bool FileNode::setName( const char *plaintextName_, const char *cipherName_,
rDebug("calling setIV on %s", cipherName_);
if(setIVFirst)
{
if(fsConfig->config->externalIVChaining && !setIV(io, iv))
if(fsConfig->config->external_iv() && !setIV(io, iv))
return false;
// now change the name..
@ -151,7 +151,7 @@ bool FileNode::setName( const char *plaintextName_, const char *cipherName_,
io->setFileName( cipherName_ );
}
if(fsConfig->config->externalIVChaining && !setIV(io, iv))
if(fsConfig->config->external_iv() && !setIV(io, iv))
{
_pname = oldPName;
_cname = oldCName;

File diff suppressed because it is too large Load Diff

View File

@ -99,41 +99,33 @@ struct EncFS_Opts
/*
Read existing config file. Looks for any supported configuration version.
*/
ConfigType readConfig( const std::string &rootDir,
const boost::shared_ptr<EncFSConfig> &config );
ConfigType readConfig( const std::string &rootDir, EncfsConfig &config );
/*
Save the configuration. Saves back as the same configuration type as was
read from.
*/
bool saveConfig( ConfigType type, const std::string &rootdir,
const boost::shared_ptr<EncFSConfig> &config );
bool saveConfig( const std::string &rootdir, const EncfsConfig &config );
class EncFS_Context;
RootPtr initFS( EncFS_Context *ctx, const boost::shared_ptr<EncFS_Opts> &opts );
RootPtr createV6Config( EncFS_Context *ctx,
RootPtr createConfig( EncFS_Context *ctx,
const boost::shared_ptr<EncFS_Opts> &opts );
void showFSInfo( const boost::shared_ptr<EncFSConfig> &config );
void showFSInfo( const EncfsConfig &config );
bool readV4Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
bool readV4Config( const char *configFile, EncfsConfig &config,
struct ConfigInfo *);
bool writeV4Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
bool readV5Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
bool readV5Config( const char *configFile, EncfsConfig &config,
struct ConfigInfo *);
bool writeV5Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
bool readV6Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
bool readV6Config( const char *configFile, EncfsConfig &config,
struct ConfigInfo *);
bool readProtoConfig( const char *configFile, EncfsConfig &config,
struct ConfigInfo *);
bool writeV6Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
#endif

View File

@ -22,205 +22,69 @@
#include <rlog/rlog.h>
#include <rlog/RLogChannel.h>
using namespace rel;
using namespace rlog;
static RLogChannel * Info = DEF_CHANNEL( "info/iface", Log_Info );
Interface::Interface(const char *name_, int Current, int Revision, int Age)
: _name( name_ )
, _current( Current )
, _revision( Revision )
, _age( Age )
{
}
Interface::Interface(const std::string &name_, int Current,
int Revision, int Age)
: _name( name_ )
, _current( Current )
, _revision( Revision )
, _age( Age )
{
}
Interface::Interface(const Interface &src)
: _name( src._name )
, _current( src._current )
, _revision( src._revision )
, _age( src._age )
{
}
Interface::Interface()
: _current( 0 )
, _revision( 0 )
, _age( 0 )
{
}
Interface &Interface::operator = (const Interface &src)
{
_name = src._name;
_current = src._current;
_revision = src._revision;
_age = src._age;
return *this;
}
const std::string & Interface::name() const
{
return _name;
}
std::string & Interface::name()
{
return _name;
}
int Interface::current() const
{
return _current;
}
int &Interface::current()
{
return _current;
}
int Interface::revision() const
{
return _revision;
}
int &Interface::revision()
{
return _revision;
}
int Interface::age() const
{
return _age;
}
int &Interface::age()
{
return _age;
}
bool operator == (const Interface &A, const Interface &B)
{
return ( A.name() == B.name()
&& A.current() == B.current()
&& A.revision() == B.revision()
&& A.age() == B.age() );
}
bool operator != (const Interface &A, const Interface &B)
{
return ( A.name() != B.name()
|| A.current() != B.current()
|| A.revision() != B.revision()
|| A.age() != B.age() );
}
// zero branch method of getting comparison sign..
// tricky.. makes assumptions
#if 0
static int sign( int a, int b )
{
unsigned int ab = ((unsigned int)(a - b)) >> 31;
unsigned int ba = ((unsigned int)(b - a)) >> 31;
return 1 + ba - ab;
}
#else
// simple, easy to check, unlikely to break due to unforseen events..
static int sign( int a, int b )
{
if(a < b)
return 0;
else if(a == b)
return 1;
else
return 2;
}
#endif
static int diffSum( const Interface &A, const Interface &B )
{
int cS = sign( A.current() , B.current() );
int aS = sign( A.age(), B.age() );
int rS = sign( A.revision(), B.revision() );
return (cS * 3 + aS) * 3 + rS;
}
const int EqualVersion = (1 * 3 + 1) * 3 + 1;
bool Interface::implements(const Interface &B) const
bool implements(const Interface &A, const Interface &B)
{
rLog(Info, "checking if %s(%i:%i:%i) implements %s(%i:%i:%i)",
name().c_str(), current(), revision(), age(),
B.name().c_str(), B.current(), B.revision(), B.age());
A.name().c_str(), A.major(), A.minor(), A.age(),
B.name().c_str(), B.major(), B.minor(), B.age());
if( name() != B.name() )
if( A.name() != B.name() )
return false;
int currentDiff = current() - B.current();
return ( currentDiff >= 0 && currentDiff <= age() );
int currentDiff = A.major() - B.major();
return ( currentDiff >= 0 && currentDiff <= (int)A.age() );
}
bool operator < (const Interface &A, const Interface &B)
Interface makeInterface(const char *name, int major, int minor, int age)
{
if( A.name() == B.name() )
{
return ( diffSum(A,B) < EqualVersion );
} else
return A.name() < B.name();
Interface iface;
iface.set_name(name);
iface.set_major(major);
iface.set_minor(minor);
iface.set_age(age);
return iface;
}
bool operator > (const Interface &A, const Interface &B)
ConfigVar & operator << (ConfigVar &dst, const Interface &iface)
{
if( A.name() == B.name() )
{
return ( diffSum(A,B) > EqualVersion );
} else
return A.name() < B.name();
}
bool operator <= (const Interface &A, const Interface &B)
{
if( A.name() == B.name() )
{
return ( diffSum(A,B) <= EqualVersion );
} else
return A.name() < B.name();
}
bool operator >= (const Interface &A, const Interface &B)
{
if( A.name() == B.name() )
{
return ( diffSum(A,B) >= EqualVersion );
} else
return A.name() < B.name();
}
ConfigVar & operator << (ConfigVar &dst, const rel::Interface &iface)
{
dst << iface.name() << iface.current() << iface.revision() << iface.age();
dst << iface.name() << (int)iface.major() << (int)iface.minor() << (int)iface.age();
return dst;
}
const ConfigVar & operator >> (const ConfigVar &src, Interface &iface)
{
src >> iface.name();
src >> iface.current();
src >> iface.revision();
src >> iface.age();
src >> *iface.mutable_name();
int major, minor, age;
src >> major >> minor >> age;
iface.set_major(major);
iface.set_minor(minor);
iface.set_age(age);
return src;
}
const XmlValuePtr & operator >> (const XmlValuePtr &src, Interface &iface)
{
(*src)["name"] >> *iface.mutable_name();
int major, minor;
(*src)["major"] >> major;
(*src)["minor"] >> minor;
iface.set_major(major);
iface.set_minor(minor);
return src;
}
bool operator != (const Interface &a, const Interface &b)
{
if (a.major() != b.major())
return true;
if (a.minor() != b.minor())
return true;
return false;
}

View File

@ -19,66 +19,23 @@
#define _Interface_incl_
#include <string>
#include "XmlReader.h"
#include "config.pb.h"
// check if A implements the interface described by B.
// Note that implements(A, B) is not the same as implements(B, A)
// This checks the current() version and age() against B.current() for
// compatibility. Even if A.implements(B) is true, B > A may also be
// true, meaning B is a newer revision of the interface then A.
bool implements( const Interface &a, const Interface &b );
Interface makeInterface( const char *name, int major, int minor, int age );
// Reae operation
class ConfigVar;
const ConfigVar & operator >> (const ConfigVar &, Interface &);
const XmlValuePtr & operator >> (const XmlValuePtr &, Interface &);
// part of REL library..
namespace rel
{
class Interface
{
public:
/*!
Version numbers as described by libtool: info://libtool/versioning
Current - the most recent interface api that is implemented.
Revision - the implementation number of the current interface.
Age - the difference between the newest and oldest interfaces that
are implemented.
*/
Interface( const char *name, int Current, int Revision, int Age );
Interface( const std::string &name, int Current, int Revision, int Age);
Interface(const Interface &src);
Interface();
// check if we implement the interface described by B.
// Note that A.implements(B) is not the same as B.implements(A)
// This checks the current() version and age() against B.current() for
// compatibility. Even if A.implements(B) is true, B > A may also be
// true, meaning B is a newer revision of the interface then A.
bool implements( const Interface &dst ) const;
const std::string &name() const;
int current() const;
int revision() const;
int age() const;
std::string &name();
int &current();
int &revision();
int &age();
Interface &operator = ( const Interface &src );
private:
std::string _name;
int _current;
int _revision;
int _age;
};
}
ConfigVar & operator << (ConfigVar &, const rel::Interface &);
const ConfigVar & operator >> (const ConfigVar &, rel::Interface &);
bool operator < (const rel::Interface &A, const rel::Interface &B);
bool operator > (const rel::Interface &A, const rel::Interface &B);
bool operator <= (const rel::Interface &A, const rel::Interface &B);
bool operator >= (const rel::Interface &A, const rel::Interface &B);
bool operator == (const rel::Interface &A, const rel::Interface &B);
bool operator != (const rel::Interface &A, const rel::Interface &B);
bool operator != (const Interface &a, const Interface &b);
#endif

View File

@ -19,6 +19,7 @@
#include "MemoryPool.h"
#include "FileUtils.h"
#include "config.pb.h"
#include <rlog/rlog.h>
#include <rlog/Error.h>
@ -29,7 +30,6 @@
#include "i18n.h"
using namespace rlog;
using namespace rel;
using namespace std;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
@ -48,13 +48,13 @@ static RLogChannel *Info = DEF_CHANNEL("info/MACFileIO", Log_Info);
// compatible, except at a high level by checking a revision number for the
// filesystem...
//
static rel::Interface MACFileIO_iface("FileIO/MAC", 2, 1, 0);
static Interface MACFileIO_iface = makeInterface("FileIO/MAC", 2, 1, 0);
int dataBlockSize(const FSConfigPtr &cfg)
{
return cfg->config->blockSize
- cfg->config->blockMACBytes
- cfg->config->blockMACRandBytes;
return cfg->config->block_size()
- cfg->config->block_mac_bytes()
- cfg->config->block_mac_rand_bytes();
}
MACFileIO::MACFileIO( const shared_ptr<FileIO> &_base,
@ -63,23 +63,23 @@ MACFileIO::MACFileIO( const shared_ptr<FileIO> &_base,
, base( _base )
, cipher( cfg->cipher )
, key( cfg->key )
, macBytes( cfg->config->blockMACBytes )
, randBytes( cfg->config->blockMACRandBytes )
, macBytes( cfg->config->block_mac_bytes() )
, randBytes( cfg->config->block_mac_rand_bytes() )
, warnOnly( cfg->opts->forceDecode )
{
rAssert( macBytes >= 0 && macBytes <= 8 );
rAssert( randBytes >= 0 );
rLog(Info, "fs block size = %i, macBytes = %i, randBytes = %i",
cfg->config->blockSize,
cfg->config->blockMACBytes,
cfg->config->blockMACRandBytes);
cfg->config->block_size(),
cfg->config->block_mac_bytes(),
cfg->config->block_mac_rand_bytes());
}
MACFileIO::~MACFileIO()
{
}
rel::Interface MACFileIO::interface() const
Interface MACFileIO::interface() const
{
return MACFileIO_iface;
}

View File

@ -36,7 +36,7 @@ public:
MACFileIO();
virtual ~MACFileIO();
virtual rel::Interface interface() const;
virtual Interface interface() const;
virtual void setFileName( const char *fileName );
virtual const char *getFileName() const;

View File

@ -2,8 +2,10 @@
include $(top_srcdir)/Makefile.common
ALL_INCLUDES = @RLOG_CFLAGS@ @OPENSSL_CFLAGS@ @BOOST_CPPFLAGS@
ALL_INCLUDES += @PROTOBUF_CFLAGS@
ALL_LDFLAGS = @RLOG_LIBS@ @OPENSSL_LIBS@ @BOOST_LDFLAGS@
ALL_LDFLAGS += @BOOST_SERIALIZATION_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@
ALL_LDFLAGS += @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@
ALL_LDFLAGS += @PROTOBUF_LIBS@
INCLUDES = $(all_includes) -I../intl
@ -47,10 +49,10 @@ endif
# : : 0 => no new interfaces, but breaks old apps
# : +1 : => internal changes, nothing breaks
#
libencfs_la_LDFLAGS = -version-info 6:2:0
libencfs_la_LDFLAGS = -version-info 7:0:0
libencfs_la_LIBADD = @RLOG_LIBS@ \
@OPENSSL_LIBS@ \
@BOOST_SERIALIZATION_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@
@BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@
EXTRASRC = ../intl/autosprintf.cpp
if BUILD_OPENSSL
@ -62,6 +64,7 @@ endif
libencfs_la_SOURCES = \
readpassphrase.cpp \
base64.cpp \
config.pb.cc \
ConfigReader.cpp \
ConfigVar.cpp \
Context.cpp \
@ -83,6 +86,7 @@ libencfs_la_SOURCES = \
FileNode.cpp \
FileUtils.cpp \
openssl.cpp \
XmlReader.cpp \
${EXTRASRC}
@ -109,6 +113,7 @@ noinst_HEADERS = \
CipherKey.h \
ConfigReader.h \
ConfigVar.h \
config.pb.h \
Context.h \
DirNode.h \
encfs.h \
@ -134,8 +139,14 @@ noinst_HEADERS = \
man_MANS=encfs.1 encfsctl.1
EXTRA_DIST = encfs.pod encfsctl.pod encfs.1 encfsctl.1 encfs-man.html
SUFFIXES = .1 .pod .proto
config.pb.cc: config.pb.h
config.pb.h: config.proto
@PROTOC@ --cpp_out=. config.proto
if BUILD_MAN
SUFFIXES = .1 .pod
# since we have POD2MAN, we can specify how to rebuild encfs.1 if necessary
.pod.1:
@POD2MAN@ --section=1 --release=@VERSION@ --center="Encrypted Filesystem" $< $@

View File

@ -25,6 +25,8 @@
#include "config.h"
#include <pthread.h>
#include <sys/mman.h>
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#else
@ -34,6 +36,7 @@
using namespace rlog;
# include <openssl/crypto.h>
# include <openssl/buffer.h>
#define BLOCKDATA( BLOCK ) (unsigned char*)BLOCK->data->data
@ -140,4 +143,34 @@ void MemoryPool::destroyAll()
}
}
SecureMem::SecureMem(int len)
{
data = (char *)OPENSSL_malloc(len);
if (data)
{
size = len;
mlock(data, size);
memset(data, '\0', size);
VALGRIND_MAKE_MEM_UNDEFINED( data, size );
} else
{
size = 0;
}
}
SecureMem::~SecureMem()
{
if (size)
{
memset(data, '\0', size);
munlock(data, size);
OPENSSL_free(data);
VALGRIND_MAKE_MEM_NOACCESS( data, size );
data = NULL;
size = 0;
}
}

View File

@ -50,5 +50,14 @@ namespace MemoryPool
void destroyAll();
}
struct SecureMem
{
int size;
char *data;
SecureMem(int len);
~SecureMem();
};
#endif

View File

@ -32,7 +32,6 @@
#include "NullNameIO.h"
using namespace std;
using namespace rel;
using namespace rlog;
#define REF_MODULE(TYPE) \
@ -130,7 +129,7 @@ shared_ptr<NameIO> NameIO::New( const Interface &iface,
NameIOMap_t::const_iterator end = gNameIOMap->end();
for(it = gNameIOMap->begin(); it != end; ++it)
{
if( it->second.iface.implements( iface ))
if( implements(it->second.iface, iface ))
{
Constructor fn = it->second.constructor;
result = (*fn)( iface, cipher, key );

View File

@ -32,33 +32,33 @@ class Cipher;
class NameIO
{
public:
typedef shared_ptr<NameIO> (*Constructor)( const rel::Interface &iface,
typedef shared_ptr<NameIO> (*Constructor)( const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key);
struct Algorithm
{
std::string name;
std::string description;
rel::Interface iface;
Interface iface;
};
typedef std::list<Algorithm> AlgorithmList;
static AlgorithmList GetAlgorithmList( bool includeHidden = false );
static shared_ptr<NameIO> New( const rel::Interface &iface,
static shared_ptr<NameIO> New( const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key);
static shared_ptr<NameIO> New( const std::string &name,
const shared_ptr<Cipher> &cipher, const CipherKey &key);
static bool Register( const char *name, const char *description,
const rel::Interface &iface, Constructor constructor,
const Interface &iface, Constructor constructor,
bool hidden = false);
NameIO();
virtual ~NameIO();
virtual rel::Interface interface() const =0;
virtual Interface interface() const =0;
void setChainedNameIV( bool enable );
bool getChainedNameIV() const;

View File

@ -26,13 +26,12 @@
#include <cstring>
using namespace std;
using namespace rel;
using namespace rlog;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
static Interface NullInterface( "nullCipher", 1, 0, 0 );
static Interface NullInterface = makeInterface( "nullCipher", 1, 0, 0 );
static Range NullKeyRange(0);
static Range NullBlockRange(1,4096,1);

View File

@ -28,13 +28,13 @@
*/
class NullCipher : public Cipher
{
rel::Interface iface;
Interface iface;
public:
NullCipher(const rel::Interface &iface);
NullCipher(const Interface &iface);
virtual ~NullCipher();
virtual rel::Interface interface() const;
virtual Interface interface() const;
// create a new key based on a password
virtual CipherKey newKey(const char *password, int passwdLength,

View File

@ -22,7 +22,6 @@
#include <cstring>
using namespace rel;
using boost::shared_ptr;
static shared_ptr<NameIO> NewNNIO( const Interface &,
@ -31,7 +30,7 @@ static shared_ptr<NameIO> NewNNIO( const Interface &,
return shared_ptr<NameIO>( new NullNameIO() );
}
static Interface NNIOIface("nameio/null", 1, 0, 0);
static Interface NNIOIface = makeInterface("nameio/null", 1, 0, 0);
static bool NullNameIO_registered = NameIO::Register("Null",
"No encryption of filenames", NNIOIface, NewNNIO);

View File

@ -23,13 +23,13 @@
class NullNameIO : public NameIO
{
public:
static rel::Interface CurrentInterface();
static Interface CurrentInterface();
NullNameIO( );
virtual ~NullNameIO();
virtual rel::Interface interface() const;
virtual Interface interface() const;
virtual int maxEncodedNameLen( int plaintextNameLen ) const;
virtual int maxDecodedNameLen( int encodedNameLen ) const;

View File

@ -33,9 +33,9 @@
using namespace std;
static rel::Interface RawFileIO_iface("FileIO/Raw", 1, 0, 0);
static Interface RawFileIO_iface = makeInterface("FileIO/Raw", 1, 0, 0);
FileIO *NewRawFileIO( const rel::Interface &iface )
FileIO *NewRawFileIO( const Interface &iface )
{
(void)iface;
return new RawFileIO();
@ -82,7 +82,7 @@ RawFileIO::~RawFileIO()
close( _fd );
}
rel::Interface RawFileIO::interface() const
Interface RawFileIO::interface() const
{
return RawFileIO_iface;
}

View File

@ -29,7 +29,7 @@ public:
RawFileIO( const std::string &fileName );
virtual ~RawFileIO();
virtual rel::Interface interface() const;
virtual Interface interface() const;
virtual void setFileName( const char *fileName );
virtual const char *getFileName() const;

View File

@ -66,10 +66,7 @@ inline int MIN(int a, int b)
the state of EVP_CIPHER struct. EVP_BytesToKey will only produce 128 bit
keys for the EVP Blowfish interface, which is not what we want.
Eliminated the salt code, since we don't use it.. Reason is that we're
using the derived key to encode random data. Since there is no known
plaintext, there is no ability for an attacker to pre-compute known
password->data mappings, which is what the salt is meant to frustrate.
DEPRECATED: this is here for backward compatibilty only. Use PBKDF
*/
int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
const unsigned char *data, int dataLen,
@ -103,7 +100,7 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
}
int offset = 0;
int toCopy = MIN( nkey, mds - offset );
int toCopy = MIN( nkey, (int)mds - offset );
if( toCopy )
{
memcpy( key, mdBuf+offset, toCopy );
@ -111,7 +108,7 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
nkey -= toCopy;
offset += toCopy;
}
toCopy = MIN( niv, mds - offset );
toCopy = MIN( niv, (int)mds - offset );
if( toCopy )
{
memcpy( iv, mdBuf+offset, toCopy );
@ -174,8 +171,8 @@ int TimedPBKDF2(const char *pass, int passlen,
// - Version 2:1 adds support for Message Digest function interface
// - Version 2:2 adds PBKDF2 for password derivation
// - Version 3:0 adds a new IV mechanism
static Interface BlowfishInterface( "ssl/blowfish", 3, 0, 2 );
static Interface AESInterface( "ssl/aes", 3, 0, 2 );
static Interface BlowfishInterface = makeInterface( "ssl/blowfish", 3, 0, 2 );
static Interface AESInterface = makeInterface( "ssl/aes", 3, 0, 2 );
#if defined(HAVE_EVP_BF)
@ -275,19 +272,20 @@ SSLKey::SSLKey(int keySize_, int ivLength_)
this->ivLength = ivLength_;
pthread_mutex_init( &mutex, 0 );
buffer = (unsigned char *)OPENSSL_malloc( keySize + ivLength );
memset( buffer, 0, keySize + ivLength );
// most likely fails unless we're running as root, or a user-page-lock
// kernel patch is applied..
mlock( buffer, keySize + ivLength );
memset( buffer, 0, keySize + ivLength );
}
SSLKey::~SSLKey()
{
memset( buffer, 0, keySize + ivLength );
OPENSSL_free( buffer );
munlock( buffer, keySize + ivLength );
OPENSSL_free( buffer );
keySize = 0;
ivLength = 0;
@ -370,7 +368,7 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_,
iface.name().c_str(), _keySize, _ivLength);
if( (EVP_CIPHER_key_length( _blockCipher ) != (int )_keySize)
&& iface.current() == 1)
&& iface.major() == 1)
{
rWarning("Running in backward compatibilty mode for 1.0 - \n"
"key is really %i bits, not %i.\n"
@ -438,7 +436,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) );
int bytes = 0;
if( iface.current() > 1 )
if( iface.major() > 1 )
{
// now we use BytesToKey, which can deal with Blowfish keys larger then
// 128 bits.
@ -680,7 +678,7 @@ int SSL_Cipher::cipherBlockSize() const
void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key) const
{
if (iface.current() >= 3)
if (iface.major() >= 3)
{
memcpy( ivec, IVData(key), _ivLength );
@ -707,7 +705,7 @@ void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed,
}
}
/** For backward compatibility.
/** Deprecated: For backward compatibility only.
A watermark attack was discovered against this IV setup. If an attacker
could get a victim to store a carefully crafted file, they could later
determine if the victim had the file in encrypted storage (without
@ -717,13 +715,6 @@ void SSL_Cipher::setIVec_old(unsigned char *ivec,
unsigned int seed,
const shared_ptr<SSLKey> &key) const
{
/* These multiplication constants chosen as they represent (non optimal)
Golumb rulers, the idea being to spread around the information in the
seed.
0x060a4011 : ruler length 26, 7 marks, 21 measurable lengths
0x0221040d : ruler length 25, 7 marks, 21 measurable lengths
*/
unsigned int var1 = 0x060a4011 * seed;
unsigned int var2 = 0x0221040d * (seed ^ 0xD3FEA11C);

View File

@ -70,21 +70,21 @@ using boost::shared_ptr;
*/
class SSL_Cipher : public Cipher
{
rel::Interface iface;
rel::Interface realIface;
Interface iface;
Interface realIface;
const EVP_CIPHER *_blockCipher;
const EVP_CIPHER *_streamCipher;
unsigned int _keySize; // in bytes
unsigned int _ivLength;
public:
SSL_Cipher(const rel::Interface &iface, const rel::Interface &realIface,
SSL_Cipher(const Interface &iface, const Interface &realIface,
const EVP_CIPHER *blockCipher, const EVP_CIPHER *streamCipher,
int keyLength);
virtual ~SSL_Cipher();
// returns the real interface, not the one we're emulating (if any)..
virtual rel::Interface interface() const;
virtual Interface interface() const;
// create a new key based on a password
virtual CipherKey newKey(const char *password, int passwdLength,

View File

@ -26,7 +26,6 @@
#include "i18n.h"
#include <cstring>
using namespace rel;
using namespace std;
static shared_ptr<NameIO> NewStreamNameIO( const Interface &iface,
@ -65,13 +64,13 @@ static bool StreamIO_registered = NameIO::Register("Stream",
Interface StreamNameIO::CurrentInterface()
{
// implement major version 2, 1, and 0
return Interface("nameio/stream", 2, 1, 2);
return makeInterface("nameio/stream", 2, 1, 2);
}
StreamNameIO::StreamNameIO( const rel::Interface &iface,
StreamNameIO::StreamNameIO( const Interface &iface,
const shared_ptr<Cipher> &cipher,
const CipherKey &key )
: _interface( iface.current() )
: _interface( iface.major() )
, _cipher( cipher )
, _key( key )
{

View File

@ -27,14 +27,14 @@ using boost::shared_ptr;
class StreamNameIO : public NameIO
{
public:
static rel::Interface CurrentInterface();
static Interface CurrentInterface();
StreamNameIO( const rel::Interface &iface,
StreamNameIO( const Interface &iface,
const shared_ptr<Cipher> &cipher,
const CipherKey &key );
virtual ~StreamNameIO();
virtual rel::Interface interface() const;
virtual Interface interface() const;
virtual int maxEncodedNameLen( int plaintextNameLen ) const;
virtual int maxDecodedNameLen( int encodedNameLen ) const;

191
encfs/XmlReader.cpp Normal file
View File

@ -0,0 +1,191 @@
/*****************************************************************************
* Author: Valient Gough <vgough@pobox.com>
*
*****************************************************************************
* Copyright (c) 2012, Valient Gough
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "XmlReader.h"
#include "base64.h"
#include <rlog/rlog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <map>
#include <tinyxml.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
using namespace std;
using namespace rlog;
XmlValue::~XmlValue()
{
}
XmlValuePtr XmlValue::operator[] (const char *path) const
{
return this->find(path);
}
XmlValuePtr XmlValue::find(const char *name) const
{
rError("in XmlValue::operator[%s]", name);
return XmlValuePtr(new XmlValue());
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, std::string &out)
{
out = ptr->text();
return ptr;
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, int &out)
{
out = atoi(ptr->text().c_str());
return ptr;
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, long &out)
{
out = atol(ptr->text().c_str());
return ptr;
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, double &out)
{
out = atof(ptr->text().c_str());
return ptr;
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, bool &out)
{
out = atoi(ptr->text().c_str());
return ptr;
}
bool XmlValue::readB64Data(unsigned char *data, int length) const
{
std::string s = value;
s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
BIO *b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
BIO *bmem = BIO_new_mem_buf((void *)s.c_str(), s.size());
bmem = BIO_push(b64, bmem);
int decodedSize = BIO_read(bmem, data, length);
BIO_free_all(b64);
if (decodedSize != length)
{
rError("decoding bytes len %i, expecting output len %i, got %i",
(int)s.size(), length, decodedSize);
return false;
}
return true;
}
std::string safeValueForNode(TiXmlElement *element)
{
std::string value;
const TiXmlNode *child = element->FirstChild();
if (child)
{
const TiXmlText *childText = child->ToText();
if (childText)
value = childText->Value();
}
return value;
}
class XmlNode : virtual public XmlValue
{
TiXmlElement *element;
public:
XmlNode(TiXmlElement *element_)
: XmlValue(safeValueForNode(element_))
, element(element_)
{
}
virtual ~XmlNode()
{
}
virtual XmlValuePtr find(const char *name) const
{
if (name[0] == '@')
{
return XmlValuePtr(new XmlValue(element->Attribute(name+1)));
} else
{
return XmlValuePtr(new XmlNode(element->FirstChild(name)->ToElement()));
}
}
};
struct XmlReader::XmlReaderData
{
boost::shared_ptr<TiXmlDocument> doc;
};
XmlReader::XmlReader()
: pd(new XmlReaderData())
{
}
XmlReader::~XmlReader()
{
}
bool XmlReader::load(const char *fileName)
{
pd->doc.reset(new TiXmlDocument(fileName));
return pd->doc->LoadFile();
}
XmlValuePtr XmlReader::operator[] ( const char *name ) const
{
TiXmlNode *node = pd->doc->FirstChild(name);
if (node == NULL)
{
rError("Xml node %s not found", name);
return XmlValuePtr(new XmlValue());
}
TiXmlElement *element = node->ToElement();
if (element == NULL)
{
rError("Xml node %s not element, type = %i", name, node->Type());
return XmlValuePtr(new XmlValue());
}
return XmlValuePtr(new XmlNode(element));
}

78
encfs/XmlReader.h Normal file
View File

@ -0,0 +1,78 @@
/*****************************************************************************
* Author: Valient Gough <vgough@pobox.com>
*
*****************************************************************************
* Copyright (c) 2012, Valient Gough
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _XmlReader_incl_
#define _XmlReader_incl_
#include <boost/shared_ptr.hpp>
#include <string>
class XmlValue;
typedef boost::shared_ptr<XmlValue> XmlValuePtr;
class XmlValue
{
std::string value;
public:
XmlValue()
{
}
XmlValue(const std::string &value)
{
this->value = value;
}
virtual ~XmlValue();
XmlValuePtr operator[] (const char *path) const;
bool readB64Data(unsigned char *data, int length) const;
const std::string &text() const
{
return value;
}
protected:
virtual XmlValuePtr find(const char *name) const;
};
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, std::string &outStr);
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, int &out);
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, long &out);
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, double &out);
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, bool &out);
class XmlReader
{
public:
XmlReader();
~XmlReader();
bool load(const char *fileName);
XmlValuePtr operator[](const char *name) const;
private:
struct XmlReaderData;
boost::shared_ptr<XmlReaderData> pd;
};
#endif

36
encfs/config.proto Normal file
View File

@ -0,0 +1,36 @@
message EncfsConfig
{
optional string creator = 1;
optional int32 revision = 2 [default=0];
required Interface cipher = 3;
required bytes key = 4;
optional bytes salt = 41;
required int32 key_size = 42; // in bits
optional int32 kdf_iterations = 43 [default=0];
optional int32 kdf_duration = 44 [default=500];
optional Interface naming = 5;
optional bool unique_iv = 51 [default=false];
optional bool chained_iv = 52 [default=false];
optional bool external_iv = 53 [default=false];
required int32 block_size = 6;
optional int32 block_mac_bytes = 61 [default=0];
optional int32 block_mac_rand_bytes = 611 [default=0];
optional bool allow_holes = 62 [default = false];
}
message Interface
{
required string name = 1;
required uint32 major = 2; // major version number
required uint32 minor = 3; // minor version number
// Age indicates number of major versions supported. 0 means no backward
// compatibility. See libtool "updating version information" for more
// details on how major/minor/age are used for versioning libraries.
optional uint32 age = 4;
}

View File

@ -176,7 +176,7 @@ static int showInfo( int argc, char **argv )
if( !checkDir( rootDir ))
return EXIT_FAILURE;
boost::shared_ptr<EncFSConfig> config(new EncFSConfig);
EncfsConfig config;
ConfigType type = readConfig( rootDir, config );
// show information stored in config..
@ -194,24 +194,22 @@ static int showInfo( int argc, char **argv )
case Config_V3:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 3 configuration; "
"created by %s\n"), config->creator.c_str());
"created by %s\n"), config.creator().c_str());
break;
case Config_V4:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 4 configuration; "
"created by %s\n"), config->creator.c_str());
"created by %s\n"), config.creator().c_str());
break;
case Config_V5:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 5 configuration; "
"created by %s (revision %i)\n"), config->creator.c_str(),
config->subVersion);
break;
case Config_V6:
case Config_V7:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 6 configuration; "
"created by %s (revision %i)\n"), config->creator.c_str(),
config->subVersion);
cout << "\n" << autosprintf(_("Version %i configuration; "
"created by %s (revision %i)\n"),
type,
config.creator().c_str(),
config.revision());
break;
}
@ -687,9 +685,7 @@ static int cmd_showcruft( int argc, char **argv )
int filesFound = showcruft( rootInfo, "/" );
cerr << autosprintf(
ngettext("Found %i invalid file.", "Found %i invalid files.",
filesFound), filesFound) << "\n";
cerr << autosprintf("Found %i invalid file(s).", filesFound) << "\n";
return EXIT_SUCCESS;
}
@ -701,7 +697,7 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
if( !checkDir( rootDir ))
return EXIT_FAILURE;
boost::shared_ptr<EncFSConfig> config(new EncFSConfig);
EncfsConfig config;
ConfigType cfgType = readConfig( rootDir, config );
if(cfgType == Config_None)
@ -711,12 +707,11 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
}
// instanciate proper cipher
shared_ptr<Cipher> cipher = Cipher::New(
config->cipherIface, config->keySize );
shared_ptr<Cipher> cipher = getCipher(config);
if(!cipher)
{
cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"),
config->cipherIface.name().c_str());
config.cipher().name().c_str());
return EXIT_FAILURE;
}
@ -724,13 +719,14 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
cout << _("Enter current Encfs password\n");
if (annotate)
cerr << "$PROMPT$ passwd" << endl;
CipherKey userKey = config->getUserKey( useStdin );
CipherKey userKey = getUserKey( config, useStdin );
if(!userKey)
return EXIT_FAILURE;
// decode volume key using user key -- at this point we detect an incorrect
// password if the key checksum does not match (causing readKey to fail).
CipherKey volumeKey = cipher->readKey( config->getKeyData(), userKey );
CipherKey volumeKey = cipher->readKey(
(const unsigned char *)config.key().data(), userKey );
if(!volumeKey)
{
@ -741,17 +737,15 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
// Now, get New user key..
userKey.reset();
cout << _("Enter new Encfs password\n");
// reinitialize salt and iteration count
config->kdfIterations = 0; // generate new
// create new key
if( useStdin )
{
if (annotate)
cerr << "$PROMPT$ new_passwd" << endl;
userKey = config->getUserKey( true );
}
else
userKey = config->getNewUserKey();
userKey = getNewUserKey( config, useStdin, string(), string() );
// re-encode the volume key using the new user key and write it out..
int result = EXIT_FAILURE;
@ -764,10 +758,10 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
cipher->writeKey( volumeKey, keyBuf, userKey );
userKey.reset();
config->assignKeyData( keyBuf, encodedKeySize );
config.set_key( keyBuf, encodedKeySize );
delete[] keyBuf;
if(saveConfig( cfgType, rootDir, config ))
if(saveConfig( rootDir, config ))
{
// password modified -- changes volume key of filesystem..
cout << _("Volume Key successfully updated.\n");
@ -816,7 +810,7 @@ int main(int argc, char **argv)
slog->subscribeTo( GetGlobalChannel("error") );
slog->subscribeTo( GetGlobalChannel("warning") );
#ifndef NO_DEBUG
//slog->subscribeTo( GetGlobalChannel("debug") );
slog->subscribeTo( GetGlobalChannel("debug") );
#endif
if(argc < 2)

View File

@ -69,7 +69,6 @@ inline static int MAX(int a, int b)
using namespace std;
using namespace rlog;
using namespace rel;
using namespace gnu;
using boost::shared_ptr;
using boost::scoped_ptr;

View File

@ -47,11 +47,12 @@
#endif
#endif
#include <google/protobuf/text_format.h>
#include <tr1/unordered_set>
using namespace std;
using namespace rel;
using namespace rlog;
using boost::shared_ptr;
@ -235,35 +236,28 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
cipher->writeKey( key, keyBuf, encodingKey );
// store in config struct..
EncFSConfig cfg;
cfg.cipherIface = cipher->interface();
cfg.keySize = 8 * cipher->keySize();
cfg.blockSize = FSBlockSize;
cfg.assignKeyData( keyBuf, encodedKeySize );
EncfsConfig cfg;
cfg.mutable_cipher()->MergeFrom(cipher->interface());
cfg.set_key_size(8 * cipher->keySize());
cfg.set_block_size(FSBlockSize);
cfg.set_key( keyBuf, encodedKeySize );
// save config
string data;
{
ostringstream st;
st << cfg;
data = st.str();
}
google::protobuf::TextFormat::PrintToString(cfg, &data);
// read back in and check everything..
EncFSConfig cfg2;
{
istringstream st(data);
st >> cfg2;
}
EncfsConfig cfg2;
google::protobuf::TextFormat::ParseFromString(data, &cfg2);
// check..
rAssert( cfg.cipherIface.implements(cfg2.cipherIface) );
rAssert( cfg.keySize == cfg2.keySize );
rAssert( cfg.blockSize == cfg2.blockSize );
rAssert( implements(cfg.cipher(),cfg2.cipher()) );
rAssert( cfg.key_size() == cfg2.key_size() );
rAssert( cfg.block_size() == cfg2.block_size() );
// try decoding key..
CipherKey key2 = cipher->readKey( cfg2.getKeyData(), encodingKey );
CipherKey key2 = cipher->readKey( (unsigned char *)cfg2.key().data(), encodingKey );
if(!key2)
{
if(verbose)
@ -286,15 +280,15 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
FSConfigPtr fsCfg = FSConfigPtr(new FSConfig);
fsCfg->cipher = cipher;
fsCfg->key = key;
fsCfg->config.reset(new EncFSConfig);
fsCfg->config->blockSize = FSBlockSize;
fsCfg->config.reset(new EncfsConfig);
fsCfg->config->set_block_size(FSBlockSize);
if(verbose)
cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
{
fsCfg->opts.reset(new EncFS_Opts);
fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false;
fsCfg->config->set_unique_iv(false);
fsCfg->nameCoding.reset( new StreamNameIO(
StreamNameIO::CurrentInterface(), cipher, key ) );
@ -310,7 +304,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
cerr << "Testing name encode/decode (block coding w/ IV chaining)\n";
{
fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false;
fsCfg->config->set_unique_iv(false);
fsCfg->nameCoding.reset( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize() ) );
@ -326,7 +320,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
cerr << "Testing name encode/decode (block coding w/ IV chaining, base32)\n";
{
fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false;
fsCfg->config->set_unique_iv(false);
fsCfg->nameCoding.reset( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize(), true ) );
@ -503,8 +497,8 @@ int main(int argc, char *argv[])
{
cerr << it->name
<< " ( " << it->iface.name() << " "
<< it->iface.current() << ":"
<< it->iface.revision() << ":"
<< it->iface.major() << ":"
<< it->iface.minor() << ":"
<< it->iface.age() << " ) : " << it->description << "\n";
cerr << " - key length " << it->keyLength.min() << " to "
<< it->keyLength.max() << " , block size " << it->blockSize.min()