reformat using clang

This commit is contained in:
Valient Gough 2014-10-18 19:19:33 -07:00
parent 744f56b95d
commit b3c851982f
59 changed files with 8004 additions and 9714 deletions

52
.clang-format Normal file
View File

@ -0,0 +1,52 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AllowShortFunctionsOnASingleLine: true
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: true
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerBinding: true
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerBindsToType: true
SpacesBeforeTrailingComments: 2
Cpp11BracedListStyle: true
Standard: Auto
IndentWidth: 2
TabWidth: 8
UseTab: Never
BreakBeforeBraces: Attach
IndentFunctionDeclarationAfterType: true
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
SpaceBeforeParens: ControlStatements
...

View File

@ -28,47 +28,37 @@
#include "i18n.h"
template <typename Type>
inline Type min( Type A, Type B )
{
inline Type min(Type A, Type B) {
return (B < A) ? B : A;
}
static void clearCache( IORequest &req, int blockSize )
{
static void clearCache(IORequest &req, int blockSize) {
memset(req.data, 0, blockSize);
req.dataLen = 0;
}
BlockFileIO::BlockFileIO(int blockSize, const FSConfigPtr &cfg)
: _blockSize( blockSize )
, _allowHoles( cfg->config->allowHoles )
{
: _blockSize(blockSize), _allowHoles(cfg->config->allowHoles) {
rAssert(_blockSize > 1);
_cache.data = new unsigned char[_blockSize];
}
BlockFileIO::~BlockFileIO()
{
BlockFileIO::~BlockFileIO() {
clearCache(_cache, _blockSize);
delete[] _cache.data;
}
ssize_t BlockFileIO::cacheReadOneBlock( const IORequest &req ) const
{
ssize_t BlockFileIO::cacheReadOneBlock(const IORequest &req) const {
// we can satisfy the request even if _cache.dataLen is too short, because
// we always request a full block during reads..
if((req.offset == _cache.offset) && (_cache.dataLen != 0))
{
if ((req.offset == _cache.offset) && (_cache.dataLen != 0)) {
// satisfy request from cache
int len = req.dataLen;
if(_cache.dataLen < len)
len = _cache.dataLen;
if (_cache.dataLen < len) len = _cache.dataLen;
memcpy(req.data, _cache.data, len);
return len;
} else
{
if(_cache.dataLen > 0)
clearCache( _cache, _blockSize );
} else {
if (_cache.dataLen > 0) clearCache(_cache, _blockSize);
// cache results of read -- issue reads for full blocks
IORequest tmp;
@ -76,8 +66,7 @@ ssize_t BlockFileIO::cacheReadOneBlock( const IORequest &req ) const
tmp.data = _cache.data;
tmp.dataLen = _blockSize;
ssize_t result = readOneBlock(tmp);
if(result > 0)
{
if (result > 0) {
_cache.offset = req.offset;
_cache.dataLen = result; // the amount we really have
if (result > req.dataLen)
@ -88,34 +77,29 @@ ssize_t BlockFileIO::cacheReadOneBlock( const IORequest &req ) const
}
}
bool BlockFileIO::cacheWriteOneBlock( const IORequest &req )
{
bool BlockFileIO::cacheWriteOneBlock(const IORequest &req) {
// cache results of write (before pass-thru, because it may be modified
// in-place)
memcpy(_cache.data, req.data, req.dataLen);
_cache.offset = req.offset;
_cache.dataLen = req.dataLen;
bool ok = writeOneBlock(req);
if(!ok)
clearCache( _cache, _blockSize );
if (!ok) clearCache(_cache, _blockSize);
return ok;
}
ssize_t BlockFileIO::read( const IORequest &req ) const
{
ssize_t BlockFileIO::read(const IORequest &req) const {
rAssert(_blockSize != 0);
int partialOffset = req.offset % _blockSize;
off_t blockNum = req.offset / _blockSize;
ssize_t result = 0;
if(partialOffset == 0 && req.dataLen <= _blockSize)
{
if (partialOffset == 0 && req.dataLen <= _blockSize) {
// read completely within a single block -- can be handled as-is by
// readOneBloc().
return cacheReadOneBlock(req);
} else
{
} else {
size_t size = req.dataLen;
// if the request is larger then a block, then request each block
@ -126,18 +110,15 @@ ssize_t BlockFileIO::read( const IORequest &req ) const
blockReq.data = NULL;
unsigned char *out = req.data;
while( size )
{
while (size) {
blockReq.offset = blockNum * _blockSize;
// if we're reading a full block, then read directly into the
// result buffer instead of using a temporary
if (partialOffset == 0 && size >= (size_t)_blockSize)
blockReq.data = out;
else
{
if(!mb.data)
mb = MemoryPool::allocate( _blockSize );
else {
if (!mb.data) mb = MemoryPool::allocate(_blockSize);
blockReq.data = mb.data;
}
@ -158,19 +139,16 @@ ssize_t BlockFileIO::read( const IORequest &req ) const
++blockNum;
partialOffset = 0;
if(unlikely(readSize < _blockSize))
break;
if (unlikely(readSize < _blockSize)) break;
}
if(mb.data)
MemoryPool::release( mb );
if (mb.data) MemoryPool::release(mb);
}
return result;
}
bool BlockFileIO::write( const IORequest &req )
{
bool BlockFileIO::write(const IORequest &req) {
rAssert(_blockSize != 0);
off_t fileSize = getSize();
@ -184,11 +162,9 @@ bool BlockFileIO::write( const IORequest &req )
ssize_t lastBlockSize = fileSize % _blockSize;
off_t lastNonEmptyBlock = lastFileBlock;
if(lastBlockSize == 0)
--lastNonEmptyBlock;
if (lastBlockSize == 0) --lastNonEmptyBlock;
if( req.offset > fileSize )
{
if (req.offset > fileSize) {
// extend file first to fill hole with 0's..
const bool forceWrite = false;
padFile(fileSize, req.offset, forceWrite);
@ -196,11 +172,9 @@ bool BlockFileIO::write( const IORequest &req )
// check against edge cases where we can just let the base class handle the
// request as-is..
if(partialOffset == 0 && req.dataLen <= _blockSize)
{
if (partialOffset == 0 && req.dataLen <= _blockSize) {
// if writing a full block.. pretty safe..
if( req.dataLen == _blockSize )
return cacheWriteOneBlock( req );
if (req.dataLen == _blockSize) return cacheWriteOneBlock(req);
// if writing a partial block, but at least as much as what is
// already there..
@ -218,34 +192,28 @@ bool BlockFileIO::write( const IORequest &req )
bool ok = true;
size_t size = req.dataLen;
unsigned char *inPtr = req.data;
while( size )
{
while (size) {
blockReq.offset = blockNum * _blockSize;
int toCopy = min((size_t)(_blockSize - partialOffset), size);
// if writing an entire block, or writing a partial block that requires
// no merging with existing data..
if( (toCopy == _blockSize)
||(partialOffset == 0 && blockReq.offset + toCopy >= fileSize))
{
if ((toCopy == _blockSize) ||
(partialOffset == 0 && blockReq.offset + toCopy >= fileSize)) {
// write directly from buffer
blockReq.data = inPtr;
blockReq.dataLen = toCopy;
} else
{
} else {
// need a temporary buffer, since we have to either merge or pad
// the data.
if(!mb.data)
mb = MemoryPool::allocate( _blockSize );
if (!mb.data) mb = MemoryPool::allocate(_blockSize);
memset(mb.data, 0, _blockSize);
blockReq.data = mb.data;
if(blockNum > lastNonEmptyBlock)
{
if (blockNum > lastNonEmptyBlock) {
// just pad..
blockReq.dataLen = toCopy + partialOffset;
} else
{
} else {
// have to merge with existing block data..
blockReq.dataLen = _blockSize;
blockReq.dataLen = cacheReadOneBlock(blockReq);
@ -259,8 +227,7 @@ bool BlockFileIO::write( const IORequest &req )
}
// Finally, write the damn thing!
if(!cacheWriteOneBlock( blockReq ))
{
if (!cacheWriteOneBlock(blockReq)) {
ok = false;
break;
}
@ -272,19 +239,14 @@ bool BlockFileIO::write( const IORequest &req )
partialOffset = 0;
}
if(mb.data)
MemoryPool::release( mb );
if (mb.data) MemoryPool::release(mb);
return ok;
}
int BlockFileIO::blockSize() const
{
return _blockSize;
}
int BlockFileIO::blockSize() const { return _blockSize; }
void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
{
void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
off_t oldLastBlock = oldSize / _blockSize;
off_t newLastBlock = newSize / _blockSize;
int newBlockSize = newSize % _blockSize;
@ -292,13 +254,11 @@ void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
IORequest req;
MemBlock mb;
if(oldLastBlock == newLastBlock)
{
if (oldLastBlock == newLastBlock) {
// when the real write occurs, it will have to read in the existing
// data and pad it anyway, so we won't do it here (unless we're
// forced).
if( forceWrite )
{
if (forceWrite) {
mb = MemoryPool::allocate(_blockSize);
req.data = mb.data;
@ -306,8 +266,7 @@ void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
req.dataLen = oldSize % _blockSize;
int outSize = newSize % _blockSize; // outSize > req.dataLen
if(outSize)
{
if (outSize) {
memset(mb.data, 0, outSize);
cacheReadOneBlock(req);
req.dataLen = outSize;
@ -315,8 +274,7 @@ void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
}
} else
rDebug("optimization: not padding last block");
} else
{
} else {
mb = MemoryPool::allocate(_blockSize);
req.data = mb.data;
@ -328,8 +286,7 @@ void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
req.dataLen = oldSize % _blockSize;
// 1. req.dataLen == 0, iff oldSize was already a multiple of blocksize
if(req.dataLen != 0)
{
if (req.dataLen != 0) {
rDebug("padding block %" PRIi64, oldLastBlock);
memset(mb.data, 0, _blockSize);
cacheReadOneBlock(req);
@ -339,10 +296,8 @@ void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
}
// 2, pad zero blocks unless holes are allowed
if(!_allowHoles)
{
for(; oldLastBlock != newLastBlock; ++oldLastBlock)
{
if (!_allowHoles) {
for (; oldLastBlock != newLastBlock; ++oldLastBlock) {
rDebug("padding block %" PRIi64, oldLastBlock);
req.offset = oldLastBlock * _blockSize;
req.dataLen = _blockSize;
@ -352,8 +307,7 @@ void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
}
// 3. only necessary if write is forced and block is non 0 length
if(forceWrite && newBlockSize)
{
if (forceWrite && newBlockSize) {
req.offset = newLastBlock * _blockSize;
req.dataLen = newBlockSize;
memset(mb.data, 0, req.dataLen);
@ -361,35 +315,27 @@ void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
}
}
if(mb.data)
MemoryPool::release( mb );
if (mb.data) MemoryPool::release(mb);
}
int BlockFileIO::truncateBase( off_t size, FileIO *base )
{
int BlockFileIO::truncateBase(off_t size, FileIO *base) {
int partialBlock = size % _blockSize;
int res = 0;
off_t oldSize = getSize();
if( size > oldSize )
{
if (size > oldSize) {
// truncate can be used to extend a file as well. truncate man page
// states that it will pad with 0's.
// do the truncate so that the underlying filesystem can allocate
// the space, and then we'll fill it in padFile..
if(base)
base->truncate( size );
if (base) base->truncate(size);
const bool forceWrite = true;
padFile(oldSize, size, forceWrite);
} else
if( size == oldSize )
{
} else if (size == oldSize) {
// the easiest case, but least likely....
} else
if( partialBlock )
{
} else if (partialBlock) {
// partial block after truncate. Need to read in the block being
// truncated before the truncate. Then write it back out afterwards,
// since the encoding will change..
@ -404,29 +350,24 @@ int BlockFileIO::truncateBase( off_t size, FileIO *base )
ssize_t rdSz = cacheReadOneBlock(req);
// do the truncate
if(base)
res = base->truncate( size );
if (base) res = base->truncate(size);
// write back out partial block
req.dataLen = partialBlock;
bool wrRes = cacheWriteOneBlock(req);
if((rdSz < 0) || (!wrRes))
{
if ((rdSz < 0) || (!wrRes)) {
// rwarning - unlikely to ever occur..
rWarning(_("truncate failure: read %i bytes, partial block of %i"),
(int)rdSz, partialBlock);
}
MemoryPool::release(mb);
} else
{
} else {
// truncating on a block bounday. No need to re-encode the last
// block..
if(base)
res = base->truncate( size );
if (base) res = base->truncate(size);
}
return res;
}

View File

@ -32,8 +32,7 @@
the existing block, merge with the write request, and a write of the full
block.
*/
class BlockFileIO : public FileIO
{
class BlockFileIO : public FileIO {
public:
BlockFileIO(int blockSize, const FSConfigPtr &cfg);
virtual ~BlockFileIO();
@ -45,7 +44,6 @@ public:
virtual int blockSize() const;
protected:
int truncateBase(off_t size, FileIO *base);
void padFile(off_t oldSize, off_t newSize, bool forceWrite);
@ -65,4 +63,3 @@ protected:
};
#endif

View File

@ -35,42 +35,40 @@ using namespace rel;
static RLogChannel *Info = DEF_CHANNEL("info/nameio", Log_Info);
static shared_ptr<NameIO> NewBlockNameIO(const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key )
{
const shared_ptr<Cipher> &cipher,
const CipherKey &key) {
int blockSize = 8;
if(cipher)
blockSize = cipher->cipherBlockSize();
if (cipher) blockSize = cipher->cipherBlockSize();
return shared_ptr<NameIO>(
new BlockNameIO(iface, cipher, key, blockSize, false));
}
static shared_ptr<NameIO> NewBlockNameIO32(const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key )
{
const shared_ptr<Cipher> &cipher,
const CipherKey &key) {
int blockSize = 8;
if(cipher)
blockSize = cipher->cipherBlockSize();
if (cipher) blockSize = cipher->cipherBlockSize();
return shared_ptr<NameIO>(
new BlockNameIO(iface, cipher, key, blockSize, true));
}
static bool BlockIO_registered = NameIO::Register("Block",
static bool BlockIO_registered = NameIO::Register(
"Block",
// description of block name encoding algorithm..
// xgroup(setup)
gettext_noop("Block encoding, hides file name size somewhat"),
BlockNameIO::CurrentInterface(false),
NewBlockNameIO);
BlockNameIO::CurrentInterface(false), NewBlockNameIO);
static bool BlockIO32_registered = NameIO::Register("Block32",
static bool BlockIO32_registered = NameIO::Register(
"Block32",
// description of block name encoding algorithm..
// xgroup(setup)
gettext_noop("Block encoding with base32 output for case-sensitive systems"),
BlockNameIO::CurrentInterface(true),
NewBlockNameIO32);
gettext_noop(
"Block encoding with base32 output for case-sensitive systems"),
BlockNameIO::CurrentInterface(true), NewBlockNameIO32);
/*
- Version 1.0 computed MAC over the filename, but not the padding bytes.
@ -89,8 +87,7 @@ static bool BlockIO32_registered = NameIO::Register("Block32",
- Version 4.0 adds support for base32, creating names more suitable for
case-insensitive filesystems (eg Mac).
*/
Interface BlockNameIO::CurrentInterface(bool caseSensitive)
{
Interface BlockNameIO::CurrentInterface(bool caseSensitive) {
// implement major version 4 plus support for two prior versions
if (caseSensitive)
return Interface("nameio/block32", 4, 0, 2);
@ -99,30 +96,24 @@ Interface BlockNameIO::CurrentInterface(bool caseSensitive)
}
BlockNameIO::BlockNameIO(const rel::Interface &iface,
const shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize,
bool caseSensitiveEncoding )
: _interface( iface.current() )
, _bs( blockSize )
, _cipher( cipher )
, _key( key )
, _caseSensitive( caseSensitiveEncoding )
{
const shared_ptr<Cipher> &cipher, const CipherKey &key,
int blockSize, bool caseSensitiveEncoding)
: _interface(iface.current()),
_bs(blockSize),
_cipher(cipher),
_key(key),
_caseSensitive(caseSensitiveEncoding) {
// just to be safe..
rAssert(blockSize < 128);
}
BlockNameIO::~BlockNameIO()
{
}
BlockNameIO::~BlockNameIO() {}
Interface BlockNameIO::interface() const
{
Interface BlockNameIO::interface() const {
return CurrentInterface(_caseSensitive);
}
int BlockNameIO::maxEncodedNameLen( int plaintextNameLen ) const
{
int BlockNameIO::maxEncodedNameLen(int plaintextNameLen) const {
// number of blocks, rounded up.. Only an estimate at this point, err on
// the size of too much space rather then too little.
int numBlocks = (plaintextNameLen + _bs) / _bs;
@ -133,31 +124,26 @@ int BlockNameIO::maxEncodedNameLen( int plaintextNameLen ) const
return B256ToB64Bytes(encodedNameLen);
}
int BlockNameIO::maxDecodedNameLen( int encodedNameLen ) const
{
int decLen256 = _caseSensitive ?
B32ToB256Bytes( encodedNameLen ) :
B64ToB256Bytes( encodedNameLen );
int BlockNameIO::maxDecodedNameLen(int encodedNameLen) const {
int decLen256 = _caseSensitive ? B32ToB256Bytes(encodedNameLen)
: B64ToB256Bytes(encodedNameLen);
return decLen256 - 2; // 2 checksum bytes removed..
}
int BlockNameIO::encodeName( const char *plaintextName, int length,
uint64_t *iv, char *encodedName ) const
{
int BlockNameIO::encodeName(const char *plaintextName, int length, uint64_t *iv,
char *encodedName) const {
// copy the data into the encoding buffer..
memcpy(encodedName + 2, plaintextName, length);
// Pad encryption buffer to block boundary..
int padding = _bs - length % _bs;
if(padding == 0)
padding = _bs; // padding a full extra block!
if (padding == 0) padding = _bs; // padding a full extra block!
memset(encodedName + length + 2, (unsigned char)padding, padding);
// store the IV before it is modified by the MAC call.
uint64_t tmpIV = 0;
if( iv && _interface >= 3 )
tmpIV = *iv;
if (iv && _interface >= 3) tmpIV = *iv;
// include padding in MAC computation
unsigned int mac = _cipher->MAC_16((unsigned char *)encodedName + 2,
@ -174,57 +160,49 @@ int BlockNameIO::encodeName( const char *plaintextName, int length,
int encodedStreamLen = length + 2 + padding;
int encLen;
if (_caseSensitive)
{
if (_caseSensitive) {
encLen = B256ToB32Bytes(encodedStreamLen);
changeBase2Inline( (unsigned char *)encodedName, encodedStreamLen,
8, 5, true );
changeBase2Inline((unsigned char *)encodedName, encodedStreamLen, 8, 5,
true);
B32ToAscii((unsigned char *)encodedName, encLen);
} else
{
} else {
encLen = B256ToB64Bytes(encodedStreamLen);
changeBase2Inline( (unsigned char *)encodedName, encodedStreamLen,
8, 6, true );
changeBase2Inline((unsigned char *)encodedName, encodedStreamLen, 8, 6,
true);
B64ToAscii((unsigned char *)encodedName, encLen);
}
return encLen;
}
int BlockNameIO::decodeName( const char *encodedName, int length,
uint64_t *iv, char *plaintextName ) const
{
int decLen256 = _caseSensitive ?
B32ToB256Bytes( length ) :
B64ToB256Bytes( length );
int BlockNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
char *plaintextName) const {
int decLen256 =
_caseSensitive ? B32ToB256Bytes(length) : B64ToB256Bytes(length);
int decodedStreamLen = decLen256 - 2;
// don't bother trying to decode files which are too small
if(decodedStreamLen < _bs)
throw ERROR("Filename too small to decode");
if (decodedStreamLen < _bs) throw ERROR("Filename too small to decode");
BUFFER_INIT(tmpBuf, 32, (unsigned int)length);
// decode into tmpBuf,
if (_caseSensitive)
{
if (_caseSensitive) {
AsciiToB32((unsigned char *)tmpBuf, (unsigned char *)encodedName, length);
changeBase2Inline((unsigned char *)tmpBuf, length, 5, 8, false);
} else
{
} else {
AsciiToB64((unsigned char *)tmpBuf, (unsigned char *)encodedName, length);
changeBase2Inline((unsigned char *)tmpBuf, length, 6, 8, false);
}
// pull out the header information
unsigned int mac = ((unsigned int)((unsigned char)tmpBuf[0])) << 8
| ((unsigned int)((unsigned char)tmpBuf[1]));
unsigned int mac = ((unsigned int)((unsigned char)tmpBuf[0])) << 8 |
((unsigned int)((unsigned char)tmpBuf[1]));
uint64_t tmpIV = 0;
if( iv && _interface >= 3 )
tmpIV = *iv;
if (iv && _interface >= 3) tmpIV = *iv;
_cipher->blockDecode((unsigned char *)tmpBuf + 2, decodedStreamLen,
(uint64_t)mac ^ tmpIV, _key);
@ -234,10 +212,8 @@ int BlockNameIO::decodeName( const char *encodedName, int length,
int finalSize = decodedStreamLen - padding;
// might happen if there is an error decoding..
if(padding > _bs || finalSize < 0)
{
rDebug("padding, _bx, finalSize = %i, %i, %i", padding,
_bs, finalSize);
if (padding > _bs || finalSize < 0) {
rDebug("padding, _bx, finalSize = %i, %i, %i", padding, _bs, finalSize);
throw ERROR("invalid padding size");
}
@ -251,8 +227,7 @@ int BlockNameIO::decodeName( const char *encodedName, int length,
BUFFER_RESET(tmpBuf);
if(mac2 != mac)
{
if (mac2 != mac) {
rDebug("checksum mismatch: expected %u, got %u", mac, mac2);
rDebug("on decode of %i bytes", finalSize);
throw ERROR("checksum mismatch in filename decode");
@ -261,8 +236,4 @@ int BlockNameIO::decodeName( const char *encodedName, int length,
return finalSize;
}
bool BlockNameIO::Enabled()
{
return true;
}
bool BlockNameIO::Enabled() { return true; }

View File

@ -32,13 +32,11 @@ class Cipher;
mode to encode filenames. The filenames are padded to be a multiple of the
cipher block size.
*/
class BlockNameIO : public NameIO
{
class BlockNameIO : public NameIO {
public:
static rel::Interface CurrentInterface(bool caseSensitive = false);
BlockNameIO( const rel::Interface &iface,
const shared_ptr<Cipher> &cipher,
BlockNameIO(const rel::Interface &iface, const shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize,
bool caseSensitiveEncoding = false);
virtual ~BlockNameIO();
@ -50,11 +48,12 @@ public:
// hack to help with static builds
static bool Enabled();
protected:
virtual int encodeName( const char *plaintextName, int length,
uint64_t *iv, char *encodedName ) const;
virtual int decodeName( const char *encodedName, int length,
uint64_t *iv, char *plaintextName ) const;
virtual int encodeName(const char *plaintextName, int length, uint64_t *iv,
char *encodedName) const;
virtual int decodeName(const char *encodedName, int length, uint64_t *iv,
char *plaintextName) const;
private:
int _interface;
@ -64,6 +63,4 @@ private:
bool _caseSensitive;
};
#endif

View File

@ -39,19 +39,14 @@ using namespace std;
using namespace rel;
#define REF_MODULE(TYPE) \
if( !TYPE::Enabled() ) \
cerr << "referenceModule: should never happen\n";
if (!TYPE::Enabled()) cerr << "referenceModule: should never happen\n";
static
void AddSymbolReferences()
{
static void AddSymbolReferences() {
REF_MODULE(SSL_Cipher)
REF_MODULE(NullCipher)
}
struct CipherAlg
{
struct CipherAlg {
bool hidden;
Cipher::CipherConstructor constructor;
string description;
@ -63,22 +58,18 @@ struct CipherAlg
typedef multimap<string, CipherAlg> CipherMap_t;
static CipherMap_t *gCipherMap = NULL;
std::list<Cipher::CipherAlgorithm>
Cipher::GetAlgorithmList( bool includeHidden )
{
std::list<Cipher::CipherAlgorithm> Cipher::GetAlgorithmList(
bool includeHidden) {
AddSymbolReferences();
list<CipherAlgorithm> result;
if(!gCipherMap)
return result;
if (!gCipherMap) return result;
CipherMap_t::const_iterator it;
CipherMap_t::const_iterator mapEnd = gCipherMap->end();
for(it = gCipherMap->begin(); it != mapEnd; ++it)
{
if(includeHidden || !it->second.hidden)
{
for (it = gCipherMap->begin(); it != mapEnd; ++it) {
if (includeHidden || !it->second.hidden) {
CipherAlgorithm tmp;
tmp.name = it->first;
tmp.description = it->second.description;
@ -94,21 +85,19 @@ Cipher::GetAlgorithmList( bool includeHidden )
}
bool Cipher::Register(const char *name, const char *description,
const Interface &iface, CipherConstructor fn, bool hidden)
{
const Interface &iface, CipherConstructor fn,
bool hidden) {
Range keyLength(-1, -1, 1);
Range blockSize(-1, -1, 1);
return Cipher::Register( name, description, iface,
keyLength, blockSize, fn, hidden );
return Cipher::Register(name, description, iface, keyLength, blockSize, fn,
hidden);
}
bool Cipher::Register(const char *name, const char *description,
const Interface &iface, const Range &keyLength,
const Range &blockSize,
CipherConstructor fn, bool hidden)
{
if(!gCipherMap)
gCipherMap = new CipherMap_t;
const Range &blockSize, CipherConstructor fn,
bool hidden) {
if (!gCipherMap) gCipherMap = new CipherMap_t;
CipherAlg ca;
ca.hidden = hidden;
@ -122,15 +111,12 @@ bool Cipher::Register(const char *name, const char *description,
return true;
}
shared_ptr<Cipher> Cipher::New(const string &name, int keyLen)
{
shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
shared_ptr<Cipher> result;
if(gCipherMap)
{
if (gCipherMap) {
CipherMap_t::const_iterator it = gCipherMap->find(name);
if(it != gCipherMap->end())
{
if (it != gCipherMap->end()) {
CipherConstructor fn = it->second.constructor;
// use current interface..
result = (*fn)(it->second.iface, keyLen);
@ -140,19 +126,15 @@ shared_ptr<Cipher> Cipher::New(const string &name, int keyLen)
return result;
}
shared_ptr<Cipher> Cipher::New( const Interface &iface, int keyLen )
{
shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) {
shared_ptr<Cipher> result;
if(gCipherMap)
{
if (gCipherMap) {
CipherMap_t::const_iterator it;
CipherMap_t::const_iterator mapEnd = gCipherMap->end();
for(it = gCipherMap->begin(); it != mapEnd; ++it)
{
for (it = gCipherMap->begin(); it != mapEnd; ++it) {
// TODO: we should look for the newest implementation..
if( it->second.iface.implements( iface ) )
{
if (it->second.iface.implements(iface)) {
CipherConstructor fn = it->second.constructor;
// pass in requested interface..
result = (*fn)(iface, keyLen);
@ -167,17 +149,12 @@ shared_ptr<Cipher> Cipher::New( const Interface &iface, int keyLen )
return result;
}
Cipher::Cipher()
{
}
Cipher::Cipher() {}
Cipher::~Cipher()
{
}
Cipher::~Cipher() {}
unsigned int Cipher::MAC_32(const unsigned char *src, int len,
const CipherKey &key, uint64_t *chainedIV ) const
{
const CipherKey &key, uint64_t *chainedIV) const {
uint64_t mac64 = MAC_64(src, len, key, chainedIV);
unsigned int mac32 = ((mac64 >> 32) & 0xffffffff) ^ (mac64 & 0xffffffff);
@ -186,8 +163,7 @@ unsigned int Cipher::MAC_32( const unsigned char *src, int len,
}
unsigned int Cipher::MAC_16(const unsigned char *src, int len,
const CipherKey &key, uint64_t *chainedIV ) const
{
const CipherKey &key, uint64_t *chainedIV) const {
uint64_t mac64 = MAC_64(src, len, key, chainedIV);
unsigned int mac32 = ((mac64 >> 32) & 0xffffffff) ^ (mac64 & 0xffffffff);
@ -196,21 +172,18 @@ unsigned int Cipher::MAC_16( const unsigned char *src, int len,
return mac16;
}
bool Cipher::nameEncode( unsigned char *data, int len,
uint64_t iv64, const CipherKey &key ) const
{
bool Cipher::nameEncode(unsigned char *data, int len, uint64_t iv64,
const CipherKey &key) const {
return streamEncode(data, len, iv64, key);
}
bool Cipher::nameDecode( unsigned char *data, int len,
uint64_t iv64, const CipherKey &key ) const
{
bool Cipher::nameDecode(unsigned char *data, int len, uint64_t iv64,
const CipherKey &key) const {
return streamDecode(data, len, iv64, key);
}
string Cipher::encodeAsString(const CipherKey &key,
const CipherKey &encodingKey )
{
const CipherKey &encodingKey) {
int encodedKeySize = this->encodedKeySize();
unsigned char *keyBuf = new unsigned char[encodedKeySize];

View File

@ -37,16 +37,14 @@
Cipher's should register themselves so they can be instanciated via
Cipher::New().
*/
class Cipher
{
class Cipher {
public:
// if no key length was indicated when cipher was registered, then keyLen
// <= 0 will be used.
typedef shared_ptr<Cipher>(*CipherConstructor)(const rel::Interface &iface,
int keyLenBits);
struct CipherAlgorithm
{
struct CipherAlgorithm {
std::string name;
std::string description;
rel::Interface iface;
@ -54,29 +52,19 @@ public:
Range blockSize;
};
typedef std::list<CipherAlgorithm> AlgorithmList;
static AlgorithmList GetAlgorithmList(bool includeHidden = false);
static shared_ptr<Cipher> New(const rel::Interface &iface, int keyLen = -1);
static shared_ptr<Cipher> New(const std::string &cipherName, int keyLen = -1);
static shared_ptr<Cipher> New( const rel::Interface &iface,
int keyLen = -1);
static shared_ptr<Cipher> New( const std::string &cipherName,
int keyLen = -1 );
static bool Register(const char *cipherName,
const char *description,
static bool Register(const char *cipherName, const char *description,
const rel::Interface &iface,
CipherConstructor constructor,
CipherConstructor constructor, bool hidden = false);
static bool Register(const char *cipherName, const char *description,
const rel::Interface &iface, const Range &keyLength,
const Range &blockSize, CipherConstructor constructor,
bool hidden = false);
static bool Register(const char *cipherName,
const char *description,
const rel::Interface &iface,
const Range &keyLength, const Range &blockSize,
CipherConstructor constructor,
bool hidden = false);
Cipher();
virtual ~Cipher();
@ -123,21 +111,22 @@ public:
// 64 bit MAC of the data with the given key
virtual uint64_t MAC_64(const unsigned char *src, int len,
const CipherKey &key, uint64_t *chainedIV = 0 ) const =0;
const CipherKey &key,
uint64_t *chainedIV = 0) const = 0;
// based on reductions of MAC_64
unsigned int MAC_32( const unsigned char *src, int len,
const CipherKey &key, uint64_t *chainedIV = 0 ) const;
unsigned int MAC_16( const unsigned char *src, int len,
const CipherKey &key, uint64_t *chainedIV = 0 ) const;
unsigned int MAC_32(const unsigned char *src, int len, const CipherKey &key,
uint64_t *chainedIV = 0) const;
unsigned int MAC_16(const unsigned char *src, int len, const CipherKey &key,
uint64_t *chainedIV = 0) const;
// functional interfaces
/*
Stream encoding of data in-place. The stream data can be any length.
*/
virtual bool streamEncode( unsigned char *data, int len,
uint64_t iv64, const CipherKey &key) const=0;
virtual bool streamDecode( unsigned char *data, int len,
uint64_t iv64, const CipherKey &key) const=0;
virtual bool streamEncode(unsigned char *data, int len, uint64_t iv64,
const CipherKey &key) const = 0;
virtual bool streamDecode(unsigned char *data, int len, uint64_t iv64,
const CipherKey &key) const = 0;
/*
These are just aliases of streamEncode / streamDecode, but there are
@ -145,21 +134,19 @@ public:
effectively two stream modes - one for encoding partial blocks and
another for encoding filenames.
*/
virtual bool nameEncode( unsigned char *data, int len,
uint64_t iv64, const CipherKey &key) const;
virtual bool nameDecode( unsigned char *data, int len,
uint64_t iv64, const CipherKey &key) const;
virtual bool nameEncode(unsigned char *data, int len, uint64_t iv64,
const CipherKey &key) const;
virtual bool nameDecode(unsigned char *data, int len, uint64_t iv64,
const CipherKey &key) const;
/*
Block encoding of data in-place. The data size should be a multiple of
the cipher block size.
*/
virtual bool blockEncode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &key) const=0;
virtual bool blockDecode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &key) const=0;
virtual bool blockEncode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &key) const = 0;
virtual bool blockDecode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &key) const = 0;
};
#endif

View File

@ -39,11 +39,9 @@ static rel::Interface CipherFileIO_iface("FileIO/Cipher", 2, 0, 1);
const int HEADER_SIZE = 8; // 64 bit initialization vector..
static bool checkSize( int fsBlockSize, int cipherBlockSize )
{
static bool checkSize(int fsBlockSize, int cipherBlockSize) {
int blockBoundary = fsBlockSize % cipherBlockSize;
if(blockBoundary != 0)
{
if (blockBoundary != 0) {
rError("CipherFileIO: blocks should be multiple of cipher block size");
return true;
} else
@ -52,13 +50,12 @@ static bool checkSize( int fsBlockSize, int cipherBlockSize )
CipherFileIO::CipherFileIO(const shared_ptr<FileIO> &_base,
const FSConfigPtr &cfg)
: BlockFileIO( cfg->config->blockSize, cfg )
, base( _base )
, haveHeader( cfg->config->uniqueIV )
, externalIV( 0 )
, fileIV( 0 )
, lastFlags( 0 )
{
: BlockFileIO(cfg->config->blockSize, cfg),
base(_base),
haveHeader(cfg->config->uniqueIV),
externalIV(0),
fileIV(0),
lastFlags(0) {
fsConfig = cfg;
cipher = cfg->cipher;
key = cfg->key;
@ -70,67 +67,49 @@ CipherFileIO::CipherFileIO( const shared_ptr<FileIO> &_base,
fsConfig->cipher->cipherBlockSize());
}
CipherFileIO::~CipherFileIO()
{
}
CipherFileIO::~CipherFileIO() {}
rel::Interface CipherFileIO::interface() const
{
return CipherFileIO_iface;
}
rel::Interface CipherFileIO::interface() const { return CipherFileIO_iface; }
int CipherFileIO::open( int flags )
{
int CipherFileIO::open(int flags) {
int res = base->open(flags);
if( res >= 0 )
lastFlags = flags;
if (res >= 0) lastFlags = flags;
return res;
}
void CipherFileIO::setFileName( const char *fileName )
{
void CipherFileIO::setFileName(const char *fileName) {
base->setFileName(fileName);
}
const char *CipherFileIO::getFileName() const
{
return base->getFileName();
}
const char *CipherFileIO::getFileName() const { return base->getFileName(); }
bool CipherFileIO::setIV( uint64_t iv )
{
bool CipherFileIO::setIV(uint64_t iv) {
rDebug("in setIV, current IV = %" PRIu64 ", new IV = %" PRIu64
", fileIV = %" PRIu64,
externalIV, iv, fileIV);
if(externalIV == 0)
{
if (externalIV == 0) {
// we're just being told about which IV to use. since we haven't
// initialized the fileIV, there is no need to just yet..
externalIV = iv;
if (fileIV != 0)
rWarning("fileIV initialized before externalIV! (%" PRIu64
", %" PRIu64 ")", fileIV, externalIV);
} else
if(haveHeader)
{
rWarning("fileIV initialized before externalIV! (%" PRIu64 ", %" PRIu64
")",
fileIV, externalIV);
} else if (haveHeader) {
// we have an old IV, and now a new IV, so we need to update the fileIV
// on disk.
if(fileIV == 0)
{
if (fileIV == 0) {
// ensure the file is open for read/write..
int newFlags = lastFlags | O_RDWR;
int res = base->open(newFlags);
if(res < 0)
{
if(res == -EISDIR)
{
if (res < 0) {
if (res == -EISDIR) {
// duh -- there are no file headers for directories!
externalIV = iv;
return base->setIV(iv);
} else
{
} else {
rDebug("writeHeader failed to re-open for write");
return false;
}
@ -140,8 +119,7 @@ bool CipherFileIO::setIV( uint64_t iv )
uint64_t oldIV = externalIV;
externalIV = iv;
if(!writeHeader())
{
if (!writeHeader()) {
externalIV = oldIV;
return false;
}
@ -150,13 +128,11 @@ bool CipherFileIO::setIV( uint64_t iv )
return base->setIV(iv);
}
int CipherFileIO::getAttr( struct stat *stbuf ) const
{
int CipherFileIO::getAttr(struct stat *stbuf) const {
int res = base->getAttr(stbuf);
// adjust size if we have a file header
if((res == 0) && haveHeader &&
S_ISREG(stbuf->st_mode) && (stbuf->st_size > 0))
{
if ((res == 0) && haveHeader && S_ISREG(stbuf->st_mode) &&
(stbuf->st_size > 0)) {
rAssert(stbuf->st_size >= HEADER_SIZE);
stbuf->st_size -= HEADER_SIZE;
}
@ -164,26 +140,22 @@ int CipherFileIO::getAttr( struct stat *stbuf ) const
return res;
}
off_t CipherFileIO::getSize() const
{
off_t CipherFileIO::getSize() const {
off_t size = base->getSize();
// No check on S_ISREG here -- don't call getSize over getAttr unless this
// is a normal file!
if(haveHeader && size > 0)
{
if (haveHeader && size > 0) {
rAssert(size >= HEADER_SIZE);
size -= HEADER_SIZE;
}
return size;
}
void CipherFileIO::initHeader( )
{
void CipherFileIO::initHeader() {
// check if the file has a header, and read it if it does.. Otherwise,
// create one.
off_t rawSize = base->getSize();
if(rawSize >= HEADER_SIZE)
{
if (rawSize >= HEADER_SIZE) {
rDebug("reading existing header, rawSize = %" PRIi64, rawSize);
// has a header.. read it
unsigned char buf[8] = {0};
@ -194,34 +166,28 @@ void CipherFileIO::initHeader( )
req.dataLen = 8;
base->read(req);
cipher->streamDecode( buf, sizeof(buf),
externalIV, key );
cipher->streamDecode(buf, sizeof(buf), externalIV, key);
fileIV = 0;
for(int i=0; i<8; ++i)
fileIV = (fileIV << 8) | (uint64_t)buf[i];
for (int i = 0; i < 8; ++i) fileIV = (fileIV << 8) | (uint64_t)buf[i];
rAssert(fileIV != 0); // 0 is never used..
} else
{
} else {
rDebug("creating new file IV header");
unsigned char buf[8] = {0};
do
{
do {
if (!cipher->randomize(buf, 8, false))
throw ERROR("Unable to generate a random file IV");
fileIV = 0;
for(int i=0; i<8; ++i)
fileIV = (fileIV << 8) | (uint64_t)buf[i];
for (int i = 0; i < 8; ++i) fileIV = (fileIV << 8) | (uint64_t)buf[i];
if (fileIV == 0)
rWarning("Unexpected result: randomize returned 8 null bytes!");
} while (fileIV == 0); // don't accept 0 as an option..
if( base->isWritable() )
{
if (base->isWritable()) {
cipher->streamEncode(buf, sizeof(buf), externalIV, key);
IORequest req;
@ -236,26 +202,21 @@ void CipherFileIO::initHeader( )
rDebug("initHeader finished, fileIV = %" PRIu64, fileIV);
}
bool CipherFileIO::writeHeader( )
{
if( !base->isWritable() )
{
bool CipherFileIO::writeHeader() {
if (!base->isWritable()) {
// open for write..
int newFlags = lastFlags | O_RDWR;
if( base->open( newFlags ) < 0 )
{
if (base->open(newFlags) < 0) {
rDebug("writeHeader failed to re-open for write");
return false;
}
}
if(fileIV == 0)
rError("Internal error: fileIV == 0 in writeHeader!!!");
if (fileIV == 0) rError("Internal error: fileIV == 0 in writeHeader!!!");
rDebug("writing fileIV %" PRIu64, fileIV);
unsigned char buf[8] = {0};
for(int i=0; i<8; ++i)
{
for (int i = 0; i < 8; ++i) {
buf[sizeof(buf) - 1 - i] = (unsigned char)(fileIV & 0xff);
fileIV >>= 8;
}
@ -272,8 +233,7 @@ bool CipherFileIO::writeHeader( )
return true;
}
ssize_t CipherFileIO::readOneBlock( const IORequest &req ) const
{
ssize_t CipherFileIO::readOneBlock(const IORequest &req) const {
// read raw data, then decipher it..
int bs = blockSize();
off_t blockNum = req.offset / bs;
@ -281,28 +241,23 @@ ssize_t CipherFileIO::readOneBlock( const IORequest &req ) const
ssize_t readSize = 0;
IORequest tmpReq = req;
if(haveHeader)
tmpReq.offset += HEADER_SIZE;
if (haveHeader) tmpReq.offset += HEADER_SIZE;
readSize = base->read(tmpReq);
bool ok;
if(readSize > 0)
{
if (readSize > 0) {
if (haveHeader && fileIV == 0)
const_cast<CipherFileIO *>(this)->initHeader();
if(readSize != bs)
{
if (readSize != bs) {
ok = streamRead(tmpReq.data, (int)readSize, blockNum ^ fileIV);
} else
{
} else {
ok = blockRead(tmpReq.data, (int)readSize, blockNum ^ fileIV);
}
if(!ok)
{
rDebug("decodeBlock failed for block %" PRIi64 ", size %i",
blockNum, (int)readSize );
if (!ok) {
rDebug("decodeBlock failed for block %" PRIi64 ", size %i", blockNum,
(int)readSize);
readSize = -1;
}
} else
@ -311,47 +266,36 @@ ssize_t CipherFileIO::readOneBlock( const IORequest &req ) const
return readSize;
}
bool CipherFileIO::writeOneBlock( const IORequest &req )
{
bool CipherFileIO::writeOneBlock(const IORequest &req) {
int bs = blockSize();
off_t blockNum = req.offset / bs;
if(haveHeader && fileIV == 0)
initHeader();
if (haveHeader && fileIV == 0) initHeader();
bool ok;
if( req.dataLen != bs )
{
ok = streamWrite( req.data, (int)req.dataLen,
blockNum ^ fileIV );
} else
{
ok = blockWrite( req.data, (int)req.dataLen,
blockNum ^ fileIV );
if (req.dataLen != bs) {
ok = streamWrite(req.data, (int)req.dataLen, blockNum ^ fileIV);
} else {
ok = blockWrite(req.data, (int)req.dataLen, blockNum ^ fileIV);
}
if( ok )
{
if(haveHeader)
{
if (ok) {
if (haveHeader) {
IORequest tmpReq = req;
tmpReq.offset += HEADER_SIZE;
ok = base->write(tmpReq);
} else
ok = base->write(req);
} else
{
rDebug("encodeBlock failed for block %" PRIi64 ", size %i",
blockNum, req.dataLen);
} else {
rDebug("encodeBlock failed for block %" PRIi64 ", size %i", blockNum,
req.dataLen);
ok = false;
}
return ok;
}
bool CipherFileIO::blockWrite(unsigned char *buf, int size,
uint64_t _iv64 ) const
{
uint64_t _iv64) const {
if (!fsConfig->reverseEncryption)
return cipher->blockEncode(buf, size, _iv64, key);
else
@ -359,28 +303,22 @@ bool CipherFileIO::blockWrite( unsigned char *buf, int size,
}
bool CipherFileIO::streamWrite(unsigned char *buf, int size,
uint64_t _iv64 ) const
{
uint64_t _iv64) const {
if (!fsConfig->reverseEncryption)
return cipher->streamEncode(buf, size, _iv64, key);
else
return cipher->streamDecode(buf, size, _iv64, key);
}
bool CipherFileIO::blockRead(unsigned char *buf, int size,
uint64_t _iv64 ) const
{
uint64_t _iv64) const {
if (fsConfig->reverseEncryption)
return cipher->blockEncode(buf, size, _iv64, key);
else
{
if(_allowHoles)
{
else {
if (_allowHoles) {
// special case - leave all 0's alone
for (int i = 0; i < size; ++i)
if(buf[i] != 0)
return cipher->blockDecode( buf, size, _iv64, key );
if (buf[i] != 0) return cipher->blockDecode(buf, size, _iv64, key);
return true;
} else
@ -389,29 +327,21 @@ bool CipherFileIO::blockRead( unsigned char *buf, int size,
}
bool CipherFileIO::streamRead(unsigned char *buf, int size,
uint64_t _iv64 ) const
{
uint64_t _iv64) const {
if (fsConfig->reverseEncryption)
return cipher->streamEncode(buf, size, _iv64, key);
else
return cipher->streamDecode(buf, size, _iv64, key);
}
int CipherFileIO::truncate( off_t size )
{
int CipherFileIO::truncate(off_t size) {
int res = 0;
if(!haveHeader)
{
if (!haveHeader) {
res = BlockFileIO::truncateBase(size, base.get());
} else
{
if(0 == fileIV)
{
} else {
if (0 == fileIV) {
// empty file.. create the header..
if( !base->isWritable() )
{
if (!base->isWritable()) {
// open for write..
int newFlags = lastFlags | O_RDWR;
if (base->open(newFlags) < 0)
@ -424,14 +354,9 @@ int CipherFileIO::truncate( off_t size )
// the wrong size..
res = BlockFileIO::truncateBase(size, 0);
if(res == 0)
base->truncate( size + HEADER_SIZE );
if (res == 0) base->truncate(size + HEADER_SIZE);
}
return res;
}
bool CipherFileIO::isWritable() const
{
return base->isWritable();
}
bool CipherFileIO::isWritable() const { return base->isWritable(); }

View File

@ -34,11 +34,9 @@ class Cipher;
Uses BlockFileIO to handle the block scatter / gather issues.
*/
class CipherFileIO : public BlockFileIO
{
class CipherFileIO : public BlockFileIO {
public:
CipherFileIO( const shared_ptr<FileIO> &base,
const FSConfigPtr &cfg);
CipherFileIO(const shared_ptr<FileIO> &base, const FSConfigPtr &cfg);
virtual ~CipherFileIO();
virtual rel::Interface interface() const;
@ -62,14 +60,10 @@ private:
void initHeader();
bool writeHeader();
bool blockRead( unsigned char *buf, int size,
uint64_t iv64 ) const;
bool streamRead( unsigned char *buf, int size,
uint64_t iv64 ) const;
bool blockWrite( unsigned char *buf, int size,
uint64_t iv64 ) const;
bool streamWrite( unsigned char *buf, int size,
uint64_t iv64 ) const;
bool blockRead(unsigned char *buf, int size, uint64_t iv64) const;
bool streamRead(unsigned char *buf, int size, uint64_t iv64) const;
bool blockWrite(unsigned char *buf, int size, uint64_t iv64) const;
bool streamWrite(unsigned char *buf, int size, uint64_t iv64) const;
shared_ptr<FileIO> base;

View File

@ -20,11 +20,6 @@
#include "CipherKey.h"
AbstractCipherKey::AbstractCipherKey()
{
}
AbstractCipherKey::~AbstractCipherKey()
{
}
AbstractCipherKey::AbstractCipherKey() {}
AbstractCipherKey::~AbstractCipherKey() {}

View File

@ -23,8 +23,7 @@
#include "shared_ptr.h"
class AbstractCipherKey
{
class AbstractCipherKey {
public:
AbstractCipherKey();
virtual ~AbstractCipherKey();
@ -33,4 +32,3 @@ public:
typedef shared_ptr<AbstractCipherKey> CipherKey;
#endif

View File

@ -28,44 +28,33 @@
#include <unistd.h>
#include <cstring>
using namespace std;
using namespace rlog;
ConfigReader::ConfigReader() {}
ConfigReader::ConfigReader()
{
}
ConfigReader::~ConfigReader()
{
}
ConfigReader::~ConfigReader() {}
// read the entire file into a ConfigVar instance and then use that to decode
// into mapped variables.
bool
ConfigReader::load(const char *fileName)
{
bool ConfigReader::load(const char *fileName) {
struct stat stbuf;
memset(&stbuf, 0, sizeof(struct stat));
if( lstat( fileName, &stbuf ) != 0)
return false;
if (lstat(fileName, &stbuf) != 0) return false;
int size = stbuf.st_size;
int fd = open(fileName, O_RDONLY);
if(fd < 0)
return false;
if (fd < 0) return false;
char *buf = new char[size];
int res = ::read(fd, buf, size);
close(fd);
if( res != size )
{
rWarning("Partial read of config file, expecting %i bytes, got %i",
size, res);
if (res != size) {
rWarning("Partial read of config file, expecting %i bytes, got %i", size,
res);
delete[] buf;
return false;
}
@ -77,21 +66,17 @@ ConfigReader::load(const char *fileName)
return loadFromVar(in);
}
bool
ConfigReader::loadFromVar(ConfigVar &in)
{
bool ConfigReader::loadFromVar(ConfigVar &in) {
in.resetOffset();
// parse.
int numEntries = in.readInt();
for(int i=0; i<numEntries; ++i)
{
for (int i = 0; i < numEntries; ++i) {
string key, value;
in >> key >> value;
if(key.length() == 0)
{
if (key.length() == 0) {
rError("Invalid key encoding in buffer");
return false;
}
@ -102,24 +87,19 @@ ConfigReader::loadFromVar(ConfigVar &in)
return true;
}
bool
ConfigReader::save(const char *fileName) const
{
bool ConfigReader::save(const char *fileName) const {
// write everything to a ConfigVar, then output to disk
ConfigVar out = toVar();
int fd = ::open(fileName, O_RDWR | O_CREAT, 0640);
if(fd >= 0)
{
if (fd >= 0) {
int retVal = ::write(fd, out.buffer(), out.size());
close(fd);
if(retVal != out.size())
{
if (retVal != out.size()) {
rError("Error writing to config file %s", fileName);
return false;
}
} else
{
} else {
rError("Unable to open or create file %s", fileName);
return false;
}
@ -127,15 +107,12 @@ ConfigReader::save(const char *fileName) const
return true;
}
ConfigVar
ConfigReader::toVar() const
{
ConfigVar ConfigReader::toVar() const {
// write everything to a ConfigVar, then output to disk
ConfigVar out;
out.writeInt(vars.size());
map<string, ConfigVar>::const_iterator it;
for(it = vars.begin(); it != vars.end(); ++it)
{
for (it = vars.begin(); it != vars.end(); ++it) {
out.writeInt(it->first.size());
out.write((unsigned char *)it->first.data(), it->first.size());
out.writeInt(it->second.size());
@ -145,8 +122,7 @@ ConfigReader::toVar() const
return out;
}
ConfigVar ConfigReader::operator[] ( const std::string &varName ) const
{
ConfigVar ConfigReader::operator[](const std::string &varName) const {
// read only
map<string, ConfigVar>::const_iterator it = vars.find(varName);
if (it == vars.end())
@ -155,8 +131,6 @@ ConfigVar ConfigReader::operator[] ( const std::string &varName ) const
return it->second;
}
ConfigVar &ConfigReader::operator[] ( const std::string &varName )
{
ConfigVar &ConfigReader::operator[](const std::string &varName) {
return vars[varName];
}

View File

@ -43,8 +43,7 @@
ConfigReader cfg;
cfg["cipher"] << cipher->interface();
*/
class ConfigReader
{
class ConfigReader {
public:
ConfigReader();
~ConfigReader();
@ -62,5 +61,4 @@ private:
std::map<std::string, ConfigVar> vars;
};
#endif

View File

@ -26,38 +26,21 @@
using namespace rlog;
#ifndef MIN
inline int MIN(int a, int b)
{
return (a < b) ? a : b;
}
inline int MIN(int a, int b) { return (a < b) ? a : b; }
#endif
ConfigVar::ConfigVar() : pd(new ConfigVarData) { pd->offset = 0; }
ConfigVar::ConfigVar()
: pd( new ConfigVarData )
{
pd->offset = 0;
}
ConfigVar::ConfigVar(const std::string &buf)
: pd( new ConfigVarData )
{
ConfigVar::ConfigVar(const std::string &buf) : pd(new ConfigVarData) {
pd->buffer = buf;
pd->offset = 0;
}
ConfigVar::ConfigVar(const ConfigVar &src)
{
pd = src.pd;
}
ConfigVar::ConfigVar(const ConfigVar &src) { pd = src.pd; }
ConfigVar::~ConfigVar()
{
pd.reset();
}
ConfigVar::~ConfigVar() { pd.reset(); }
ConfigVar & ConfigVar::operator = (const ConfigVar &src)
{
ConfigVar &ConfigVar::operator=(const ConfigVar &src) {
if (src.pd == pd)
return *this;
else
@ -66,30 +49,22 @@ ConfigVar & ConfigVar::operator = (const ConfigVar &src)
return *this;
}
void ConfigVar::resetOffset()
{
pd->offset = 0;
}
void ConfigVar::resetOffset() { pd->offset = 0; }
int ConfigVar::read(unsigned char *buffer_, int bytes) const
{
int ConfigVar::read(unsigned char *buffer_, int bytes) const {
int toCopy = MIN(bytes, pd->buffer.size() - pd->offset);
if(toCopy > 0)
memcpy( buffer_, pd->buffer.data() + pd->offset, toCopy );
if (toCopy > 0) memcpy(buffer_, pd->buffer.data() + pd->offset, toCopy);
pd->offset += toCopy;
return toCopy;
}
int ConfigVar::write(const unsigned char *data, int bytes)
{
if(pd->buffer.size() == (unsigned int)pd->offset)
{
int ConfigVar::write(const unsigned char *data, int bytes) {
if (pd->buffer.size() == (unsigned int)pd->offset) {
pd->buffer.append((const char *)data, bytes);
} else
{
} else {
pd->buffer.insert(pd->offset, (const char *)data, bytes);
}
@ -98,31 +73,19 @@ int ConfigVar::write(const unsigned char *data, int bytes)
return bytes;
}
int ConfigVar::size() const
{
return pd->buffer.size();
}
int ConfigVar::size() const { return pd->buffer.size(); }
const char *ConfigVar::buffer() const
{
return pd->buffer.data();
}
const char *ConfigVar::buffer() const { return pd->buffer.data(); }
int ConfigVar::at() const
{
return pd->offset;
}
int ConfigVar::at() const { return pd->offset; }
void ConfigVar::writeString(const char *data, int bytes)
{
void ConfigVar::writeString(const char *data, int bytes) {
writeInt(bytes);
write((const unsigned char *)data, bytes);
}
// convert integer to BER encoded integer
void ConfigVar::writeInt(int val)
{
void ConfigVar::writeInt(int val) {
// we can represent 7 bits per char output, so a 32bit number may take up
// to 5 bytes.
// first byte: 0x0000007f 0111,1111
@ -141,14 +104,12 @@ void ConfigVar::writeInt(int val)
// find the starting point - we only need to output starting at the most
// significant non-zero digit..
int start = 0;
while(digit[start] == 0x80)
++start;
while (digit[start] == 0x80) ++start;
write(digit + start, 5 - start);
}
int ConfigVar::readInt() const
{
int ConfigVar::readInt() const {
const unsigned char *buf = (const unsigned char *)buffer();
int bytes = this->size();
int offset = at();
@ -157,8 +118,7 @@ int ConfigVar::readInt() const
rAssert(offset < bytes);
do
{
do {
unsigned char tmp = buf[offset++];
highBitSet = tmp & 0x80;
@ -173,8 +133,7 @@ int ConfigVar::readInt() const
return value;
}
int ConfigVar::readInt( int defaultValue ) const
{
int ConfigVar::readInt(int defaultValue) const {
int bytes = this->size();
int offset = at();
@ -184,69 +143,58 @@ int ConfigVar::readInt( int defaultValue ) const
return readInt();
}
bool ConfigVar::readBool( bool defaultValue ) const
{
bool ConfigVar::readBool(bool defaultValue) const {
int tmp = readInt(defaultValue ? 1 : 0);
return (tmp != 0);
}
ConfigVar & operator << (ConfigVar &src, bool value)
{
ConfigVar &operator<<(ConfigVar &src, bool value) {
src.writeInt(value ? 1 : 0);
return src;
}
ConfigVar & operator << (ConfigVar &src, int var)
{
ConfigVar &operator<<(ConfigVar &src, int var) {
src.writeInt(var);
return src;
}
ConfigVar & operator << (ConfigVar &src, const std::string &str)
{
ConfigVar &operator<<(ConfigVar &src, const std::string &str) {
src.writeString(str.data(), str.length());
return src;
}
const ConfigVar & operator >> (const ConfigVar &src, bool &result)
{
const ConfigVar &operator>>(const ConfigVar &src, bool &result) {
int tmp = src.readInt();
result = (tmp != 0);
return src;
}
const ConfigVar & operator >> (const ConfigVar &src, int &result)
{
const ConfigVar &operator>>(const ConfigVar &src, int &result) {
result = src.readInt();
return src;
}
const ConfigVar & operator >> (const ConfigVar &src, std::string &result)
{
const ConfigVar &operator>>(const ConfigVar &src, std::string &result) {
int length = src.readInt();
// rAssert(length > 0);
int readLen;
unsigned char tmpBuf[32];
if(length > (int)sizeof(tmpBuf))
{
if (length > (int)sizeof(tmpBuf)) {
unsigned char *ptr = new unsigned char[length];
readLen = src.read(ptr, length);
result.assign((char *)ptr, length);
delete[] ptr;
} else
{
} else {
readLen = src.read(tmpBuf, length);
result.assign((char *)tmpBuf, length);
}
if(readLen != length)
{
if (readLen != length) {
rDebug("string encoded as size %i bytes, read %i", length, readLen);
}
rAssert(readLen == length);
return src;
}

View File

@ -24,10 +24,8 @@
#include <string>
#include "shared_ptr.h"
class ConfigVar
{
struct ConfigVarData
{
class ConfigVar {
struct ConfigVarData {
std::string buffer;
int offset;
};
@ -78,4 +76,3 @@ const ConfigVar & operator >> (const ConfigVar &, int &);
const ConfigVar &operator>>(const ConfigVar &, std::string &str);
#endif

View File

@ -29,8 +29,7 @@
using namespace rel;
using namespace rlog;
EncFS_Context::EncFS_Context()
{
EncFS_Context::EncFS_Context() {
pthread_cond_init(&wakeupCond, 0);
pthread_mutex_init(&wakeupMutex, 0);
pthread_mutex_init(&contextMutex, 0);
@ -38,8 +37,7 @@ EncFS_Context::EncFS_Context()
usageCount = 0;
}
EncFS_Context::~EncFS_Context()
{
EncFS_Context::~EncFS_Context() {
pthread_mutex_destroy(&contextMutex);
pthread_mutex_destroy(&wakeupMutex);
pthread_cond_destroy(&wakeupCond);
@ -48,22 +46,18 @@ EncFS_Context::~EncFS_Context()
openFiles.clear();
}
shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode)
{
shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode) {
shared_ptr<DirNode> ret;
do
{
do {
{
Lock lock(contextMutex);
ret = root;
++usageCount;
}
if(!ret)
{
if (!ret) {
int res = remountFS(this);
if(res != 0)
{
if (res != 0) {
*errCode = res;
break;
}
@ -73,22 +67,16 @@ shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode)
return ret;
}
void EncFS_Context::setRoot(const shared_ptr<DirNode> &r)
{
void EncFS_Context::setRoot(const shared_ptr<DirNode> &r) {
Lock lock(contextMutex);
root = r;
if(r)
rootCipherDir = r->rootDirectory();
if (r) rootCipherDir = r->rootDirectory();
}
bool EncFS_Context::isMounted()
{
return root;
}
bool EncFS_Context::isMounted() { return root; }
int EncFS_Context::getAndResetUsageCounter()
{
int EncFS_Context::getAndResetUsageCounter() {
Lock lock(contextMutex);
int count = usageCount;
@ -97,51 +85,43 @@ int EncFS_Context::getAndResetUsageCounter()
return count;
}
int EncFS_Context::openFileCount() const
{
int EncFS_Context::openFileCount() const {
Lock lock(contextMutex);
return openFiles.size();
}
shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path)
{
shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(path));
if(it != openFiles.end())
{
if (it != openFiles.end()) {
// all the items in the set point to the same node.. so just use the
// first
return (*it->second.begin())->node;
} else
{
} else {
return shared_ptr<FileNode>();
}
}
void EncFS_Context::renameNode(const char *from, const char *to)
{
void EncFS_Context::renameNode(const char *from, const char *to) {
Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(from));
if(it != openFiles.end())
{
if (it != openFiles.end()) {
std::set<Placeholder *> val = it->second;
openFiles.erase(it);
openFiles[std::string(to)] = val;
}
}
shared_ptr<FileNode> EncFS_Context::getNode(void *pl)
{
shared_ptr<FileNode> EncFS_Context::getNode(void *pl) {
Placeholder *ph = (Placeholder *)pl;
return ph->node;
}
void *EncFS_Context::putNode(const char *path,
const shared_ptr<FileNode> &node)
{
const shared_ptr<FileNode> &node) {
Lock lock(contextMutex);
Placeholder *pl = new Placeholder(node);
openFiles[std::string(path)].insert(pl);
@ -149,8 +129,7 @@ void *EncFS_Context::putNode(const char *path,
return (void *)pl;
}
void EncFS_Context::eraseNode(const char *path, void *pl)
{
void EncFS_Context::eraseNode(const char *path, void *pl) {
Lock lock(contextMutex);
Placeholder *ph = (Placeholder *)pl;
@ -163,8 +142,7 @@ void EncFS_Context::eraseNode(const char *path, void *pl)
rAssert(rmCount == 1);
// if no more references to this file, remove the record all together
if(it->second.empty())
{
if (it->second.empty()) {
// attempts to make use of shallow copy to clear memory used to hold
// unencrypted filenames.. not sure this does any good..
std::string storedName = it->first;
@ -174,4 +152,3 @@ void EncFS_Context::eraseNode(const char *path, void *pl)
delete ph;
}

View File

@ -37,8 +37,7 @@ struct EncFS_Opts;
class FileNode;
class DirNode;
class EncFS_Context
{
class EncFS_Context {
public:
EncFS_Context();
~EncFS_Context();
@ -82,20 +81,17 @@ private:
* release() is called. shared_ptr then does our reference counting for
* us.
*/
struct Placeholder
{
struct Placeholder {
shared_ptr<FileNode> node;
Placeholder(const shared_ptr<FileNode> &ptr) : node(ptr) {}
};
// set of open files, indexed by path
#ifdef USE_HASHMAP
typedef __gnu_cxx::hash_map<std::string,
std::set<Placeholder*> > FileMap;
// set of open files, indexed by path
typedef __gnu_cxx::hash_map<std::string, std::set<Placeholder *> > FileMap;
#else
typedef std::map< std::string,
std::set<Placeholder*> > FileMap;
typedef std::map<std::string, std::set<Placeholder *> > FileMap;
#endif
mutable pthread_mutex_t contextMutex;
@ -108,4 +104,3 @@ private:
int remountFS(EncFS_Context *ctx);
#endif

View File

@ -50,33 +50,19 @@ using namespace rlog;
static RLogChannel *Info = DEF_CHANNEL("info/DirNode", Log_Info);
class DirDeleter
{
class DirDeleter {
public:
void operator () ( DIR *d )
{
::closedir( d );
}
void operator()(DIR *d) { ::closedir(d); }
};
DirTraverse::DirTraverse(const shared_ptr<DIR> &_dirPtr,
uint64_t _iv, const shared_ptr<NameIO> &_naming)
: dir( _dirPtr )
, iv( _iv )
, naming( _naming )
{
}
DirTraverse::DirTraverse(const shared_ptr<DIR> &_dirPtr, uint64_t _iv,
const shared_ptr<NameIO> &_naming)
: dir(_dirPtr), iv(_iv), naming(_naming) {}
DirTraverse::DirTraverse(const DirTraverse &src)
: dir( src.dir )
, iv( src.iv )
, naming( src.naming )
{
}
: dir(src.dir), iv(src.iv), naming(src.naming) {}
DirTraverse &DirTraverse::operator = (const DirTraverse &src)
{
DirTraverse &DirTraverse::operator=(const DirTraverse &src) {
dir = src.dir;
iv = src.iv;
naming = src.naming;
@ -84,23 +70,18 @@ DirTraverse &DirTraverse::operator = (const DirTraverse &src)
return *this;
}
DirTraverse::~DirTraverse()
{
DirTraverse::~DirTraverse() {
dir.reset();
iv = 0;
naming.reset();
}
static
bool _nextName(struct dirent *&de, const shared_ptr<DIR> &dir,
int *fileType, ino_t *inode)
{
static bool _nextName(struct dirent *&de, const shared_ptr<DIR> &dir,
int *fileType, ino_t *inode) {
de = ::readdir(dir.get());
if(de)
{
if(fileType)
{
if (de) {
if (fileType) {
#if defined(_DIRENT_HAVE_D_TYPE) || defined(__FreeBSD__) || defined(__APPLE__)
*fileType = de->d_type;
#else
@ -108,29 +89,22 @@ bool _nextName(struct dirent *&de, const shared_ptr<DIR> &dir,
*fileType = 0;
#endif
}
if(inode)
*inode = de->d_ino;
if (inode) *inode = de->d_ino;
return true;
} else
{
if(fileType)
*fileType = 0;
} else {
if (fileType) *fileType = 0;
return false;
}
}
std::string DirTraverse::nextPlaintextName(int *fileType, ino_t *inode)
{
std::string DirTraverse::nextPlaintextName(int *fileType, ino_t *inode) {
struct dirent *de = 0;
while(_nextName(de, dir, fileType, inode))
{
try
{
while (_nextName(de, dir, fileType, inode)) {
try {
uint64_t localIv = iv;
return naming->decodePath(de->d_name, &localIv);
} catch ( rlog::Error &ex )
{
}
catch (rlog::Error &ex) {
// .. .problem decoding, ignore it and continue on to next name..
rDebug("error decoding filename: %s", de->d_name);
}
@ -139,19 +113,16 @@ std::string DirTraverse::nextPlaintextName(int *fileType, ino_t *inode)
return string();
}
std::string DirTraverse::nextInvalid()
{
std::string DirTraverse::nextInvalid() {
struct dirent *de = 0;
// find the first name which produces a decoding error...
while(_nextName(de, dir, (int*)0, (ino_t*)0))
{
try
{
while (_nextName(de, dir, (int *)0, (ino_t *)0)) {
try {
uint64_t localIv = iv;
naming->decodePath(de->d_name, &localIv);
continue;
} catch( rlog::Error &ex )
{
}
catch (rlog::Error &ex) {
return string(de->d_name);
}
}
@ -159,8 +130,7 @@ std::string DirTraverse::nextInvalid()
return string();
}
struct RenameEl
{
struct RenameEl {
// ciphertext names
string oldCName;
string newCName; // intermediate name (not final cname)
@ -172,8 +142,7 @@ struct RenameEl
bool isDirectory;
};
class RenameOp
{
class RenameOp {
private:
DirNode *dn;
shared_ptr<list<RenameEl> > renameList;
@ -181,74 +150,55 @@ private:
public:
RenameOp(DirNode *_dn, const shared_ptr<list<RenameEl> > &_renameList)
: dn(_dn), renameList(_renameList)
{
: dn(_dn), renameList(_renameList) {
last = renameList->begin();
}
RenameOp(const RenameOp &src)
: dn(src.dn)
, renameList(src.renameList)
, last(src.last)
{
}
: dn(src.dn), renameList(src.renameList), last(src.last) {}
~RenameOp();
operator bool () const
{
return renameList;
}
operator bool() const { return renameList; }
bool apply();
void undo();
};
RenameOp::~RenameOp()
{
if(renameList)
{
RenameOp::~RenameOp() {
if (renameList) {
// got a bunch of decoded filenames sitting in memory.. do a little
// cleanup before leaving..
list<RenameEl>::iterator it;
for(it = renameList->begin(); it != renameList->end(); ++it)
{
for (it = renameList->begin(); it != renameList->end(); ++it) {
it->oldPName.assign(it->oldPName.size(), ' ');
it->newPName.assign(it->newPName.size(), ' ');
}
}
}
bool RenameOp::apply()
{
try
{
while(last != renameList->end())
{
bool RenameOp::apply() {
try {
while (last != renameList->end()) {
// backing store rename.
rDebug("renaming %s -> %s",
last->oldCName.c_str(), last->newCName.c_str());
rDebug("renaming %s -> %s", last->oldCName.c_str(),
last->newCName.c_str());
struct stat st;
bool preserve_mtime = ::stat(last->oldCName.c_str(), &st) == 0;
// internal node rename..
dn->renameNode( last->oldPName.c_str(),
last->newPName.c_str() );
dn->renameNode(last->oldPName.c_str(), last->newPName.c_str());
// rename on disk..
if(::rename( last->oldCName.c_str(),
last->newCName.c_str() ) == -1)
{
rWarning("Error renaming %s: %s",
last->oldCName.c_str(), strerror( errno ));
dn->renameNode( last->newPName.c_str(),
last->oldPName.c_str(), false );
if (::rename(last->oldCName.c_str(), last->newCName.c_str()) == -1) {
rWarning("Error renaming %s: %s", last->oldCName.c_str(),
strerror(errno));
dn->renameNode(last->newPName.c_str(), last->oldPName.c_str(), false);
return false;
}
if(preserve_mtime)
{
if (preserve_mtime) {
struct utimbuf ut;
ut.actime = st.st_atime;
ut.modtime = st.st_mtime;
@ -259,19 +209,17 @@ bool RenameOp::apply()
}
return true;
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
err.log(_RLWarningChannel);
return false;
}
}
void RenameOp::undo()
{
void RenameOp::undo() {
rDebug("in undoRename");
if(last == renameList->begin())
{
if (last == renameList->begin()) {
rDebug("nothing to undo");
return; // nothing to undo
}
@ -281,20 +229,17 @@ void RenameOp::undo()
int undoCount = 0;
list<RenameEl>::const_iterator it = last;
while( it != renameList->begin() )
{
while (it != renameList->begin()) {
--it;
rDebug("undo: renaming %s -> %s",
it->newCName.c_str(), it->oldCName.c_str());
rDebug("undo: renaming %s -> %s", it->newCName.c_str(),
it->oldCName.c_str());
::rename(it->newCName.c_str(), it->oldCName.c_str());
try
{
dn->renameNode( it->newPName.c_str(),
it->oldPName.c_str(), false );
} catch( rlog::Error &err )
{
try {
dn->renameNode(it->newPName.c_str(), it->oldPName.c_str(), false);
}
catch (rlog::Error &err) {
err.log(_RLWarningChannel);
// continue on anyway...
}
@ -304,10 +249,8 @@ void RenameOp::undo()
rWarning("Undo rename count: %i", undoCount);
}
DirNode::DirNode(EncFS_Context *_ctx,
const string &sourceDir,
const FSConfigPtr &_config)
{
DirNode::DirNode(EncFS_Context *_ctx, const string &sourceDir,
const FSConfigPtr &_config) {
pthread_mutex_init(&mutex, 0);
Lock _lock(mutex);
@ -318,67 +261,47 @@ DirNode::DirNode(EncFS_Context *_ctx,
// make sure rootDir ends in '/', so that we can form a path by appending
// the rest..
if( rootDir[ rootDir.length()-1 ] != '/' )
rootDir.append( 1, '/');
if (rootDir[rootDir.length() - 1] != '/') rootDir.append(1, '/');
naming = fsConfig->nameCoding;
}
DirNode::~DirNode()
{
}
DirNode::~DirNode() {}
bool
DirNode::hasDirectoryNameDependency() const
{
bool DirNode::hasDirectoryNameDependency() const {
return naming ? naming->getChainedNameIV() : false;
}
string
DirNode::rootDirectory()
{
string DirNode::rootDirectory() {
// don't update last access here, otherwise 'du' would cause lastAccess to
// be reset.
// chop off '/' terminator from root dir.
return string(rootDir, 0, rootDir.length() - 1);
}
string
DirNode::cipherPath( const char *plaintextPath )
{
string DirNode::cipherPath(const char *plaintextPath) {
return rootDir + naming->encodePath(plaintextPath);
}
string
DirNode::cipherPathWithoutRoot( const char *plaintextPath )
{
string DirNode::cipherPathWithoutRoot(const char *plaintextPath) {
return naming->encodePath(plaintextPath);
}
string
DirNode::plainPath( const char *cipherPath_ )
{
try
{
if( !strncmp( cipherPath_, rootDir.c_str(),
rootDir.length() ) )
{
string DirNode::plainPath(const char *cipherPath_) {
try {
if (!strncmp(cipherPath_, rootDir.c_str(), rootDir.length())) {
return naming->decodePath(cipherPath_ + rootDir.length());
} else
{
if ( cipherPath_[0] == '+' )
{
} else {
if (cipherPath_[0] == '+') {
// decode as fully qualified path
return string("/") + naming->decodeName( cipherPath_+1,
strlen(cipherPath_+1) );
} else
{
return string("/") +
naming->decodeName(cipherPath_ + 1, strlen(cipherPath_ + 1));
} else {
return naming->decodePath(cipherPath_);
}
}
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("decode err: %s", err.message());
err.log(_RLWarningChannel);
@ -386,22 +309,17 @@ DirNode::plainPath( const char *cipherPath_ )
}
}
string
DirNode::relativeCipherPath( const char *plaintextPath )
{
try
{
if(plaintextPath[0] == '/')
{
string DirNode::relativeCipherPath(const char *plaintextPath) {
try {
if (plaintextPath[0] == '/') {
// mark with '+' to indicate special decoding..
return string("+") + naming->encodeName(plaintextPath+1,
strlen(plaintextPath+1));
} else
{
return string("+") +
naming->encodeName(plaintextPath + 1, strlen(plaintextPath + 1));
} else {
return naming->encodePath(plaintextPath);
}
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("encode err: %s", err.message());
err.log(_RLWarningChannel);
@ -409,29 +327,24 @@ DirNode::relativeCipherPath( const char *plaintextPath )
}
}
DirTraverse DirNode::openDir(const char *plaintextPath)
{
DirTraverse DirNode::openDir(const char *plaintextPath) {
string cyName = rootDir + naming->encodePath(plaintextPath);
// rDebug("openDir on %s", cyName.c_str() );
DIR *dir = ::opendir(cyName.c_str());
if(dir == NULL)
{
if (dir == NULL) {
rDebug("opendir error %s", strerror(errno));
return DirTraverse(shared_ptr<DIR>(), 0, shared_ptr<NameIO>());
} else
{
} else {
shared_ptr<DIR> dp(dir, DirDeleter());
uint64_t iv = 0;
// if we're using chained IV mode, then compute the IV at this
// directory level..
try
{
if( naming->getChainedNameIV() )
naming->encodePath( plaintextPath, &iv );
} catch( rlog::Error &err )
{
try {
if (naming->getChainedNameIV()) naming->encodePath(plaintextPath, &iv);
}
catch (rlog::Error &err) {
rError("encode err: %s", err.message());
err.log(_RLWarningChannel);
}
@ -439,9 +352,8 @@ DirTraverse DirNode::openDir(const char *plaintextPath)
}
}
bool DirNode::genRenameList( list<RenameEl> &renameList,
const char *fromP, const char *toP )
{
bool DirNode::genRenameList(list<RenameEl> &renameList, const char *fromP,
const char *toP) {
uint64_t fromIV = 0, toIV = 0;
// compute the IV for both paths
@ -452,43 +364,37 @@ bool DirNode::genRenameList( list<RenameEl> &renameList,
string sourcePath = rootDir + fromCPart;
// ok..... we wish it was so simple.. should almost never happen
if(fromIV == toIV)
return true;
if (fromIV == toIV) return true;
// generate the real destination path, where we expect to find the files..
rDebug("opendir %s", sourcePath.c_str());
shared_ptr<DIR> dir = shared_ptr<DIR>(
opendir( sourcePath.c_str() ), DirDeleter() );
if(!dir)
return false;
shared_ptr<DIR> dir =
shared_ptr<DIR>(opendir(sourcePath.c_str()), DirDeleter());
if (!dir) return false;
struct dirent *de = NULL;
while((de = ::readdir( dir.get() )) != NULL)
{
while ((de = ::readdir(dir.get())) != NULL) {
// decode the name using the oldIV
uint64_t localIV = fromIV;
string plainName;
if ((de->d_name[0] == '.') &&
((de->d_name[1] == '\0')
|| ((de->d_name[1] == '.') && (de->d_name[2] == '\0'))))
{
((de->d_name[1] == '\0') ||
((de->d_name[1] == '.') && (de->d_name[2] == '\0')))) {
// skip "." and ".."
continue;
}
try
{
try {
plainName = naming->decodePath(de->d_name, &localIV);
} catch( rlog::Error &ex )
{
}
catch (rlog::Error &ex) {
// if filename can't be decoded, then ignore it..
continue;
}
// any error in the following will trigger a rename failure.
try
{
try {
// re-encode using the new IV..
localIV = toIV;
string newName = naming->encodePath(plainName.c_str(), &localIV);
@ -505,8 +411,7 @@ bool DirNode::genRenameList( list<RenameEl> &renameList,
bool isDir;
#if defined(_DIRENT_HAVE_D_TYPE)
if(de->d_type != DT_UNKNOWN)
{
if (de->d_type != DT_UNKNOWN) {
isDir = (de->d_type == DT_DIR);
} else
#endif
@ -516,25 +421,20 @@ bool DirNode::genRenameList( list<RenameEl> &renameList,
ren.isDirectory = isDir;
if(isDir)
{
if (isDir) {
// recurse.. We want to add subdirectory elements before the
// parent, as that is the logical rename order..
if(!genRenameList( renameList,
ren.oldPName.c_str(),
ren.newPName.c_str()))
{
if (!genRenameList(renameList, ren.oldPName.c_str(),
ren.newPName.c_str())) {
return false;
}
}
rDebug("adding file %s to rename list",
oldFull.c_str());
rDebug("adding file %s to rename list", oldFull.c_str());
renameList.push_back(ren);
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
// We can't convert this name, because we don't have a valid IV for
// it (or perhaps a valid key).. It will be inaccessible..
rWarning("Aborting rename: error on file: %s",
@ -550,7 +450,6 @@ bool DirNode::genRenameList( list<RenameEl> &renameList,
return true;
}
/*
A bit of a pain.. If a directory is renamed in a filesystem with
directory initialization vector chaining, then we have to recursively
@ -559,24 +458,19 @@ bool DirNode::genRenameList( list<RenameEl> &renameList,
Returns a list of renamed items on success, a null list on failure.
*/
shared_ptr<RenameOp>
DirNode::newRenameOp( const char *fromP, const char *toP )
{
shared_ptr<RenameOp> DirNode::newRenameOp(const char *fromP, const char *toP) {
// Do the rename in two stages to avoid chasing our tail
// Undo everything if we encounter an error!
shared_ptr<list<RenameEl> > renameList(new list<RenameEl>);
if(!genRenameList( *renameList.get(), fromP, toP ))
{
if (!genRenameList(*renameList.get(), fromP, toP)) {
rWarning("Error during generation of recursive rename list");
return shared_ptr<RenameOp>();
} else
return shared_ptr<RenameOp>(new RenameOp(this, renameList));
}
int DirNode::mkdir(const char *plaintextPath, mode_t mode,
uid_t uid, gid_t gid)
{
int DirNode::mkdir(const char *plaintextPath, mode_t mode, uid_t uid,
gid_t gid) {
string cyName = rootDir + naming->encodePath(plaintextPath);
rAssert(!cyName.empty());
@ -585,23 +479,18 @@ int DirNode::mkdir(const char *plaintextPath, mode_t mode,
// if uid or gid are set, then that should be the directory owner
int olduid = -1;
int oldgid = -1;
if(uid != 0)
olduid = setfsuid( uid );
if(gid != 0)
oldgid = setfsgid( gid );
if (uid != 0) olduid = setfsuid(uid);
if (gid != 0) oldgid = setfsgid(gid);
int res = ::mkdir(cyName.c_str(), mode);
if(olduid >= 0)
setfsuid( olduid );
if(oldgid >= 0)
setfsgid( oldgid );
if (olduid >= 0) setfsuid(olduid);
if (oldgid >= 0) setfsgid(oldgid);
if(res == -1)
{
if (res == -1) {
int eno = errno;
rWarning("mkdir error on %s mode %i: %s", cyName.c_str(),
mode, strerror(eno));
rWarning("mkdir error on %s mode %i: %s", cyName.c_str(), mode,
strerror(eno));
res = -eno;
} else
res = 0;
@ -609,9 +498,7 @@ int DirNode::mkdir(const char *plaintextPath, mode_t mode,
return res;
}
int
DirNode::rename( const char *fromPlaintext, const char *toPlaintext )
{
int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
Lock _lock(mutex);
string fromCName = rootDir + naming->encodePath(fromPlaintext);
@ -624,15 +511,12 @@ DirNode::rename( const char *fromPlaintext, const char *toPlaintext )
shared_ptr<FileNode> toNode = findOrCreate(toPlaintext);
shared_ptr<RenameOp> renameOp;
if( hasDirectoryNameDependency() && isDirectory( fromCName.c_str() ))
{
if (hasDirectoryNameDependency() && isDirectory(fromCName.c_str())) {
rLog(Info, "recursive rename begin");
renameOp = newRenameOp(fromPlaintext, toPlaintext);
if(!renameOp || !renameOp->apply())
{
if(renameOp)
renameOp->undo();
if (!renameOp || !renameOp->apply()) {
if (renameOp) renameOp->undo();
rWarning("rename aborted");
return -EACCES;
@ -641,38 +525,33 @@ DirNode::rename( const char *fromPlaintext, const char *toPlaintext )
}
int res = 0;
try
{
try {
struct stat st;
bool preserve_mtime = ::stat(fromCName.c_str(), &st) == 0;
renameNode(fromPlaintext, toPlaintext);
res = ::rename(fromCName.c_str(), toCName.c_str());
if(res == -1)
{
if (res == -1) {
// undo
res = -errno;
renameNode(toPlaintext, fromPlaintext, false);
if(renameOp)
renameOp->undo();
} else if(preserve_mtime)
{
if (renameOp) renameOp->undo();
} else if (preserve_mtime) {
struct utimbuf ut;
ut.actime = st.st_atime;
ut.modtime = st.st_mtime;
::utime(toCName.c_str(), &ut);
}
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
// exception from renameNode, just show the error and continue..
err.log(_RLWarningChannel);
res = -EIO;
}
if(res != 0)
{
if (res != 0) {
rLog(Info, "rename failed: %s", strerror(errno));
res = -errno;
}
@ -680,8 +559,7 @@ DirNode::rename( const char *fromPlaintext, const char *toPlaintext )
return res;
}
int DirNode::link( const char *from, const char *to )
{
int DirNode::link(const char *from, const char *to) {
Lock _lock(mutex);
string fromCName = rootDir + naming->encodePath(from);
@ -693,11 +571,9 @@ 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->externalIVChaining) {
rLog(Info, "hard links not supported with external IV chaining!");
} else
{
} else {
res = ::link(fromCName.c_str(), toCName.c_str());
if (res == -1)
res = -errno;
@ -712,30 +588,24 @@ int DirNode::link( const char *from, const char *to )
The node is keyed by filename, so a rename means the internal node names
must be changed.
*/
shared_ptr<FileNode> DirNode::renameNode( const char *from, const char *to )
{
shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to) {
return renameNode(from, to, true);
}
shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to,
bool forwardMode )
{
bool forwardMode) {
shared_ptr<FileNode> node = findOrCreate(from);
if(node)
{
if (node) {
uint64_t newIV = 0;
string cname = rootDir + naming->encodePath(to, &newIV);
rLog(Info, "renaming internal node %s -> %s",
node->cipherName(), cname.c_str());
rLog(Info, "renaming internal node %s -> %s", node->cipherName(),
cname.c_str());
if(node->setName( to, cname.c_str(), newIV, forwardMode ))
{
if(ctx)
ctx->renameNode( from, to );
} else
{
if (node->setName(to, cname.c_str(), newIV, forwardMode)) {
if (ctx) ctx->renameNode(from, to);
} else {
// rename error! - put it back
rError("renameNode failed");
throw ERROR("Internal node name change failed!");
@ -745,22 +615,17 @@ shared_ptr<FileNode> DirNode::renameNode( const char *from, const char *to,
return node;
}
shared_ptr<FileNode> DirNode::findOrCreate( const char *plainName)
{
shared_ptr<FileNode> DirNode::findOrCreate(const char *plainName) {
shared_ptr<FileNode> node;
if(ctx)
node = ctx->lookupNode( plainName );
if (ctx) node = ctx->lookupNode(plainName);
if(!node)
{
if (!node) {
uint64_t iv = 0;
string cipherName = naming->encodePath(plainName, &iv);
node.reset( new FileNode( this, fsConfig,
plainName,
node.reset(new FileNode(this, fsConfig, plainName,
(rootDir + cipherName).c_str()));
if(fsConfig->config->externalIVChaining)
node->setName(0, 0, iv);
if (fsConfig->config->externalIVChaining) node->setName(0, 0, iv);
rLog(Info, "created FileNode for %s", node->cipherName());
}
@ -768,9 +633,8 @@ shared_ptr<FileNode> DirNode::findOrCreate( const char *plainName)
return node;
}
shared_ptr<FileNode>
DirNode::lookupNode( const char *plainName, const char * requestor )
{
shared_ptr<FileNode> DirNode::lookupNode(const char *plainName,
const char *requestor) {
(void)requestor;
Lock _lock(mutex);
@ -784,10 +648,9 @@ DirNode::lookupNode( const char *plainName, const char * requestor )
node on sucess.. This is done in one step to avoid any race conditions
with the stored state of the file.
*/
shared_ptr<FileNode>
DirNode::openNode( const char *plainName, const char * requestor, int flags,
int *result )
{
shared_ptr<FileNode> DirNode::openNode(const char *plainName,
const char *requestor, int flags,
int *result) {
(void)requestor;
rAssert(result != NULL);
Lock _lock(mutex);
@ -800,28 +663,26 @@ DirNode::openNode( const char *plainName, const char * requestor, int flags,
return shared_ptr<FileNode>();
}
int DirNode::unlink( const char *plaintextName )
{
int DirNode::unlink(const char *plaintextName) {
string cyName = naming->encodePath(plaintextName);
rLog(Info, "unlink %s", cyName.c_str());
Lock _lock(mutex);
int res = 0;
if(ctx && ctx->lookupNode( plaintextName ))
{
if (ctx && ctx->lookupNode(plaintextName)) {
// If FUSE is running with "hard_remove" option where it doesn't
// hide open files for us, then we can't allow an unlink of an open
// file..
rWarning("Refusing to unlink open file: %s, hard_remove option "
"is probably in effect", cyName.c_str() );
rWarning(
"Refusing to unlink open file: %s, hard_remove option "
"is probably in effect",
cyName.c_str());
res = -EBUSY;
} else
{
} else {
string fullName = rootDir + cyName;
res = ::unlink(fullName.c_str());
if(res == -1)
{
if (res == -1) {
res = -errno;
rDebug("unlink error: %s", strerror(errno));
}

View File

@ -40,8 +40,7 @@ class RenameOp;
struct RenameEl;
class EncFS_Context;
class DirTraverse
{
class DirTraverse {
public:
DirTraverse(const shared_ptr<DIR> &dirPtr, uint64_t iv,
const shared_ptr<NameIO> &naming);
@ -63,8 +62,8 @@ public:
The opposite of nextPlaintextName(), as that skips undecodable names..
*/
std::string nextInvalid();
private:
private:
shared_ptr<DIR> dir; // struct DIR
// initialization vector to use. Not very general purpose, but makes it
// more efficient to support filename IV chaining..
@ -74,24 +73,20 @@ private:
inline bool DirTraverse::valid() const { return dir.get() != 0; }
#ifdef USE_HASHMAP
namespace __gnu_cxx
{
template<> struct hash<std::string>
{
size_t operator() (const std::string &__s) const
{
namespace __gnu_cxx {
template <>
struct hash<std::string> {
size_t operator()(const std::string &__s) const {
return __stl_hash_string(__s.c_str());
}
};
}
#endif
class DirNode
{
class DirNode {
public:
// sourceDir points to where raw files are stored
DirNode(EncFS_Context *ctx,
const std::string &sourceDir,
DirNode(EncFS_Context *ctx, const std::string &sourceDir,
const FSConfigPtr &config);
~DirNode();
@ -107,7 +102,8 @@ public:
node is not retained. If the open succeeds, then the node is returned.
*/
shared_ptr<FileNode> openNode(const char *plaintextName,
const char *requestor, int flags, int *openResult );
const char *requestor, int flags,
int *openResult);
std::string cipherPath(const char *plaintextPath);
std::string cipherPathWithoutRoot(const char *plaintextPath);
@ -132,8 +128,8 @@ public:
DirTraverse openDir(const char *plainDirName);
// uid and gid are used as the directory owner, only if not zero
int mkdir( const char *plaintextPath, mode_t mode,
uid_t uid = 0, gid_t gid = 0);
int mkdir(const char *plaintextPath, mode_t mode, uid_t uid = 0,
gid_t gid = 0);
int rename(const char *fromPlaintext, const char *toPlaintext);
@ -143,7 +139,6 @@ public:
int idleSeconds();
protected:
/*
notify that a file is being renamed.
This renames the internal node, if any. If the file is not open, then
@ -163,7 +158,6 @@ protected:
shared_ptr<RenameOp> newRenameOp(const char *from, const char *to);
private:
friend class RenameOp;
bool genRenameList(std::list<RenameEl> &list, const char *fromP,

View File

@ -28,8 +28,7 @@
#include "CipherKey.h"
#include "shared_ptr.h"
enum ConfigType
{
enum ConfigType {
Config_None = 0,
Config_Prehistoric,
Config_V3,
@ -42,8 +41,7 @@ struct EncFS_Opts;
class Cipher;
class NameIO;
struct EncFSConfig
{
struct EncFSConfig {
ConfigType cfgType;
std::string creator;
@ -71,10 +69,7 @@ struct EncFSConfig
bool chainedNameIV; // filename IV chaining
bool allowHoles; // allow holes in files (implicit zero blocks)
EncFSConfig()
: keyData()
, salt()
{
EncFSConfig() : keyData(), salt() {
cfgType = Config_None;
subVersion = 0;
blockMACBytes = 0;
@ -111,8 +106,7 @@ private:
std::ostream &operator<<(std::ostream &os, const EncFSConfig &cfg);
std::istream &operator>>(std::istream &os, EncFSConfig &cfg);
struct FSConfig
{
struct FSConfig {
shared_ptr<EncFSConfig> config;
shared_ptr<EncFS_Opts> opts;
@ -129,4 +123,3 @@ struct FSConfig
typedef shared_ptr<FSConfig> FSConfigPtr;
#endif

View File

@ -20,22 +20,13 @@
#include "FileIO.h"
FileIO::FileIO()
{
}
FileIO::FileIO() {}
FileIO::~FileIO()
{
}
FileIO::~FileIO() {}
int FileIO::blockSize() const
{
return 1;
}
int FileIO::blockSize() const { return 1; }
bool FileIO::setIV( uint64_t iv )
{
bool FileIO::setIV(uint64_t iv) {
(void)iv;
return true;
}

View File

@ -27,8 +27,7 @@
#include "Interface.h"
struct IORequest
{
struct IORequest {
off_t offset;
// amount of bytes to read/write.
@ -38,15 +37,9 @@ struct IORequest
IORequest();
};
inline IORequest::IORequest()
: offset(0)
, dataLen(0)
, data(0)
{
}
inline IORequest::IORequest() : offset(0), dataLen(0), data(0) {}
class FileIO
{
class FileIO {
public:
FileIO();
virtual ~FileIO();
@ -77,6 +70,7 @@ public:
virtual int truncate(off_t size) = 0;
virtual bool isWritable() const = 0;
private:
// not implemented..
FileIO(const FileIO &);
@ -84,4 +78,3 @@ private:
};
#endif

View File

@ -66,8 +66,7 @@ using namespace rlog;
static RLogChannel *Info = DEF_CHANNEL("info/FileNode", Log_Info);
FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
const char *plaintextName_, const char *cipherName_)
{
const char *plaintextName_, const char *cipherName_) {
pthread_mutex_init(&mutex, 0);
Lock _lock(mutex);
@ -86,8 +85,7 @@ FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
io = shared_ptr<FileIO>(new MACFileIO(io, fsConfig));
}
FileNode::~FileNode()
{
FileNode::~FileNode() {
// FileNode mutex should be locked before the destructor is called
// pthread_mutex_lock( &mutex );
@ -98,23 +96,13 @@ FileNode::~FileNode()
pthread_mutex_destroy(&mutex);
}
const char *FileNode::cipherName() const
{
return _cname.c_str();
}
const char *FileNode::cipherName() const { return _cname.c_str(); }
const char *FileNode::plaintextName() const
{
return _pname.c_str();
}
const char *FileNode::plaintextName() const { return _pname.c_str(); }
string FileNode::plaintextParent() const
{
return parentDirectory( _pname );
}
string FileNode::plaintextParent() const { return parentDirectory(_pname); }
static bool setIV(const shared_ptr<FileIO> &io, uint64_t iv)
{
static bool setIV(const shared_ptr<FileIO> &io, uint64_t iv) {
struct stat stbuf;
if ((io->getAttr(&stbuf) < 0) || S_ISREG(stbuf.st_mode))
return io->setIV(iv);
@ -123,38 +111,29 @@ static bool setIV(const shared_ptr<FileIO> &io, uint64_t iv)
}
bool FileNode::setName(const char *plaintextName_, const char *cipherName_,
uint64_t iv, bool setIVFirst )
{
uint64_t iv, bool setIVFirst) {
// Lock _lock( mutex );
rDebug("calling setIV on %s", cipherName_);
if(setIVFirst)
{
if(fsConfig->config->externalIVChaining && !setIV(io, iv))
return false;
if (setIVFirst) {
if (fsConfig->config->externalIVChaining && !setIV(io, iv)) return false;
// now change the name..
if(plaintextName_)
this->_pname = plaintextName_;
if(cipherName_)
{
if (plaintextName_) this->_pname = plaintextName_;
if (cipherName_) {
this->_cname = cipherName_;
io->setFileName(cipherName_);
}
} else
{
} else {
std::string oldPName = _pname;
std::string oldCName = _cname;
if(plaintextName_)
this->_pname = plaintextName_;
if(cipherName_)
{
if (plaintextName_) this->_pname = plaintextName_;
if (cipherName_) {
this->_cname = cipherName_;
io->setFileName(cipherName_);
}
if(fsConfig->config->externalIVChaining && !setIV(io, iv))
{
if (fsConfig->config->externalIVChaining && !setIV(io, iv)) {
_pname = oldPName;
_cname = oldCName;
return false;
@ -164,27 +143,22 @@ bool FileNode::setName( const char *plaintextName_, const char *cipherName_,
return true;
}
int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid)
{
int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid) {
Lock _lock(mutex);
int res;
int olduid = -1;
int oldgid = -1;
if(uid != 0)
{
if (uid != 0) {
olduid = setfsuid(uid);
if(olduid == -1)
{
if (olduid == -1) {
rInfo("setfsuid error: %s", strerror(errno));
return -EPERM;
}
}
if(gid != 0)
{
if (gid != 0) {
oldgid = setfsgid(gid);
if(oldgid == -1)
{
if (oldgid == -1) {
rInfo("setfsgid error: %s", strerror(errno));
return -EPERM;
}
@ -197,20 +171,16 @@ int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid)
*/
if (S_ISREG(mode)) {
res = ::open(_cname.c_str(), O_CREAT | O_EXCL | O_WRONLY, mode);
if (res >= 0)
res = ::close( res );
if (res >= 0) res = ::close(res);
} else if (S_ISFIFO(mode))
res = ::mkfifo(_cname.c_str(), mode);
else
res = ::mknod(_cname.c_str(), mode, rdev);
if(olduid >= 0)
setfsuid( olduid );
if(oldgid >= 0)
setfsgid( oldgid );
if (olduid >= 0) setfsuid(olduid);
if (oldgid >= 0) setfsgid(oldgid);
if(res == -1)
{
if (res == -1) {
int eno = errno;
rDebug("mknod error: %s", strerror(eno));
res = -eno;
@ -219,32 +189,28 @@ int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid)
return res;
}
int FileNode::open(int flags) const
{
int FileNode::open(int flags) const {
Lock _lock(mutex);
int res = io->open(flags);
return res;
}
int FileNode::getAttr(struct stat *stbuf) const
{
int FileNode::getAttr(struct stat *stbuf) const {
Lock _lock(mutex);
int res = io->getAttr(stbuf);
return res;
}
off_t FileNode::getSize() const
{
off_t FileNode::getSize() const {
Lock _lock(mutex);
int res = io->getSize();
return res;
}
ssize_t FileNode::read( off_t offset, unsigned char *data, ssize_t size ) const
{
ssize_t FileNode::read(off_t offset, unsigned char *data, ssize_t size) const {
IORequest req;
req.offset = offset;
req.dataLen = size;
@ -255,10 +221,9 @@ ssize_t FileNode::read( off_t offset, unsigned char *data, ssize_t size ) const
return io->read(req);
}
bool FileNode::write(off_t offset, unsigned char *data, ssize_t size)
{
rLog(Info, "FileNode::write offset %" PRIi64 ", data size %i",
offset, (int)size);
bool FileNode::write(off_t offset, unsigned char *data, ssize_t size) {
rLog(Info, "FileNode::write offset %" PRIi64 ", data size %i", offset,
(int)size);
IORequest req;
req.offset = offset;
@ -270,20 +235,17 @@ bool FileNode::write(off_t offset, unsigned char *data, ssize_t size)
return io->write(req);
}
int FileNode::truncate( off_t size )
{
int FileNode::truncate(off_t size) {
Lock _lock(mutex);
return io->truncate(size);
}
int FileNode::sync(bool datasync)
{
int FileNode::sync(bool datasync) {
Lock _lock(mutex);
int fh = io->open(O_RDONLY);
if(fh >= 0)
{
if (fh >= 0) {
int res = -EIO;
#ifdef linux
if (datasync)
@ -297,11 +259,9 @@ int FileNode::sync(bool datasync)
res = fsync(fh);
#endif
if(res == -1)
res = -errno;
if (res == -1) res = -errno;
return res;
} else
return fh;
}

View File

@ -33,12 +33,9 @@ class Cipher;
class FileIO;
class DirNode;
class FileNode
{
class FileNode {
public:
FileNode(DirNode *parent,
const FSConfigPtr &cfg,
const char *plaintextName,
FileNode(DirNode *parent, const FSConfigPtr &cfg, const char *plaintextName,
const char *cipherName);
~FileNode();
@ -50,8 +47,8 @@ public:
// if setIVFirst is true, then the IV is changed before the name is changed
// (default). The reverse is also supported for special cases..
bool setName( const char *plaintextName, const char *cipherName,
uint64_t iv, bool setIVFirst = true);
bool setName(const char *plaintextName, const char *cipherName, uint64_t iv,
bool setIVFirst = true);
// create node
// If uid/gid are not 0, then chown is used change ownership as specified
@ -72,8 +69,8 @@ public:
// datasync or full sync
int sync(bool dataSync);
private:
private:
// doing locking at the FileNode level isn't as efficient as at the
// lowest level of RawFileIO, since that means locks are held longer
// (held during CPU intensive crypto operations!). However it makes it
@ -92,9 +89,6 @@ private:
private:
FileNode(const FileNode &src);
FileNode &operator=(const FileNode &src);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -45,8 +45,7 @@ bool userAllowMkdir(int promptno, const char *dirPath, mode_t mode );
class Cipher;
class DirNode;
struct EncFS_Root
{
struct EncFS_Root {
shared_ptr<Cipher> cipher;
CipherKey volumeKey;
shared_ptr<DirNode> root;
@ -57,15 +56,9 @@ struct EncFS_Root
typedef shared_ptr<EncFS_Root> RootPtr;
enum ConfigMode
{
Config_Prompt,
Config_Standard,
Config_Paranoia
};
enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia };
struct EncFS_Opts
{
struct EncFS_Opts {
std::string rootDir;
bool createIfNotFound; // create filesystem if not found
bool idleTracking; // turn on idle monitoring of filesystem
@ -85,8 +78,7 @@ struct EncFS_Opts
ConfigMode configMode;
EncFS_Opts()
{
EncFS_Opts() {
createIfNotFound = true;
idleTracking = false;
mountOnDemand = false;
@ -118,25 +110,21 @@ class EncFS_Context;
RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts);
RootPtr createV6Config( EncFS_Context *ctx,
const shared_ptr<EncFS_Opts> &opts );
RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts);
void showFSInfo(const shared_ptr<EncFSConfig> &config);
bool readV4Config( const char *configFile,
const shared_ptr<EncFSConfig> &config,
bool readV4Config(const char *configFile, const shared_ptr<EncFSConfig> &config,
struct ConfigInfo *);
bool writeV4Config(const char *configFile,
const shared_ptr<EncFSConfig> &config);
bool readV5Config( const char *configFile,
const shared_ptr<EncFSConfig> &config,
bool readV5Config(const char *configFile, const shared_ptr<EncFSConfig> &config,
struct ConfigInfo *);
bool writeV5Config(const char *configFile,
const shared_ptr<EncFSConfig> &config);
bool readV6Config( const char *configFile,
const shared_ptr<EncFSConfig> &config,
bool readV6Config(const char *configFile, const shared_ptr<EncFSConfig> &config,
struct ConfigInfo *);
bool writeV6Config(const char *configFile,
const shared_ptr<EncFSConfig> &config);

View File

@ -31,39 +31,21 @@ 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 )
{
}
: _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 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 )
{
}
: _name(src._name),
_current(src._current),
_revision(src._revision),
_age(src._age) {}
Interface::Interface()
: _current( 0 )
, _revision( 0 )
, _age( 0 )
{
}
Interface::Interface() : _current(0), _revision(0), _age(0) {}
Interface &Interface::operator = (const Interface &src)
{
Interface &Interface::operator=(const Interface &src) {
_name = src._name;
_current = src._current;
_revision = src._revision;
@ -71,60 +53,30 @@ Interface &Interface::operator = (const Interface &src)
return *this;
}
const std::string & Interface::name() const
{
return _name;
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());
}
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() );
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..
@ -139,8 +91,7 @@ static int sign( int a, int b )
}
#else
// simple, easy to check, unlikely to break due to unforseen events..
static int sign( int a, int b )
{
static int sign(int a, int b) {
if (a < b)
return 0;
else if (a == b)
@ -150,8 +101,7 @@ static int sign( int a, int b )
}
#endif
static int diffSum( const Interface &A, const Interface &B )
{
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());
@ -161,69 +111,54 @@ static int diffSum( const Interface &A, const Interface &B )
const int EqualVersion = (1 * 3 + 1) * 3 + 1;
bool Interface::implements(const Interface &B) const
{
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());
bool Interface::implements(const Interface &B) const {
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());
if( name() != B.name() )
return false;
if (name() != B.name()) return false;
int currentDiff = current() - B.current();
return (currentDiff >= 0 && currentDiff <= age());
}
bool operator < (const Interface &A, const Interface &B)
{
if( 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() )
{
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() )
{
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() )
{
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)
{
ConfigVar &operator<<(ConfigVar &dst, const rel::Interface &iface) {
dst << iface.name() << iface.current() << iface.revision() << iface.age();
return dst;
}
const ConfigVar & operator >> (const ConfigVar &src, Interface &iface)
{
const ConfigVar &operator>>(const ConfigVar &src, Interface &iface) {
src >> iface.name();
src >> iface.current();
src >> iface.revision();
src >> iface.age();
return src;
}

View File

@ -26,13 +26,10 @@
class ConfigVar;
// part of REL library..
namespace rel
{
namespace rel {
class Interface
{
class Interface {
public:
/*!
Version numbers as described by libtool: info://libtool/versioning
Current - the most recent interface api that is implemented.
@ -70,7 +67,6 @@ namespace rel
int _revision;
int _age;
};
}
ConfigVar &operator<<(ConfigVar &, const rel::Interface &);
@ -84,4 +80,3 @@ bool operator == (const rel::Interface &A, const rel::Interface &B);
bool operator!=(const rel::Interface &A, const rel::Interface &B);
#endif

View File

@ -51,62 +51,41 @@ static RLogChannel *Info = DEF_CHANNEL("info/MACFileIO", Log_Info);
//
static rel::Interface MACFileIO_iface("FileIO/MAC", 2, 1, 0);
int dataBlockSize(const FSConfigPtr &cfg)
{
return cfg->config->blockSize
- cfg->config->blockMACBytes
- cfg->config->blockMACRandBytes;
int dataBlockSize(const FSConfigPtr &cfg) {
return cfg->config->blockSize - cfg->config->blockMACBytes -
cfg->config->blockMACRandBytes;
}
MACFileIO::MACFileIO( const shared_ptr<FileIO> &_base,
const FSConfigPtr &cfg )
: BlockFileIO( dataBlockSize( cfg ), cfg )
, base( _base )
, cipher( cfg->cipher )
, key( cfg->key )
, macBytes( cfg->config->blockMACBytes )
, randBytes( cfg->config->blockMACRandBytes )
, warnOnly( cfg->opts->forceDecode )
{
MACFileIO::MACFileIO(const shared_ptr<FileIO> &_base, const FSConfigPtr &cfg)
: BlockFileIO(dataBlockSize(cfg), cfg),
base(_base),
cipher(cfg->cipher),
key(cfg->key),
macBytes(cfg->config->blockMACBytes),
randBytes(cfg->config->blockMACRandBytes),
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->blockSize, cfg->config->blockMACBytes,
cfg->config->blockMACRandBytes);
}
MACFileIO::~MACFileIO()
{
}
MACFileIO::~MACFileIO() {}
rel::Interface MACFileIO::interface() const
{
return MACFileIO_iface;
}
rel::Interface MACFileIO::interface() const { return MACFileIO_iface; }
int MACFileIO::open( int flags )
{
return base->open( flags );
}
int MACFileIO::open(int flags) { return base->open(flags); }
void MACFileIO::setFileName( const char *fileName )
{
void MACFileIO::setFileName(const char *fileName) {
base->setFileName(fileName);
}
const char *MACFileIO::getFileName() const
{
return base->getFileName();
}
const char *MACFileIO::getFileName() const { return base->getFileName(); }
bool MACFileIO::setIV( uint64_t iv )
{
return base->setIV( iv );
}
bool MACFileIO::setIV(uint64_t iv) { return base->setIV(iv); }
inline static off_t roundUpDivide( off_t numerator, int denominator )
{
inline static off_t roundUpDivide(off_t numerator, int denominator) {
// integer arithmetic always rounds down, so we can round up by adding
// enough so that any value other then a multiple of denominator gets
// rouned to the next highest value.
@ -123,8 +102,7 @@ inline static off_t roundUpDivide( off_t numerator, int denominator )
// ... blockNum = 1
// ... partialBlock = 0
// ... adjLoc = 1 * blockSize
static off_t locWithHeader( off_t offset, int blockSize, int headerSize )
{
static off_t locWithHeader(off_t offset, int blockSize, int headerSize) {
off_t blockNum = roundUpDivide(offset, blockSize - headerSize);
return offset + blockNum * headerSize;
}
@ -134,18 +112,15 @@ static off_t locWithHeader( off_t offset, int blockSize, int headerSize )
// The output value will always be less then the input value, because the
// headers are stored at the beginning of the block, so even the first data is
// offset by the size of the header.
static off_t locWithoutHeader( off_t offset, int blockSize, int headerSize )
{
static off_t locWithoutHeader(off_t offset, int blockSize, int headerSize) {
off_t blockNum = roundUpDivide(offset, blockSize);
return offset - blockNum * headerSize;
}
int MACFileIO::getAttr( struct stat *stbuf ) const
{
int MACFileIO::getAttr(struct stat *stbuf) const {
int res = base->getAttr(stbuf);
if(res == 0 && S_ISREG(stbuf->st_mode))
{
if (res == 0 && S_ISREG(stbuf->st_mode)) {
// have to adjust size field..
int headerSize = macBytes + randBytes;
int bs = blockSize() + headerSize;
@ -155,21 +130,18 @@ int MACFileIO::getAttr( struct stat *stbuf ) const
return res;
}
off_t MACFileIO::getSize() const
{
off_t MACFileIO::getSize() const {
// adjust the size to hide the header overhead we tack on..
int headerSize = macBytes + randBytes;
int bs = blockSize() + headerSize;
off_t size = base->getSize();
if(size > 0)
size = locWithoutHeader( size, bs, headerSize );
if (size > 0) size = locWithoutHeader(size, bs, headerSize);
return size;
}
ssize_t MACFileIO::readOneBlock( const IORequest &req ) const
{
ssize_t MACFileIO::readOneBlock(const IORequest &req) const {
int headerSize = macBytes + randBytes;
int bs = blockSize() + headerSize;
@ -186,47 +158,38 @@ ssize_t MACFileIO::readOneBlock( const IORequest &req ) const
// don't store zeros if configured for zero-block pass-through
bool skipBlock = true;
if( _allowHoles )
{
if (_allowHoles) {
for (int i = 0; i < readSize; ++i)
if(tmp.data[i] != 0)
{
if (tmp.data[i] != 0) {
skipBlock = false;
break;
}
} else if (macBytes > 0)
skipBlock = false;
if(readSize > headerSize)
{
if(!skipBlock)
{
if (readSize > headerSize) {
if (!skipBlock) {
// At this point the data has been decoded. So, compute the MAC of
// the block and check against the checksum stored in the header..
uint64_t mac = cipher->MAC_64( tmp.data + macBytes,
readSize - macBytes, key );
uint64_t mac =
cipher->MAC_64(tmp.data + macBytes, readSize - macBytes, key);
// Constant time comparision to prevent timing attacks
unsigned char fail = 0;
for(int i=0; i<macBytes; ++i, mac >>= 8)
{
for (int i = 0; i < macBytes; ++i, mac >>= 8) {
int test = mac & 0xff;
int stored = tmp.data[i];
fail |= (test ^ stored);
}
if( fail > 0 )
{
if (fail > 0) {
// uh oh..
long blockNum = req.offset / bs;
rWarning(_("MAC comparison failure in block %li"),
blockNum);
if( !warnOnly )
{
rWarning(_("MAC comparison failure in block %li"), blockNum);
if (!warnOnly) {
MemoryPool::release(mb);
throw ERROR(
_("MAC comparison failure, refusing to read"));
throw ERROR(_("MAC comparison failure, refusing to read"));
}
}
}
@ -234,11 +197,9 @@ ssize_t MACFileIO::readOneBlock( const IORequest &req ) const
// now copy the data to the output buffer
readSize -= headerSize;
memcpy(req.data, tmp.data + headerSize, readSize);
} else
{
} else {
rDebug("readSize %i at offset %" PRIi64, (int)readSize, req.offset);
if(readSize > 0)
readSize = 0;
if (readSize > 0) readSize = 0;
}
MemoryPool::release(mb);
@ -246,8 +207,7 @@ ssize_t MACFileIO::readOneBlock( const IORequest &req ) const
return readSize;
}
bool MACFileIO::writeOneBlock( const IORequest &req )
{
bool MACFileIO::writeOneBlock(const IORequest &req) {
int headerSize = macBytes + randBytes;
int bs = blockSize() + headerSize;
@ -262,20 +222,17 @@ bool MACFileIO::writeOneBlock( const IORequest &req )
memset(newReq.data, 0, headerSize);
memcpy(newReq.data + headerSize, req.data, req.dataLen);
if(randBytes > 0)
{
if (randBytes > 0) {
if (!cipher->randomize(newReq.data + macBytes, randBytes, false))
return false;
}
if(macBytes > 0)
{
if (macBytes > 0) {
// compute the mac (which includes the random data) and fill it in
uint64_t mac = cipher->MAC_64( newReq.data+macBytes,
req.dataLen + randBytes, key );
uint64_t mac =
cipher->MAC_64(newReq.data + macBytes, req.dataLen + randBytes, key);
for(int i=0; i<macBytes; ++i)
{
for (int i = 0; i < macBytes; ++i) {
newReq.data[i] = mac & 0xff;
mac >>= 8;
}
@ -289,20 +246,15 @@ bool MACFileIO::writeOneBlock( const IORequest &req )
return ok;
}
int MACFileIO::truncate( off_t size )
{
int MACFileIO::truncate(off_t size) {
int headerSize = macBytes + randBytes;
int bs = blockSize() + headerSize;
int res = BlockFileIO::truncateBase(size, 0);
if(res == 0)
base->truncate( locWithHeader( size, bs, headerSize ) );
if (res == 0) base->truncate(locWithHeader(size, bs, headerSize));
return res;
}
bool MACFileIO::isWritable() const
{
return base->isWritable();
}
bool MACFileIO::isWritable() const { return base->isWritable(); }

View File

@ -24,16 +24,14 @@
#include "BlockFileIO.h"
#include "Cipher.h"
class MACFileIO : public BlockFileIO
{
class MACFileIO : public BlockFileIO {
public:
/*
If warnOnlyMode is enabled, then a MAC comparison failure will only
result in a warning message from encfs -- the garbled data will still
be made available..
*/
MACFileIO( const shared_ptr<FileIO> &base,
const FSConfigPtr &cfg );
MACFileIO(const shared_ptr<FileIO> &base, const FSConfigPtr &cfg);
MACFileIO();
virtual ~MACFileIO();
@ -64,4 +62,3 @@ private:
};
#endif

View File

@ -39,16 +39,13 @@ using namespace rlog;
#include <openssl/buffer.h>
#define BLOCKDATA(BLOCK) (unsigned char *) BLOCK->data->data
struct BlockList
{
struct BlockList {
BlockList *next;
int size;
BUF_MEM *data;
};
static BlockList *allocBlock( int size )
{
static BlockList *allocBlock(int size) {
BlockList *block = new BlockList;
block->size = size;
block->data = BUF_MEM_new();
@ -58,8 +55,7 @@ static BlockList *allocBlock( int size )
return block;
}
static void freeBlock( BlockList *el )
{
static void freeBlock(BlockList *el) {
VALGRIND_MAKE_MEM_UNDEFINED(el->data->data, el->data->max);
BUF_MEM_free(el->data);
@ -69,24 +65,19 @@ static void freeBlock( BlockList *el )
static pthread_mutex_t gMPoolMutex = PTHREAD_MUTEX_INITIALIZER;
static BlockList *gMemPool = NULL;
MemBlock MemoryPool::allocate( int size )
{
MemBlock MemoryPool::allocate(int size) {
pthread_mutex_lock(&gMPoolMutex);
BlockList *parent = NULL;
BlockList *block = gMemPool;
// check if we already have a large enough block available..
while(block != NULL && block->size < size)
{
while (block != NULL && block->size < size) {
parent = block;
block = block->next;
}
// unlink block from list
if(block)
{
if (block) {
if (!parent)
gMemPool = block->next;
else
@ -94,8 +85,7 @@ MemBlock MemoryPool::allocate( int size )
}
pthread_mutex_unlock(&gMPoolMutex);
if(!block)
block = allocBlock( size );
if (!block) block = allocBlock(size);
block->next = NULL;
MemBlock result;
@ -107,8 +97,7 @@ MemBlock MemoryPool::allocate( int size )
return result;
}
void MemoryPool::release( const MemBlock &mb )
{
void MemoryPool::release(const MemBlock &mb) {
pthread_mutex_lock(&gMPoolMutex);
BlockList *block = (BlockList *)mb.internalData;
@ -124,8 +113,7 @@ void MemoryPool::release( const MemBlock &mb )
pthread_mutex_unlock(&gMPoolMutex);
}
void MemoryPool::destroyAll()
{
void MemoryPool::destroyAll() {
pthread_mutex_lock(&gMPoolMutex);
BlockList *block = gMemPool;
@ -133,13 +121,10 @@ void MemoryPool::destroyAll()
pthread_mutex_unlock(&gMPoolMutex);
while(block != NULL)
{
while (block != NULL) {
BlockList *next = block->next;
freeBlock(block);
block = next;
}
}

View File

@ -21,9 +21,7 @@
#ifndef _MemoryPool_incl_
#define _MemoryPool_incl_
struct MemBlock
{
struct MemBlock {
unsigned char *data;
void *internalData;
@ -31,10 +29,7 @@ struct MemBlock
MemBlock();
};
inline MemBlock::MemBlock()
: data(0), internalData(0)
{
}
inline MemBlock::MemBlock() : data(0), internalData(0) {}
/*
Memory Pool for fixed sized objects.
@ -45,12 +40,10 @@ inline MemBlock::MemBlock()
unsigned char *buffer = mb.data;
MemoryPool::release( mb );
*/
namespace MemoryPool
{
namespace MemoryPool {
MemBlock allocate(int size);
void release(const MemBlock &el);
void destroyAll();
}
#endif

View File

@ -23,11 +23,9 @@
#include <pthread.h>
namespace rel
{
namespace rel {
class Lock
{
class Lock {
public:
Lock(pthread_mutex_t &mutex);
~Lock();
@ -43,23 +41,15 @@ namespace rel
pthread_mutex_t *_mutex;
};
inline Lock::Lock( pthread_mutex_t &mutex )
: _mutex( &mutex )
{
inline Lock::Lock(pthread_mutex_t &mutex) : _mutex(&mutex) {
pthread_mutex_lock(_mutex);
}
inline Lock::~Lock( )
{
if(_mutex)
pthread_mutex_unlock( _mutex );
inline Lock::~Lock() {
if (_mutex) pthread_mutex_unlock(_mutex);
}
inline void Lock::leave()
{
_mutex = 0;
}
inline void Lock::leave() { _mutex = 0; }
}
#endif

View File

@ -39,20 +39,15 @@ using namespace rel;
using namespace rlog;
#define REF_MODULE(TYPE) \
if(!TYPE::Enabled() ) \
cerr << "referenceModule: should never happen\n";
if (!TYPE::Enabled()) cerr << "referenceModule: should never happen\n";
static
void AddSymbolReferences()
{
static void AddSymbolReferences() {
REF_MODULE(BlockNameIO)
REF_MODULE(StreamNameIO)
REF_MODULE(NullNameIO)
}
struct NameIOAlg
{
struct NameIOAlg {
bool hidden;
NameIO::Constructor constructor;
string description;
@ -62,21 +57,15 @@ struct NameIOAlg
typedef multimap<string, NameIOAlg> NameIOMap_t;
static NameIOMap_t *gNameIOMap = 0;
list< NameIO::Algorithm >
NameIO::GetAlgorithmList( bool includeHidden )
{
list<NameIO::Algorithm> NameIO::GetAlgorithmList(bool includeHidden) {
AddSymbolReferences();
list<Algorithm> result;
if(gNameIOMap)
{
if (gNameIOMap) {
NameIOMap_t::const_iterator it;
NameIOMap_t::const_iterator end = gNameIOMap->end();
for(it = gNameIOMap->begin(); it != end; ++it)
{
if(includeHidden || !it->second.hidden)
{
for (it = gNameIOMap->begin(); it != end; ++it) {
if (includeHidden || !it->second.hidden) {
Algorithm tmp;
tmp.name = it->first;
tmp.description = it->second.description;
@ -92,10 +81,8 @@ NameIO::GetAlgorithmList( bool includeHidden )
bool NameIO::Register(const char *name, const char *description,
const Interface &iface, Constructor constructor,
bool hidden )
{
if( !gNameIOMap )
gNameIOMap = new NameIOMap_t;
bool hidden) {
if (!gNameIOMap) gNameIOMap = new NameIOMap_t;
NameIOAlg alg;
alg.hidden = hidden;
@ -108,14 +95,12 @@ bool NameIO::Register( const char *name, const char *description,
}
shared_ptr<NameIO> NameIO::New(const string &name,
const shared_ptr<Cipher> &cipher, const CipherKey &key)
{
const shared_ptr<Cipher> &cipher,
const CipherKey &key) {
shared_ptr<NameIO> result;
if(gNameIOMap)
{
if (gNameIOMap) {
NameIOMap_t::const_iterator it = gNameIOMap->find(name);
if(it != gNameIOMap->end())
{
if (it != gNameIOMap->end()) {
Constructor fn = it->second.constructor;
result = (*fn)(it->second.iface, cipher, key);
}
@ -124,17 +109,14 @@ shared_ptr<NameIO> NameIO::New( const string &name,
}
shared_ptr<NameIO> NameIO::New(const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key )
{
const shared_ptr<Cipher> &cipher,
const CipherKey &key) {
shared_ptr<NameIO> result;
if(gNameIOMap)
{
if (gNameIOMap) {
NameIOMap_t::const_iterator it;
NameIOMap_t::const_iterator end = gNameIOMap->end();
for(it = gNameIOMap->begin(); it != end; ++it)
{
if( it->second.iface.implements( iface ))
{
for (it = gNameIOMap->begin(); it != end; ++it) {
if (it->second.iface.implements(iface)) {
Constructor fn = it->second.constructor;
result = (*fn)(iface, cipher, key);
break;
@ -144,61 +126,37 @@ shared_ptr<NameIO> NameIO::New( const Interface &iface,
return result;
}
NameIO::NameIO() : chainedNameIV(false), reverseEncryption(false) {}
NameIO::~NameIO() {}
NameIO::NameIO()
: chainedNameIV( false ), reverseEncryption( false )
{
}
void NameIO::setChainedNameIV(bool enable) { chainedNameIV = enable; }
NameIO::~NameIO()
{
}
bool NameIO::getChainedNameIV() const { return chainedNameIV; }
void NameIO::setChainedNameIV( bool enable )
{
chainedNameIV = enable;
}
bool NameIO::getChainedNameIV() const
{
return chainedNameIV;
}
void NameIO::setReverseEncryption( bool enable )
{
reverseEncryption = enable;
}
bool NameIO::getReverseEncryption() const
{
return reverseEncryption;
}
void NameIO::setReverseEncryption(bool enable) { reverseEncryption = enable; }
bool NameIO::getReverseEncryption() const { return reverseEncryption; }
std::string NameIO::recodePath(const char *path,
int (NameIO::*_length)(int) const,
int (NameIO::*_code)(const char*, int, uint64_t *, char*) const,
uint64_t *iv ) const
{
int (NameIO::*_code)(const char *, int,
uint64_t *, char *) const,
uint64_t *iv) const {
string output;
while( *path )
{
if( *path == '/' )
{
while (*path) {
if (*path == '/') {
if (!output.empty()) // don't start the string with '/'
output += '/';
++path;
} else
{
} else {
bool isDotFile = (*path == '.');
const char *next = strchr(path, '/');
int len = next ? next - path : strlen(path);
// at this point we know that len > 0
if( isDotFile && (path[len-1] == '.') && (len <= 2) )
{
if (isDotFile && (path[len - 1] == '.') && (len <= 2)) {
output.append(len, '.'); // append [len] copies of '.'
path += len;
continue;
@ -206,8 +164,7 @@ std::string NameIO::recodePath( const char *path,
// figure out buffer sizes
int approxLen = (this->*_length)(len);
if(approxLen <= 0)
throw ERROR("Filename too small to decode");
if (approxLen <= 0) throw ERROR("Filename too small to decode");
BUFFER_INIT(codeBuf, 32, (unsigned int)approxLen + 1)
@ -227,63 +184,47 @@ std::string NameIO::recodePath( const char *path,
return output;
}
std::string NameIO::encodePath( const char *plaintextPath ) const
{
std::string NameIO::encodePath(const char *plaintextPath) const {
uint64_t iv = 0;
return encodePath(plaintextPath, &iv);
}
std::string NameIO::decodePath( const char *cipherPath ) const
{
std::string NameIO::decodePath(const char *cipherPath) const {
uint64_t iv = 0;
return decodePath(cipherPath, &iv);
}
std::string NameIO::_encodePath( const char *plaintextPath, uint64_t *iv ) const
{
std::string NameIO::_encodePath(const char *plaintextPath, uint64_t *iv) const {
// if chaining is not enabled, then the iv pointer is not used..
if(!chainedNameIV)
iv = 0;
return recodePath( plaintextPath,
&NameIO::maxEncodedNameLen, &NameIO::encodeName, iv);
if (!chainedNameIV) iv = 0;
return recodePath(plaintextPath, &NameIO::maxEncodedNameLen,
&NameIO::encodeName, iv);
}
std::string NameIO::_decodePath( const char *cipherPath, uint64_t *iv ) const
{
std::string NameIO::_decodePath(const char *cipherPath, uint64_t *iv) const {
// if chaining is not enabled, then the iv pointer is not used..
if(!chainedNameIV)
iv = 0;
return recodePath( cipherPath,
&NameIO::maxDecodedNameLen, &NameIO::decodeName, iv);
if (!chainedNameIV) iv = 0;
return recodePath(cipherPath, &NameIO::maxDecodedNameLen, &NameIO::decodeName,
iv);
}
std::string NameIO::encodePath( const char *path, uint64_t *iv ) const
{
return getReverseEncryption() ?
_decodePath( path, iv ) :
_encodePath( path, iv );
std::string NameIO::encodePath(const char *path, uint64_t *iv) const {
return getReverseEncryption() ? _decodePath(path, iv) : _encodePath(path, iv);
}
std::string NameIO::decodePath( const char *path, uint64_t *iv ) const
{
return getReverseEncryption() ?
_encodePath( path, iv ) :
_decodePath( path, iv );
std::string NameIO::decodePath(const char *path, uint64_t *iv) const {
return getReverseEncryption() ? _encodePath(path, iv) : _decodePath(path, iv);
}
int NameIO::encodeName( const char *input, int length, char *output ) const
{
int NameIO::encodeName(const char *input, int length, char *output) const {
return encodeName(input, length, (uint64_t *)0, output);
}
int NameIO::decodeName( const char *input, int length, char *output ) const
{
int NameIO::decodeName(const char *input, int length, char *output) const {
return decodeName(input, length, (uint64_t *)0, output);
}
std::string NameIO::_encodeName( const char *plaintextName, int length ) const
{
std::string NameIO::_encodeName(const char *plaintextName, int length) const {
int approxLen = maxEncodedNameLen(length);
BUFFER_INIT(codeBuf, 32, (unsigned int)approxLen + 1)
@ -301,8 +242,7 @@ std::string NameIO::_encodeName( const char *plaintextName, int length ) const
return result;
}
std::string NameIO::_decodeName( const char *encodedName, int length ) const
{
std::string NameIO::_decodeName(const char *encodedName, int length) const {
int approxLen = maxDecodedNameLen(length);
BUFFER_INIT(codeBuf, 32, (unsigned int)approxLen + 1)
@ -320,18 +260,14 @@ std::string NameIO::_decodeName( const char *encodedName, int length ) const
return result;
}
std::string NameIO::encodeName( const char *path, int length ) const
{
return getReverseEncryption() ?
_decodeName( path, length ) :
_encodeName( path, length );
std::string NameIO::encodeName(const char *path, int length) const {
return getReverseEncryption() ? _decodeName(path, length)
: _encodeName(path, length);
}
std::string NameIO::decodeName( const char *path, int length ) const
{
return getReverseEncryption() ?
_encodeName( path, length ) :
_decodeName( path, length );
std::string NameIO::decodeName(const char *path, int length) const {
return getReverseEncryption() ? _encodeName(path, length)
: _decodeName(path, length);
}
/*
int NameIO::encodeName( const char *path, int length,

View File

@ -31,14 +31,13 @@
class Cipher;
class NameIO
{
class NameIO {
public:
typedef shared_ptr<NameIO>(*Constructor)(const rel::Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key);
const shared_ptr<Cipher> &cipher,
const CipherKey &key);
struct Algorithm
{
struct Algorithm {
std::string name;
std::string description;
rel::Interface iface;
@ -48,15 +47,16 @@ public:
static AlgorithmList GetAlgorithmList(bool includeHidden = false);
static shared_ptr<NameIO> New(const rel::Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key);
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);
const shared_ptr<Cipher> &cipher,
const CipherKey &key);
static bool Register(const char *name, const char *description,
const rel::Interface &iface, Constructor constructor,
bool hidden = false);
NameIO();
virtual ~NameIO();
@ -85,16 +85,13 @@ protected:
virtual int decodeName(const char *encodedName, int length,
char *plaintextName) const;
virtual int encodeName( const char *plaintextName, int length,
uint64_t *iv, char *encodedName ) const =0;
virtual int decodeName( const char *encodedName, int length,
uint64_t *iv, char *plaintextName ) const =0;
virtual int encodeName(const char *plaintextName, int length, uint64_t *iv,
char *encodedName) const = 0;
virtual int decodeName(const char *encodedName, int length, uint64_t *iv,
char *plaintextName) const = 0;
private:
std::string recodePath( const char *path,
int (NameIO::*codingLen)(int) const,
std::string recodePath(const char *path, int (NameIO::*codingLen)(int) const,
int (NameIO::*codingFunc)(const char *, int,
uint64_t *, char *) const,
uint64_t *iv) const;
@ -108,8 +105,6 @@ private:
bool reverseEncryption;
};
/*
Helper macros for creating temporary buffers with an optimization that
below a given size (OptimizedSize) is allocated on the stack, and when a
@ -120,19 +115,15 @@ private:
#define BUFFER_INIT(Name, OptimizedSize, Size) \
char Name##_Raw[OptimizedSize]; \
char *Name = Name##_Raw; \
if( sizeof(Name ## _Raw) < Size ) \
Name = new char[ Size ];\
if (sizeof(Name##_Raw) < Size) Name = new char[Size]; \
memset(Name, 0, Size);
#define BUFFER_RESET(Name) \
do { \
if( Name != Name ## _Raw ) \
{ \
if (Name != Name##_Raw) { \
delete[] Name; \
Name = Name##_Raw; \
} \
} while (0);
#endif

View File

@ -18,7 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "NullCipher.h"
#include <cstring>
@ -36,28 +35,24 @@ static Interface NullInterface( "nullCipher", 1, 0, 0 );
static Range NullKeyRange(0);
static Range NullBlockRange(1, 4096, 1);
static shared_ptr<Cipher> NewNullCipher(const Interface &iface, int keyLen)
{
static shared_ptr<Cipher> NewNullCipher(const Interface &iface, int keyLen) {
(void)keyLen;
return shared_ptr<Cipher>(new NullCipher(iface));
}
const bool HiddenCipher = true;
static bool NullCipher_registered = Cipher::Register("Null",
"Non encrypting cipher. For testing only!",
NullInterface, NullKeyRange, NullBlockRange, NewNullCipher,
HiddenCipher);
static bool NullCipher_registered = Cipher::Register(
"Null", "Non encrypting cipher. For testing only!", NullInterface,
NullKeyRange, NullBlockRange, NewNullCipher, HiddenCipher);
class NullKey : public AbstractCipherKey
{
class NullKey : public AbstractCipherKey {
public:
NullKey() {}
virtual ~NullKey() {}
};
class NullDestructor
{
class NullDestructor {
public:
NullDestructor() {}
NullDestructor(const NullDestructor &) {}
@ -69,85 +64,52 @@ public:
shared_ptr<AbstractCipherKey> gNullKey(new NullKey(), NullDestructor());
NullCipher::NullCipher(const Interface &iface_)
{
this->iface = iface_;
}
NullCipher::NullCipher(const Interface &iface_) { this->iface = iface_; }
NullCipher::~NullCipher()
{
}
NullCipher::~NullCipher() {}
Interface NullCipher::interface() const
{
return iface;
}
Interface NullCipher::interface() const { return iface; }
CipherKey NullCipher::newKey(const char *, int,
int &, long, const unsigned char *, int )
{
CipherKey NullCipher::newKey(const char *, int, int &, long,
const unsigned char *, int) {
return gNullKey;
}
CipherKey NullCipher::newKey(const char *, int)
{
return gNullKey;
}
CipherKey NullCipher::newKey(const char *, int) { return gNullKey; }
CipherKey NullCipher::newRandomKey()
{
return gNullKey;
}
CipherKey NullCipher::newRandomKey() { return gNullKey; }
bool NullCipher::randomize( unsigned char *buf, int len, bool ) const
{
bool NullCipher::randomize(unsigned char *buf, int len, bool) const {
memset(buf, 0, len);
return true;
}
uint64_t NullCipher::MAC_64(const unsigned char *, int ,
const CipherKey &, uint64_t *) const
{
uint64_t NullCipher::MAC_64(const unsigned char *, int, const CipherKey &,
uint64_t *) const {
return 0;
}
CipherKey NullCipher::readKey( const unsigned char *,
const CipherKey &, bool)
{
CipherKey NullCipher::readKey(const unsigned char *, const CipherKey &, bool) {
return gNullKey;
}
void NullCipher::writeKey(const CipherKey &, unsigned char *,
const CipherKey &)
{
}
const CipherKey &) {}
bool NullCipher::compareKey(const CipherKey &A_,
const CipherKey &B_) const
{
bool NullCipher::compareKey(const CipherKey &A_, const CipherKey &B_) const {
shared_ptr<NullKey> A = dynamic_pointer_cast<NullKey>(A_);
shared_ptr<NullKey> B = dynamic_pointer_cast<NullKey>(B_);
return A.get() == B.get();
}
int NullCipher::encodedKeySize() const
{
return 0;
}
int NullCipher::encodedKeySize() const { return 0; }
int NullCipher::keySize() const
{
return 0;
}
int NullCipher::keySize() const { return 0; }
int NullCipher::cipherBlockSize() const
{
return 1;
}
int NullCipher::cipherBlockSize() const { return 1; }
bool NullCipher::streamEncode( unsigned char *src, int len,
uint64_t iv64, const CipherKey &key) const
{
bool NullCipher::streamEncode(unsigned char *src, int len, uint64_t iv64,
const CipherKey &key) const {
(void)src;
(void)len;
(void)iv64;
@ -155,9 +117,8 @@ bool NullCipher::streamEncode( unsigned char *src, int len,
return true;
}
bool NullCipher::streamDecode( unsigned char *src, int len,
uint64_t iv64, const CipherKey &key) const
{
bool NullCipher::streamDecode(unsigned char *src, int len, uint64_t iv64,
const CipherKey &key) const {
(void)src;
(void)len;
(void)iv64;
@ -166,19 +127,13 @@ bool NullCipher::streamDecode( unsigned char *src, int len,
}
bool NullCipher::blockEncode(unsigned char *, int, uint64_t,
const CipherKey & ) const
{
const CipherKey &) const {
return true;
}
bool NullCipher::blockDecode(unsigned char *, int, uint64_t,
const CipherKey & ) const
{
return true;
}
bool NullCipher::Enabled()
{
const CipherKey &) const {
return true;
}
bool NullCipher::Enabled() { return true; }

View File

@ -28,8 +28,7 @@
Implements Cipher interface for a pass-through mode. May be useful for
testing, but that's it.
*/
class NullCipher : public Cipher
{
class NullCipher : public Cipher {
rel::Interface iface;
public:
@ -48,39 +47,34 @@ public:
// data must be len keySize()
virtual CipherKey readKey(const unsigned char *data,
const CipherKey &encodingKey,
bool checkKey);
const CipherKey &encodingKey, bool checkKey);
virtual void writeKey(const CipherKey &key, unsigned char *data,
const CipherKey &encodingKey);
virtual bool compareKey( const CipherKey &A,
const CipherKey &B ) const;
virtual bool compareKey(const CipherKey &A, const CipherKey &B) const;
// meta-data about the cypher
virtual int keySize() const;
virtual int encodedKeySize() const;
virtual int cipherBlockSize() const;
virtual bool randomize( unsigned char *buf, int len,
bool strongRandom ) const;
virtual bool randomize(unsigned char *buf, int len, bool strongRandom) const;
virtual uint64_t MAC_64(const unsigned char *data, int len,
const CipherKey &key, uint64_t *chainedIV) const;
// functional interfaces
virtual bool streamEncode(unsigned char *in, int len,
uint64_t iv64, const CipherKey &key) const;
virtual bool streamDecode(unsigned char *in, int len,
uint64_t iv64, const CipherKey &key) const;
virtual bool streamEncode(unsigned char *in, int len, uint64_t iv64,
const CipherKey &key) const;
virtual bool streamDecode(unsigned char *in, int len, uint64_t iv64,
const CipherKey &key) const;
virtual bool blockEncode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &key) const;
virtual bool blockDecode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &key) const;
virtual bool blockEncode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &key) const;
virtual bool blockDecode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &key) const;
// hack to help with static builds
static bool Enabled();
};
#endif

View File

@ -27,66 +27,45 @@
using namespace rel;
static shared_ptr<NameIO> NewNNIO( const Interface &,
const shared_ptr<Cipher> &, const CipherKey & )
{
static shared_ptr<NameIO> NewNNIO(const Interface &, const shared_ptr<Cipher> &,
const CipherKey &) {
return shared_ptr<NameIO>(new NullNameIO());
}
static Interface NNIOIface("nameio/null", 1, 0, 0);
static bool NullNameIO_registered = NameIO::Register("Null",
"No encryption of filenames", NNIOIface, NewNNIO);
static bool NullNameIO_registered =
NameIO::Register("Null", "No encryption of filenames", NNIOIface, NewNNIO);
NullNameIO::NullNameIO( )
{
NullNameIO::NullNameIO() {}
}
NullNameIO::~NullNameIO() {}
NullNameIO::~NullNameIO()
{
}
Interface NullNameIO::interface() const { return NNIOIface; }
Interface NullNameIO::interface() const
{
return NNIOIface;
}
Interface NullNameIO::CurrentInterface() { return NNIOIface; }
Interface NullNameIO::CurrentInterface()
{
return NNIOIface;
}
int NullNameIO::maxEncodedNameLen( int plaintextNameLen ) const
{
int NullNameIO::maxEncodedNameLen(int plaintextNameLen) const {
return plaintextNameLen;
}
int NullNameIO::maxDecodedNameLen( int encodedNameLen ) const
{
int NullNameIO::maxDecodedNameLen(int encodedNameLen) const {
return encodedNameLen;
}
int NullNameIO::encodeName( const char *plaintextName, int length,
uint64_t *iv, char *encodedName ) const
{
int NullNameIO::encodeName(const char *plaintextName, int length, uint64_t *iv,
char *encodedName) const {
(void)iv;
memcpy(encodedName, plaintextName, length);
return length;
}
int NullNameIO::decodeName( const char *encodedName, int length,
uint64_t *iv, char *plaintextName ) const
{
int NullNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
char *plaintextName) const {
(void)iv;
memcpy(plaintextName, encodedName, length);
return length;
}
bool NullNameIO::Enabled()
{
return true;
}
bool NullNameIO::Enabled() { return true; }

View File

@ -23,8 +23,7 @@
#include "NameIO.h"
class NullNameIO : public NameIO
{
class NullNameIO : public NameIO {
public:
static rel::Interface CurrentInterface();
@ -39,14 +38,14 @@ public:
// hack to help with static builds
static bool Enabled();
protected:
virtual int encodeName( const char *plaintextName, int length,
uint64_t *iv, char *encodedName ) const;
virtual int decodeName( const char *encodedName, int length,
uint64_t *iv, char *plaintextName ) const;
virtual int encodeName(const char *plaintextName, int length, uint64_t *iv,
char *encodedName) const;
virtual int decodeName(const char *encodedName, int length, uint64_t *iv,
char *plaintextName) const;
private:
};
#endif

View File

@ -21,12 +21,11 @@
#ifndef _Range_incl_
#define _Range_incl_
class Range
{
class Range {
int minVal;
int maxVal;
int increment;
public:
Range();
Range(int minMax);
@ -41,49 +40,35 @@ public:
int inc() const;
};
inline Range::Range(int minMax)
{
inline Range::Range(int minMax) {
this->minVal = minMax;
this->maxVal = minMax;
this->increment = 1;
}
inline Range::Range(int min_, int max_, int increment_)
{
inline Range::Range(int min_, int max_, int increment_) {
this->minVal = min_;
this->maxVal = max_;
this->increment = increment_;
if(increment == 0)
this->increment = 1;
if (increment == 0) this->increment = 1;
}
inline Range::Range()
: minVal(-1)
, maxVal(-1)
, increment(1)
{
}
inline Range::Range() : minVal(-1), maxVal(-1), increment(1) {}
inline bool Range::allowed(int value) const
{
if(value >= minVal && value <= maxVal)
{
inline bool Range::allowed(int value) const {
if (value >= minVal && value <= maxVal) {
int tmp = value - minVal;
if((tmp % increment) == 0)
return true;
if ((tmp % increment) == 0) return true;
}
return false;
}
inline int Range::closest(int value) const
{
inline int Range::closest(int value) const {
if (allowed(value))
return value;
else
if(value < minVal)
else if (value < minVal)
return minVal;
else
if(value > maxVal)
else if (value > maxVal)
return maxVal;
// must be inbetween but not matched with increment
@ -95,19 +80,10 @@ inline int Range::closest(int value) const
return closest(value + tmp);
}
inline int Range::min() const
{
return minVal;
}
inline int Range::min() const { return minVal; }
inline int Range::max() const
{
return maxVal;
}
inline int Range::max() const { return maxVal; }
inline int Range::inc() const
{
return increment;
}
inline int Range::inc() const { return increment; }
#endif

View File

@ -38,57 +38,41 @@ using namespace std;
static rel::Interface RawFileIO_iface("FileIO/Raw", 1, 0, 0);
FileIO *NewRawFileIO( const rel::Interface &iface )
{
FileIO *NewRawFileIO(const rel::Interface &iface) {
(void)iface;
return new RawFileIO();
}
inline void swap( int &x, int &y )
{
inline void swap(int &x, int &y) {
int tmp = x;
x = y;
y = tmp;
}
RawFileIO::RawFileIO()
: knownSize( false )
, fileSize(0)
, fd( -1 )
, oldfd( -1 )
, canWrite( false )
{
}
: knownSize(false), fileSize(0), fd(-1), oldfd(-1), canWrite(false) {}
RawFileIO::RawFileIO(const std::string &fileName)
: name( fileName )
, knownSize( false )
, fileSize( 0 )
, fd( -1 )
, oldfd( -1 )
, canWrite( false )
{
}
: name(fileName),
knownSize(false),
fileSize(0),
fd(-1),
oldfd(-1),
canWrite(false) {}
RawFileIO::~RawFileIO()
{
RawFileIO::~RawFileIO() {
int _fd = -1;
int _oldfd = -1;
swap(_fd, fd);
swap(_oldfd, oldfd);
if( _oldfd != -1 )
close( _oldfd );
if (_oldfd != -1) close(_oldfd);
if( _fd != -1 )
close( _fd );
if (_fd != -1) close(_fd);
}
rel::Interface RawFileIO::interface() const
{
return RawFileIO_iface;
}
rel::Interface RawFileIO::interface() const { return RawFileIO_iface; }
/*
Workaround for opening a file for write when permissions don't allow.
@ -97,19 +81,16 @@ rel::Interface RawFileIO::interface() const
be called with a lock around it so that there won't be a race condition
with calls to lstat picking up the wrong permissions.
*/
static int open_readonly_workaround(const char *path, int flags)
{
static int open_readonly_workaround(const char *path, int flags) {
int fd = -1;
struct stat stbuf;
memset(&stbuf, 0, sizeof(struct stat));
if(lstat( path, &stbuf ) != -1)
{
if (lstat(path, &stbuf) != -1) {
// make sure user has read/write permission..
chmod(path, stbuf.st_mode | 0600);
fd = ::open(path, flags);
chmod(path, stbuf.st_mode);
} else
{
} else {
rInfo("can't stat file %s", path);
}
@ -125,8 +106,7 @@ static int open_readonly_workaround(const char *path, int flags)
- Also keep the O_LARGEFILE flag, in case the underlying filesystem needs
it..
*/
int RawFileIO::open(int flags)
{
int RawFileIO::open(int flags) {
bool requestWrite = ((flags & O_RDWR) || (flags & O_WRONLY));
rDebug("open call for %s file", requestWrite ? "writable" : "read only");
@ -134,17 +114,14 @@ int RawFileIO::open(int flags)
int result = 0;
// if we have a descriptor and it is writable, or we don't need writable..
if((fd >= 0) && (canWrite || !requestWrite))
{
if ((fd >= 0) && (canWrite || !requestWrite)) {
rDebug("using existing file descriptor");
result = fd; // success
} else
{
} else {
int finalFlags = requestWrite ? O_RDWR : O_RDONLY;
#if defined(O_LARGEFILE)
if( flags & O_LARGEFILE )
finalFlags |= O_LARGEFILE;
if (flags & O_LARGEFILE) finalFlags |= O_LARGEFILE;
#else
#warning O_LARGEFILE not supported
#endif
@ -153,18 +130,15 @@ int RawFileIO::open(int flags)
rDebug("open file with flags %i, result = %i", finalFlags, newFd);
if((newFd == -1) && (errno == EACCES))
{
if ((newFd == -1) && (errno == EACCES)) {
rDebug("using readonly workaround for open");
newFd = open_readonly_workaround(name.c_str(), finalFlags);
}
if(newFd >= 0)
{
if(oldfd >= 0)
{
rError("leaking FD?: oldfd = %i, fd = %i, newfd = %i",
oldfd, fd, newFd);
if (newFd >= 0) {
if (oldfd >= 0) {
rError("leaking FD?: oldfd = %i, fd = %i, newfd = %i", oldfd, fd,
newFd);
}
// the old fd might still be in use, so just keep it around for
@ -172,78 +146,61 @@ int RawFileIO::open(int flags)
canWrite = requestWrite;
oldfd = fd;
result = fd = newFd;
} else
{
} else {
result = -errno;
rInfo("::open error: %s", strerror(errno));
}
}
if(result < 0)
rInfo("file %s open failure: %i", name.c_str(), -result);
if (result < 0) rInfo("file %s open failure: %i", name.c_str(), -result);
return result;
}
int RawFileIO::getAttr( struct stat *stbuf ) const
{
int RawFileIO::getAttr(struct stat *stbuf) const {
int res = lstat(name.c_str(), stbuf);
int eno = errno;
if(res < 0)
rInfo("getAttr error on %s: %s", name.c_str(), strerror( eno ));
if (res < 0) rInfo("getAttr error on %s: %s", name.c_str(), strerror(eno));
return (res < 0) ? -eno : 0;
}
void RawFileIO::setFileName( const char *fileName )
{
name = fileName;
}
void RawFileIO::setFileName(const char *fileName) { name = fileName; }
const char *RawFileIO::getFileName() const
{
return name.c_str();
}
const char *RawFileIO::getFileName() const { return name.c_str(); }
off_t RawFileIO::getSize() const
{
if(!knownSize)
{
off_t RawFileIO::getSize() const {
if (!knownSize) {
struct stat stbuf;
memset(&stbuf, 0, sizeof(struct stat));
int res = lstat(name.c_str(), &stbuf);
if(res == 0)
{
if (res == 0) {
const_cast<RawFileIO *>(this)->fileSize = stbuf.st_size;
const_cast<RawFileIO *>(this)->knownSize = true;
return fileSize;
} else
return -1;
} else
{
} else {
return fileSize;
}
}
ssize_t RawFileIO::read( const IORequest &req ) const
{
ssize_t RawFileIO::read(const IORequest &req) const {
rAssert(fd >= 0);
ssize_t readSize = pread(fd, req.data, req.dataLen, req.offset);
if(readSize < 0)
{
rInfo("read failed at offset %" PRIi64 " for %i bytes: %s",
req.offset, req.dataLen, strerror( errno ));
if (readSize < 0) {
rInfo("read failed at offset %" PRIi64 " for %i bytes: %s", req.offset,
req.dataLen, strerror(errno));
}
return readSize;
}
bool RawFileIO::write( const IORequest &req )
{
bool RawFileIO::write(const IORequest &req) {
rAssert(fd >= 0);
rAssert(true == canWrite);
@ -252,15 +209,13 @@ bool RawFileIO::write( const IORequest &req )
ssize_t bytes = req.dataLen;
off_t offset = req.offset;
while( bytes && retrys > 0 )
{
while (bytes && retrys > 0) {
ssize_t writeSize = ::pwrite(fd, buf, bytes, offset);
if( writeSize < 0 )
{
if (writeSize < 0) {
knownSize = false;
rInfo("write failed at offset %" PRIi64 " for %i bytes: %s",
offset, (int)bytes, strerror( errno ));
rInfo("write failed at offset %" PRIi64 " for %i bytes: %s", offset,
(int)bytes, strerror(errno));
return false;
}
@ -270,31 +225,25 @@ bool RawFileIO::write( const IORequest &req )
--retrys;
}
if(bytes != 0)
{
if (bytes != 0) {
rError("Write error: wrote %i bytes of %i, max retries reached\n",
(int)(req.dataLen - bytes), req.dataLen);
knownSize = false;
return false;
} else
{
if(knownSize)
{
} else {
if (knownSize) {
off_t last = req.offset + req.dataLen;
if(last > fileSize)
fileSize = last;
if (last > fileSize) fileSize = last;
}
return true;
}
}
int RawFileIO::truncate( off_t size )
{
int RawFileIO::truncate(off_t size) {
int res;
if(fd >= 0 && canWrite)
{
if (fd >= 0 && canWrite) {
res = ::ftruncate(fd, size);
#if !defined(__FreeBSD__) && !defined(__APPLE__)
::fdatasync(fd);
@ -302,15 +251,13 @@ int RawFileIO::truncate( off_t size )
} else
res = ::truncate(name.c_str(), size);
if(res < 0)
{
if (res < 0) {
int eno = errno;
rInfo("truncate failed for %s (%i) size %" PRIi64 ", error %s",
name.c_str(), fd, size, strerror(eno));
res = -eno;
knownSize = false;
} else
{
} else {
res = 0;
fileSize = size;
knownSize = true;
@ -319,7 +266,4 @@ int RawFileIO::truncate( off_t size )
return res;
}
bool RawFileIO::isWritable() const
{
return canWrite;
}
bool RawFileIO::isWritable() const { return canWrite; }

View File

@ -25,8 +25,7 @@
#include <string>
class RawFileIO : public FileIO
{
class RawFileIO : public FileIO {
public:
RawFileIO();
RawFileIO(const std::string &fileName);
@ -48,8 +47,8 @@ public:
virtual int truncate(off_t size);
virtual bool isWritable() const;
protected:
protected:
std::string name;
bool knownSize;
@ -61,4 +60,3 @@ protected:
};
#endif

View File

@ -53,10 +53,7 @@ const int MAX_IVLENGTH = 16;
const int KEY_CHECKSUM_BYTES = 4;
#ifndef MIN
inline int MIN(int a, int b)
{
return (a < b) ? a : b;
}
inline int MIN(int a, int b) { return (a < b) ? a : b; }
#endif
/*
@ -71,9 +68,8 @@ inline int MIN(int a, int b)
password->data mappings, which is what the salt is meant to frustrate.
*/
int BytesToKey(int keyLen, int ivLen, const EVP_MD *md,
const unsigned char *data, int dataLen,
unsigned int rounds, unsigned char *key, unsigned char *iv)
{
const unsigned char *data, int dataLen, unsigned int rounds,
unsigned char *key, unsigned char *iv) {
if (data == NULL || dataLen == 0)
return 0; // OpenSSL returns nkey here, but why? It is a failure..
@ -86,16 +82,13 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
EVP_MD_CTX cx;
EVP_MD_CTX_init(&cx);
for(;;)
{
for (;;) {
EVP_DigestInit_ex(&cx, md, NULL);
if( addmd++ )
EVP_DigestUpdate( &cx, mdBuf, mds );
if (addmd++) EVP_DigestUpdate(&cx, mdBuf, mds);
EVP_DigestUpdate(&cx, data, dataLen);
EVP_DigestFinal_ex(&cx, mdBuf, &mds);
for(unsigned int i=1; i < rounds; ++i)
{
for (unsigned int i = 1; i < rounds; ++i) {
EVP_DigestInit_ex(&cx, md, NULL);
EVP_DigestUpdate(&cx, mdBuf, mds);
EVP_DigestFinal_ex(&cx, mdBuf, &mds);
@ -103,16 +96,14 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
int offset = 0;
int toCopy = MIN(nkey, mds - offset);
if( toCopy )
{
if (toCopy) {
memcpy(key, mdBuf + offset, toCopy);
key += toCopy;
nkey -= toCopy;
offset += toCopy;
}
toCopy = MIN(niv, mds - offset);
if( toCopy )
{
if (toCopy) {
memcpy(iv, mdBuf + offset, toCopy);
iv += toCopy;
niv -= toCopy;
@ -126,46 +117,37 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
return keyLen;
}
long time_diff(const timeval &end, const timeval &start)
{
long time_diff(const timeval &end, const timeval &start) {
return (end.tv_sec - start.tv_sec) * 1000 * 1000 +
(end.tv_usec - start.tv_usec);
}
int TimedPBKDF2(const char *pass, int passlen,
const unsigned char *salt, int saltlen,
int keylen, unsigned char *out,
long desiredPDFTime)
{
int TimedPBKDF2(const char *pass, int passlen, const unsigned char *salt,
int saltlen, int keylen, unsigned char *out,
long desiredPDFTime) {
int iter = 1000;
timeval start, end;
for(;;)
{
for (;;) {
gettimeofday(&start, 0);
int res = PKCS5_PBKDF2_HMAC_SHA1(
pass, passlen, const_cast<unsigned char*>(salt), saltlen,
iter, keylen, out);
if(res != 1)
return -1;
int res =
PKCS5_PBKDF2_HMAC_SHA1(pass, passlen, const_cast<unsigned char *>(salt),
saltlen, iter, keylen, out);
if (res != 1) return -1;
gettimeofday(&end, 0);
long delta = time_diff(end, start);
if(delta < desiredPDFTime / 8)
{
if (delta < desiredPDFTime / 8) {
iter *= 4;
} else if(delta < (5 * desiredPDFTime / 6))
{
} else if (delta < (5 * desiredPDFTime / 6)) {
// estimate number of iterations to get close to desired time
iter = (int)((double)iter * (double)desiredPDFTime
/ (double)delta);
iter = (int)((double)iter * (double)desiredPDFTime / (double)delta);
} else
return iter;
}
}
// - Version 1:0 used EVP_BytesToKey, which didn't do the right thing for
// Blowfish key lengths > 128 bit.
// - Version 2:0 uses BytesToKey.
@ -181,44 +163,39 @@ static Interface AESInterface( "ssl/aes", 3, 0, 2 );
static Range BFKeyRange(128, 256, 32);
static Range BFBlockRange(64, 4096, 8);
static shared_ptr<Cipher> NewBFCipher( const Interface &iface, int keyLen )
{
if( keyLen <= 0 )
keyLen = 160;
static shared_ptr<Cipher> NewBFCipher(const Interface &iface, int keyLen) {
if (keyLen <= 0) keyLen = 160;
keyLen = BFKeyRange.closest(keyLen);
const EVP_CIPHER *blockCipher = EVP_bf_cbc();
const EVP_CIPHER *streamCipher = EVP_bf_cfb();
return shared_ptr<Cipher>( new SSL_Cipher(iface, BlowfishInterface,
blockCipher, streamCipher, keyLen / 8) );
return shared_ptr<Cipher>(new SSL_Cipher(
iface, BlowfishInterface, blockCipher, streamCipher, keyLen / 8));
}
static bool BF_Cipher_registered = Cipher::Register("Blowfish",
static bool BF_Cipher_registered =
Cipher::Register("Blowfish",
// xgroup(setup)
gettext_noop("8 byte block cipher"),
BlowfishInterface, BFKeyRange, BFBlockRange, NewBFCipher);
gettext_noop("8 byte block cipher"), BlowfishInterface,
BFKeyRange, BFBlockRange, NewBFCipher);
#endif
#if defined(HAVE_EVP_AES)
static Range AESKeyRange(128, 256, 64);
static Range AESBlockRange(64, 4096, 16);
static shared_ptr<Cipher> NewAESCipher( const Interface &iface, int keyLen )
{
if( keyLen <= 0 )
keyLen = 192;
static shared_ptr<Cipher> NewAESCipher(const Interface &iface, int keyLen) {
if (keyLen <= 0) keyLen = 192;
keyLen = AESKeyRange.closest(keyLen);
const EVP_CIPHER *blockCipher = 0;
const EVP_CIPHER *streamCipher = 0;
switch(keyLen)
{
switch (keyLen) {
case 128:
blockCipher = EVP_aes_128_cbc();
streamCipher = EVP_aes_128_cfb();
@ -236,17 +213,16 @@ static shared_ptr<Cipher> NewAESCipher( const Interface &iface, int keyLen )
break;
}
return shared_ptr<Cipher>( new SSL_Cipher(iface, AESInterface,
blockCipher, streamCipher, keyLen / 8) );
return shared_ptr<Cipher>(new SSL_Cipher(iface, AESInterface, blockCipher,
streamCipher, keyLen / 8));
}
static bool AES_Cipher_registered = Cipher::Register("AES",
"16 byte block cipher",
AESInterface, AESKeyRange, AESBlockRange, NewAESCipher);
static bool AES_Cipher_registered =
Cipher::Register("AES", "16 byte block cipher", AESInterface, AESKeyRange,
AESBlockRange, NewAESCipher);
#endif
class SSLKey : public AbstractCipherKey
{
class SSLKey : public AbstractCipherKey {
public:
pthread_mutex_t mutex;
@ -268,8 +244,7 @@ public:
~SSLKey();
};
SSLKey::SSLKey(int keySize_, int ivLength_)
{
SSLKey::SSLKey(int keySize_, int ivLength_) {
this->keySize = keySize_;
this->ivLength = ivLength_;
pthread_mutex_init(&mutex, 0);
@ -281,8 +256,7 @@ SSLKey::SSLKey(int keySize_, int ivLength_)
mlock(buffer, keySize + ivLength);
}
SSLKey::~SSLKey()
{
SSLKey::~SSLKey() {
memset(buffer, 0, keySize + ivLength);
OPENSSL_free(buffer);
@ -302,19 +276,15 @@ SSLKey::~SSLKey()
pthread_mutex_destroy(&mutex);
}
inline unsigned char* KeyData( const shared_ptr<SSLKey> &key )
{
inline unsigned char *KeyData(const shared_ptr<SSLKey> &key) {
return key->buffer;
}
inline unsigned char* IVData( const shared_ptr<SSLKey> &key )
{
inline unsigned char *IVData(const shared_ptr<SSLKey> &key) {
return key->buffer + key->keySize;
}
void initKey(const shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher,
const EVP_CIPHER *_streamCipher, int _keySize)
{
const EVP_CIPHER *_streamCipher, int _keySize) {
Lock lock(key->mutex);
// initialize the cipher context once so that we don't have to do it for
// every block..
@ -347,15 +317,11 @@ void initKey(const shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher,
HMAC_Init_ex(&key->mac_ctx, KeyData(key), _keySize, EVP_sha1(), 0);
}
static RLogChannel *CipherInfo = DEF_CHANNEL("info/cipher", Log_Info);
SSL_Cipher::SSL_Cipher(const Interface &iface_,
const Interface &realIface_,
SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_,
const EVP_CIPHER *blockCipher,
const EVP_CIPHER *streamCipher,
int keySize_)
{
const EVP_CIPHER *streamCipher, int keySize_) {
this->iface = iface_;
this->realIface = realIface_;
this->_blockCipher = blockCipher;
@ -368,25 +334,19 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_,
rLog(CipherInfo, "allocated cipher %s, keySize %i, ivlength %i",
iface.name().c_str(), _keySize, _ivLength);
if( (EVP_CIPHER_key_length( _blockCipher ) != (int )_keySize)
&& iface.current() == 1)
{
rWarning("Running in backward compatibilty mode for 1.0 - \n"
if ((EVP_CIPHER_key_length(_blockCipher) != (int)_keySize) &&
iface.current() == 1) {
rWarning(
"Running in backward compatibilty mode for 1.0 - \n"
"key is really %i bits, not %i.\n"
"Consider creating a new filesystem and moving your data.",
EVP_CIPHER_key_length( _blockCipher ) * 8,
_keySize * 8 );
EVP_CIPHER_key_length(_blockCipher) * 8, _keySize * 8);
}
}
SSL_Cipher::~SSL_Cipher()
{
}
SSL_Cipher::~SSL_Cipher() {}
Interface SSL_Cipher::interface() const
{
return realIface;
}
Interface SSL_Cipher::interface() const { return realIface; }
/*
create a key from the password.
@ -397,31 +357,24 @@ Interface SSL_Cipher::interface() const
*/
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
int &iterationCount, long desiredDuration,
const unsigned char *salt, int saltLen)
{
const unsigned char *salt, int saltLen) {
shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength));
if(iterationCount == 0)
{
if (iterationCount == 0) {
// timed run, fills in iteration count
int res = TimedPBKDF2(password, passwdLength,
salt, saltLen,
_keySize+_ivLength, KeyData(key),
1000 * desiredDuration);
if(res <= 0)
{
int res =
TimedPBKDF2(password, passwdLength, salt, saltLen, _keySize + _ivLength,
KeyData(key), 1000 * desiredDuration);
if (res <= 0) {
rWarning("openssl error, PBKDF2 failed");
return CipherKey();
} else
iterationCount = res;
} else
{
} else {
// known iteration length
if (PKCS5_PBKDF2_HMAC_SHA1(
password, passwdLength,
const_cast<unsigned char*>(salt), saltLen,
iterationCount, _keySize + _ivLength, KeyData(key)) != 1)
{
password, passwdLength, const_cast<unsigned char *>(salt), saltLen,
iterationCount, _keySize + _ivLength, KeyData(key)) != 1) {
rWarning("openssl error, PBKDF2 failed");
return CipherKey();
}
@ -432,27 +385,23 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
return key;
}
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
{
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.current() > 1) {
// now we use BytesToKey, which can deal with Blowfish keys larger then
// 128 bits.
bytes = BytesToKey( _keySize, _ivLength, EVP_sha1(),
(unsigned char *)password, passwdLength, 16,
KeyData(key), IVData(key) );
bytes =
BytesToKey(_keySize, _ivLength, EVP_sha1(), (unsigned char *)password,
passwdLength, 16, KeyData(key), IVData(key));
// the reason for moving from EVP_BytesToKey to BytesToKey function..
if(bytes != (int)_keySize)
{
rWarning("newKey: BytesToKey returned %i, expecting %i key bytes",
bytes, _keySize);
if (bytes != (int)_keySize) {
rWarning("newKey: BytesToKey returned %i, expecting %i key bytes", bytes,
_keySize);
}
} else
{
} else {
// for backward compatibility with filesystems created with 1:0
bytes = EVP_BytesToKey(_blockCipher, EVP_sha1(), NULL,
(unsigned char *)password, passwdLength, 16,
@ -472,24 +421,21 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
This algorithm can change at any time without affecting backward
compatibility.
*/
CipherKey SSL_Cipher::newRandomKey()
{
CipherKey SSL_Cipher::newRandomKey() {
const int bufLen = MAX_KEYLENGTH;
unsigned char tmpBuf[bufLen];
int saltLen = 20;
unsigned char saltBuf[saltLen];
if(!randomize(tmpBuf, bufLen, true) ||
!randomize(saltBuf, saltLen, true))
if (!randomize(tmpBuf, bufLen, true) || !randomize(saltBuf, saltLen, true))
return CipherKey();
shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength));
// doesn't need to be versioned, because a random key is a random key..
// Doesn't need to be reproducable..
if(PKCS5_PBKDF2_HMAC_SHA1((char*)tmpBuf, bufLen, saltBuf, saltLen,
1000, _keySize + _ivLength, KeyData(key)) != 1)
{
if (PKCS5_PBKDF2_HMAC_SHA1((char *)tmpBuf, bufLen, saltBuf, saltLen, 1000,
_keySize + _ivLength, KeyData(key)) != 1) {
rWarning("openssl error, PBKDF2 failed");
return CipherKey();
}
@ -504,9 +450,8 @@ CipherKey SSL_Cipher::newRandomKey()
/*
compute a 64-bit check value for the data using HMAC.
*/
static uint64_t _checksum_64( SSLKey *key,
const unsigned char *data, int dataLen, uint64_t *chainedIV)
{
static uint64_t _checksum_64(SSLKey *key, const unsigned char *data,
int dataLen, uint64_t *chainedIV) {
rAssert(dataLen > 0);
Lock lock(key->mutex);
@ -515,13 +460,11 @@ static uint64_t _checksum_64( SSLKey *key,
HMAC_Init_ex(&key->mac_ctx, 0, 0, 0, 0);
HMAC_Update(&key->mac_ctx, data, dataLen);
if(chainedIV)
{
if (chainedIV) {
// toss in the chained IV as well
uint64_t tmp = *chainedIV;
unsigned char h[8];
for(unsigned int i=0; i<8; ++i)
{
for (unsigned int i = 0; i < 8; ++i) {
h[i] = tmp & 0xff;
tmp >>= 8;
}
@ -539,15 +482,13 @@ static uint64_t _checksum_64( SSLKey *key,
h[i % 8] ^= (unsigned char)(md[i]);
uint64_t value = (uint64_t)h[0];
for(int i=1; i<8; ++i)
value = (value << 8) | (uint64_t)h[i];
for (int i = 1; i < 8; ++i) value = (value << 8) | (uint64_t)h[i];
return value;
}
bool SSL_Cipher::randomize(unsigned char *buf, int len,
bool strongRandom ) const
{
bool strongRandom) const {
// to avoid warnings of uninitialized data from valgrind
memset(buf, 0, len);
int result;
@ -556,8 +497,7 @@ bool SSL_Cipher::randomize( unsigned char *buf, int len,
else
result = RAND_pseudo_bytes(buf, len);
if(result != 1)
{
if (result != 1) {
char errStr[120]; // specs require string at least 120 bytes long..
unsigned long errVal = 0;
if ((errVal = ERR_get_error()) != 0)
@ -569,20 +509,17 @@ bool SSL_Cipher::randomize( unsigned char *buf, int len,
}
uint64_t SSL_Cipher::MAC_64(const unsigned char *data, int len,
const CipherKey &key, uint64_t *chainedIV ) const
{
const CipherKey &key, uint64_t *chainedIV) const {
shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(key);
uint64_t tmp = _checksum_64(mk.get(), data, len, chainedIV);
if(chainedIV)
*chainedIV = tmp;
if (chainedIV) *chainedIV = tmp;
return tmp;
}
CipherKey SSL_Cipher::readKey(const unsigned char *data,
const CipherKey &masterKey, bool checkKey)
{
const CipherKey &masterKey, bool checkKey) {
shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(masterKey);
rAssert(mk->keySize == _keySize);
@ -598,8 +535,7 @@ CipherKey SSL_Cipher::readKey(const unsigned char *data,
// check for success
unsigned int checksum2 = MAC_32(tmpBuf, _keySize + _ivLength, masterKey);
if(checksum2 != checksum && checkKey)
{
if (checksum2 != checksum && checkKey) {
rDebug("checksum mismatch: expected %u, got %u", checksum, checksum2);
rDebug("on decode of %i bytes", _keySize + _ivLength);
memset(tmpBuf, 0, sizeof(tmpBuf));
@ -617,8 +553,7 @@ CipherKey SSL_Cipher::readKey(const unsigned char *data,
}
void SSL_Cipher::writeKey(const CipherKey &ckey, unsigned char *data,
const CipherKey &masterKey)
{
const CipherKey &masterKey) {
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize);
rAssert(key->ivLength == _ivLength);
@ -638,8 +573,7 @@ void SSL_Cipher::writeKey(const CipherKey &ckey, unsigned char *data,
memcpy(data + KEY_CHECKSUM_BYTES, tmpBuf, bufLen);
// first N bytes contain HMAC derived checksum..
for(int i=1; i<=KEY_CHECKSUM_BYTES; ++i)
{
for (int i = 1; i <= KEY_CHECKSUM_BYTES; ++i) {
data[KEY_CHECKSUM_BYTES - i] = checksum & 0xff;
checksum >>= 8;
}
@ -647,8 +581,7 @@ void SSL_Cipher::writeKey(const CipherKey &ckey, unsigned char *data,
memset(tmpBuf, 0, sizeof(tmpBuf));
}
bool SSL_Cipher::compareKey( const CipherKey &A, const CipherKey &B) const
{
bool SSL_Cipher::compareKey(const CipherKey &A, const CipherKey &B) const {
shared_ptr<SSLKey> key1 = dynamic_pointer_cast<SSLKey>(A);
shared_ptr<SSLKey> key2 = dynamic_pointer_cast<SSLKey>(B);
@ -661,33 +594,25 @@ bool SSL_Cipher::compareKey( const CipherKey &A, const CipherKey &B) const
return true;
}
int SSL_Cipher::encodedKeySize() const
{
int SSL_Cipher::encodedKeySize() const {
return _keySize + _ivLength + KEY_CHECKSUM_BYTES;
}
int SSL_Cipher::keySize() const
{
return _keySize;
}
int SSL_Cipher::keySize() const { return _keySize; }
int SSL_Cipher::cipherBlockSize() const
{
int SSL_Cipher::cipherBlockSize() const {
return EVP_CIPHER_block_size(_blockCipher);
}
void SSL_Cipher::setIVec(unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key) const
{
if (iface.current() >= 3)
{
const shared_ptr<SSLKey> &key) const {
if (iface.current() >= 3) {
memcpy(ivec, IVData(key), _ivLength);
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdLen = EVP_MAX_MD_SIZE;
for(int i=0; i<8; ++i)
{
for (int i = 0; i < 8; ++i) {
md[i] = (unsigned char)(seed & 0xff);
seed >>= 8;
}
@ -700,8 +625,7 @@ void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed,
rAssert(mdLen >= _ivLength);
memcpy(ivec, md, _ivLength);
} else
{
} else {
setIVec_old(ivec, seed, key);
}
}
@ -712,10 +636,8 @@ void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed,
determine if the victim had the file in encrypted storage (without
decrypting the file).
*/
void SSL_Cipher::setIVec_old(unsigned char *ivec,
unsigned int seed,
const shared_ptr<SSLKey> &key) const
{
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.
@ -737,8 +659,7 @@ void SSL_Cipher::setIVec_old(unsigned char *ivec,
ivec[6] ^= (var2 >> 8) & 0xff;
ivec[7] ^= (var1) & 0xff;
if(_ivLength > 8)
{
if (_ivLength > 8) {
ivec[8 + 0] ^= (var1) & 0xff;
ivec[8 + 1] ^= (var2 >> 8) & 0xff;
ivec[8 + 2] ^= (var1 >> 16) & 0xff;
@ -750,17 +671,14 @@ void SSL_Cipher::setIVec_old(unsigned char *ivec,
}
}
static void flipBytes(unsigned char *buf, int size)
{
static void flipBytes(unsigned char *buf, int size) {
unsigned char revBuf[64];
int bytesLeft = size;
while(bytesLeft)
{
while (bytesLeft) {
int toFlip = MIN(sizeof(revBuf), bytesLeft);
for(int i=0; i<toFlip; ++i)
revBuf[i] = buf[toFlip - (i+1)];
for (int i = 0; i < toFlip; ++i) revBuf[i] = buf[toFlip - (i + 1)];
memcpy(buf, revBuf, toFlip);
bytesLeft -= toFlip;
@ -769,24 +687,19 @@ static void flipBytes(unsigned char *buf, int size)
memset(revBuf, 0, sizeof(revBuf));
}
static void shuffleBytes(unsigned char *buf, int size)
{
for(int i=0; i<size-1; ++i)
buf[i+1] ^= buf[i];
static void shuffleBytes(unsigned char *buf, int size) {
for (int i = 0; i < size - 1; ++i) buf[i + 1] ^= buf[i];
}
static void unshuffleBytes(unsigned char *buf, int size)
{
for(int i=size-1; i; --i)
buf[i] ^= buf[i-1];
static void unshuffleBytes(unsigned char *buf, int size) {
for (int i = size - 1; i; --i) buf[i] ^= buf[i - 1];
}
/* Partial blocks are encoded with a stream cipher. We make multiple passes on
the data to ensure that the ends of the data depend on each other.
*/
bool SSL_Cipher::streamEncode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &ckey) const
{
bool SSL_Cipher::streamEncode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &ckey) const {
rAssert(size > 0);
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize);
@ -813,18 +726,16 @@ bool SSL_Cipher::streamEncode(unsigned char *buf, int size,
EVP_EncryptFinal_ex(&key->stream_enc, buf + dstLen, &tmpLen);
dstLen += tmpLen;
if(dstLen != size)
{
rError("encoding %i bytes, got back %i (%i in final_ex)",
size, dstLen, tmpLen);
if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen,
tmpLen);
}
return true;
}
bool SSL_Cipher::streamDecode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &ckey) const
{
bool SSL_Cipher::streamDecode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &ckey) const {
rAssert(size > 0);
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize);
@ -851,19 +762,16 @@ bool SSL_Cipher::streamDecode(unsigned char *buf, int size,
unshuffleBytes(buf, size);
dstLen += tmpLen;
if(dstLen != size)
{
rError("encoding %i bytes, got back %i (%i in final_ex)",
size, dstLen, tmpLen);
if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen,
tmpLen);
}
return true;
}
bool SSL_Cipher::blockEncode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &ckey ) const
{
bool SSL_Cipher::blockEncode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &ckey) const {
rAssert(size > 0);
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize);
@ -886,18 +794,16 @@ bool SSL_Cipher::blockEncode(unsigned char *buf, int size,
EVP_EncryptFinal_ex(&key->block_enc, buf + dstLen, &tmpLen);
dstLen += tmpLen;
if(dstLen != size)
{
rError("encoding %i bytes, got back %i (%i in final_ex)",
size, dstLen, tmpLen);
if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen,
tmpLen);
}
return true;
}
bool SSL_Cipher::blockDecode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &ckey ) const
{
bool SSL_Cipher::blockDecode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &ckey) const {
rAssert(size > 0);
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize);
@ -920,17 +826,12 @@ bool SSL_Cipher::blockDecode(unsigned char *buf, int size,
EVP_DecryptFinal_ex(&key->block_dec, buf + dstLen, &tmpLen);
dstLen += tmpLen;
if(dstLen != size)
{
rError("decoding %i bytes, got back %i (%i in final_ex)",
size, dstLen, tmpLen);
if (dstLen != size) {
rError("decoding %i bytes, got back %i (%i in final_ex)", size, dstLen,
tmpLen);
}
return true;
}
bool SSL_Cipher::Enabled()
{
return true;
}
bool SSL_Cipher::Enabled() { return true; }

View File

@ -68,8 +68,7 @@ typedef struct evp_cipher_st EVP_CIPHER;
initial value vector to randomize the output. But it makes the code
simpler to reuse the encryption algorithm as is.
*/
class SSL_Cipher : public Cipher
{
class SSL_Cipher : public Cipher {
rel::Interface iface;
rel::Interface realIface;
const EVP_CIPHER *_blockCipher;
@ -97,20 +96,17 @@ public:
// data must be len keySize()
virtual CipherKey readKey(const unsigned char *data,
const CipherKey &encodingKey,
bool checkKey);
const CipherKey &encodingKey, bool checkKey);
virtual void writeKey(const CipherKey &key, unsigned char *data,
const CipherKey &encodingKey);
virtual bool compareKey( const CipherKey &A,
const CipherKey &B ) const;
virtual bool compareKey(const CipherKey &A, const CipherKey &B) const;
// meta-data about the cypher
virtual int keySize() const;
virtual int encodedKeySize() const;
virtual int cipherBlockSize() const;
virtual bool randomize( unsigned char *buf, int len,
bool strongRandom ) const;
virtual bool randomize(unsigned char *buf, int len, bool strongRandom) const;
virtual uint64_t MAC_64(const unsigned char *src, int len,
const CipherKey &key, uint64_t *augment) const;
@ -119,23 +115,24 @@ public:
/*
Stream encoding in-place.
*/
virtual bool streamEncode(unsigned char *in, int len,
uint64_t iv64, const CipherKey &key) const;
virtual bool streamDecode(unsigned char *in, int len,
uint64_t iv64, const CipherKey &key) const;
virtual bool streamEncode(unsigned char *in, int len, uint64_t iv64,
const CipherKey &key) const;
virtual bool streamDecode(unsigned char *in, int len, uint64_t iv64,
const CipherKey &key) const;
/*
Block encoding is done in-place. Partial blocks are supported, but
blocks are always expected to begin on a block boundary. See
blockSize().
*/
virtual bool blockEncode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &key) const;
virtual bool blockDecode(unsigned char *buf, int size,
uint64_t iv64, const CipherKey &key) const;
virtual bool blockEncode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &key) const;
virtual bool blockDecode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &key) const;
// hack to help with static builds
static bool Enabled();
private:
void setIVec(unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key) const;
@ -145,6 +142,4 @@ private:
const shared_ptr<SSLKey> &key) const;
};
#endif

View File

@ -33,16 +33,15 @@ using namespace rel;
using namespace std;
static shared_ptr<NameIO> NewStreamNameIO(const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key)
{
const shared_ptr<Cipher> &cipher,
const CipherKey &key) {
return shared_ptr<NameIO>(new StreamNameIO(iface, cipher, key));
}
static bool StreamIO_registered = NameIO::Register("Stream",
static bool StreamIO_registered = NameIO::Register(
"Stream",
gettext_noop("Stream encoding, keeps filenames as short as possible"),
StreamNameIO::CurrentInterface(),
NewStreamNameIO);
StreamNameIO::CurrentInterface(), NewStreamNameIO);
/*
- Version 0.1 is for EncFS 0.x support. The difference to 1.0 is that 0.x
@ -65,8 +64,7 @@ static bool StreamIO_registered = NameIO::Register("Stream",
- Version 2.1 adds support for version 0 for EncFS 0.x compatibility.
*/
Interface StreamNameIO::CurrentInterface()
{
Interface StreamNameIO::CurrentInterface() {
// implement major version 2, 1, and 0
return Interface("nameio/stream", 2, 1, 2);
}
@ -74,54 +72,38 @@ Interface StreamNameIO::CurrentInterface()
StreamNameIO::StreamNameIO(const rel::Interface &iface,
const shared_ptr<Cipher> &cipher,
const CipherKey &key)
: _interface( iface.current() )
, _cipher( cipher )
, _key( key )
{
: _interface(iface.current()), _cipher(cipher), _key(key) {}
}
StreamNameIO::~StreamNameIO() {}
StreamNameIO::~StreamNameIO()
{
}
Interface StreamNameIO::interface() const { return CurrentInterface(); }
Interface StreamNameIO::interface() const
{
return CurrentInterface();
}
int StreamNameIO::maxEncodedNameLen( int plaintextStreamLen ) const
{
int StreamNameIO::maxEncodedNameLen(int plaintextStreamLen) const {
int encodedStreamLen = 2 + plaintextStreamLen;
return B256ToB64Bytes(encodedStreamLen);
}
int StreamNameIO::maxDecodedNameLen( int encodedStreamLen ) const
{
int StreamNameIO::maxDecodedNameLen(int encodedStreamLen) const {
int decLen256 = B64ToB256Bytes(encodedStreamLen);
return decLen256 - 2;
}
int StreamNameIO::encodeName(const char *plaintextName, int length,
uint64_t *iv, char *encodedName ) const
{
uint64_t *iv, char *encodedName) const {
uint64_t tmpIV = 0;
if( iv && _interface >= 2 )
tmpIV = *iv;
if (iv && _interface >= 2) tmpIV = *iv;
unsigned int mac = _cipher->MAC_16( (const unsigned char *)plaintextName,
length, _key, iv );
unsigned int mac =
_cipher->MAC_16((const unsigned char *)plaintextName, length, _key, iv);
// add on checksum bytes
unsigned char *encodeBegin;
if(_interface >= 1)
{
if (_interface >= 1) {
// current versions store the checksum at the beginning
encodedName[0] = (mac >> 8) & 0xff;
encodedName[1] = (mac) & 0xff;
encodeBegin = (unsigned char *)encodedName + 2;
} else
{
} else {
// encfs 0.x stored checksums at the end.
encodedName[length] = (mac >> 8) & 0xff;
encodedName[length + 1] = (mac) & 0xff;
@ -136,22 +118,19 @@ int StreamNameIO::encodeName( const char *plaintextName, int length,
int encodedStreamLen = length + 2;
int encLen64 = B256ToB64Bytes(encodedStreamLen);
changeBase2Inline( (unsigned char *)encodedName, encodedStreamLen,
8, 6, true );
changeBase2Inline((unsigned char *)encodedName, encodedStreamLen, 8, 6, true);
B64ToAscii((unsigned char *)encodedName, encLen64);
return encLen64;
}
int StreamNameIO::decodeName( const char *encodedName, int length,
uint64_t *iv, char *plaintextName ) const
{
int StreamNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
char *plaintextName) const {
rAssert(length > 2);
int decLen256 = B64ToB256Bytes(length);
int decodedStreamLen = decLen256 - 2;
if(decodedStreamLen <= 0)
throw ERROR("Filename too small to decode");
if (decodedStreamLen <= 0) throw ERROR("Filename too small to decode");
BUFFER_INIT(tmpBuf, 32, (unsigned int)length);
@ -163,22 +142,19 @@ int StreamNameIO::decodeName( const char *encodedName, int length,
// pull out the checksum value which is used as an initialization vector
uint64_t tmpIV = 0;
unsigned int mac;
if(_interface >= 1)
{
if (_interface >= 1) {
// current versions store the checksum at the beginning
mac = ((unsigned int)((unsigned char)tmpBuf[0])) << 8
| ((unsigned int)((unsigned char)tmpBuf[1]));
mac = ((unsigned int)((unsigned char)tmpBuf[0])) << 8 |
((unsigned int)((unsigned char)tmpBuf[1]));
// version 2 adds support for IV chaining..
if( iv && _interface >= 2 )
tmpIV = *iv;
if (iv && _interface >= 2) tmpIV = *iv;
memcpy(plaintextName, tmpBuf + 2, decodedStreamLen);
} else
{
} else {
// encfs 0.x stored checksums at the end.
mac = ((unsigned int)((unsigned char)tmpBuf[decodedStreamLen])) << 8
| ((unsigned int)((unsigned char)tmpBuf[decodedStreamLen+1]));
mac = ((unsigned int)((unsigned char)tmpBuf[decodedStreamLen])) << 8 |
((unsigned int)((unsigned char)tmpBuf[decodedStreamLen + 1]));
memcpy(plaintextName, tmpBuf, decodedStreamLen);
}
@ -192,8 +168,7 @@ int StreamNameIO::decodeName( const char *encodedName, int length,
decodedStreamLen, _key, iv);
BUFFER_RESET(tmpBuf);
if(mac2 != mac)
{
if (mac2 != mac) {
rDebug("checksum mismatch: expected %u, got %u", mac, mac2);
rDebug("on decode of %i bytes", decodedStreamLen);
throw ERROR("checksum mismatch in filename decode");
@ -202,8 +177,4 @@ int StreamNameIO::decodeName( const char *encodedName, int length,
return decodedStreamLen;
}
bool StreamNameIO::Enabled()
{
return true;
}
bool StreamNameIO::Enabled() { return true; }

View File

@ -26,13 +26,11 @@
class Cipher;
class StreamNameIO : public NameIO
{
class StreamNameIO : public NameIO {
public:
static rel::Interface CurrentInterface();
StreamNameIO( const rel::Interface &iface,
const shared_ptr<Cipher> &cipher,
StreamNameIO(const rel::Interface &iface, const shared_ptr<Cipher> &cipher,
const CipherKey &key);
virtual ~StreamNameIO();
@ -43,17 +41,17 @@ public:
// hack to help with static builds
static bool Enabled();
protected:
virtual int encodeName( const char *plaintextName, int length,
uint64_t *iv, char *encodedName ) const;
virtual int decodeName( const char *encodedName, int length,
uint64_t *iv, char *plaintextName ) const;
virtual int encodeName(const char *plaintextName, int length, uint64_t *iv,
char *encodedName) const;
virtual int decodeName(const char *encodedName, int length, uint64_t *iv,
char *plaintextName) const;
private:
int _interface;
shared_ptr<Cipher> _cipher;
CipherKey _key;
};
#endif

View File

@ -27,8 +27,7 @@
// It is the caller's responsibility to make sure the output array is large
// enough.
void changeBase2(unsigned char *src, int srcLen, int src2Pow,
unsigned char *dst, int dstLen, int dst2Pow)
{
unsigned char *dst, int dstLen, int dst2Pow) {
unsigned long work = 0;
int workBits = 0; // number of bits left in the work buffer
unsigned char *end = src + srcLen;
@ -37,13 +36,11 @@ void changeBase2(unsigned char *src, int srcLen, int src2Pow,
// copy the new bits onto the high bits of the stream.
// The bits that fall off the low end are the output bits.
while(src != end)
{
while (src != end) {
work |= ((unsigned long)(*src++)) << workBits;
workBits += src2Pow;
while(workBits >= dst2Pow)
{
while (workBits >= dst2Pow) {
*dst++ = work & mask;
work >>= dst2Pow;
workBits -= dst2Pow;
@ -51,8 +48,7 @@ void changeBase2(unsigned char *src, int srcLen, int src2Pow,
}
// now, we could have a partial value left in the work buffer..
if(workBits && ((dst - origDst) < dstLen))
*dst++ = work & mask;
if (workBits && ((dst - origDst) < dstLen)) *dst++ = work & mask;
}
/*
@ -62,22 +58,16 @@ void changeBase2(unsigned char *src, int srcLen, int src2Pow,
Uses the stack to store output values. Recurse every time a new value is
to be written, then write the value at the tail end of the recursion.
*/
static
void changeBase2Inline(unsigned char *src, int srcLen,
int src2Pow, int dst2Pow,
bool outputPartialLastByte,
unsigned long work,
int workBits,
unsigned char *outLoc)
{
static void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow,
int dst2Pow, bool outputPartialLastByte,
unsigned long work, int workBits,
unsigned char *outLoc) {
const int mask = (1 << dst2Pow) - 1;
if(!outLoc)
outLoc = src;
if (!outLoc) outLoc = src;
// copy the new bits onto the high bits of the stream.
// The bits that fall off the low end are the output bits.
while(srcLen && workBits < dst2Pow)
{
while (srcLen && workBits < dst2Pow) {
work |= ((unsigned long)(*src++)) << workBits;
workBits += src2Pow;
--srcLen;
@ -88,22 +78,18 @@ void changeBase2Inline(unsigned char *src, int srcLen,
work >>= dst2Pow;
workBits -= dst2Pow;
if(srcLen)
{
if (srcLen) {
// more input left, so recurse
changeBase2Inline( src, srcLen, src2Pow, dst2Pow,
outputPartialLastByte, work, workBits, outLoc+1);
changeBase2Inline(src, srcLen, src2Pow, dst2Pow, outputPartialLastByte,
work, workBits, outLoc + 1);
*outLoc = outVal;
} else
{
} else {
// no input left, we can write remaining values directly
*outLoc++ = outVal;
// we could have a partial value left in the work buffer..
if(outputPartialLastByte)
{
while(workBits > 0)
{
if (outputPartialLastByte) {
while (workBits > 0) {
*outLoc++ = work & mask;
work >>= dst2Pow;
workBits -= dst2Pow;
@ -112,15 +98,12 @@ void changeBase2Inline(unsigned char *src, int srcLen,
}
}
void changeBase2Inline(unsigned char *src, int srcLen,
int src2Pow, int dst2Pow,
bool outputPartialLastByte)
{
changeBase2Inline(src, srcLen, src2Pow, dst2Pow,
outputPartialLastByte, 0, 0, 0);
void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow, int dst2Pow,
bool outputPartialLastByte) {
changeBase2Inline(src, srcLen, src2Pow, dst2Pow, outputPartialLastByte, 0, 0,
0);
}
// character set for ascii b64:
// ",-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
// a standard base64 (eg a64l doesn't use ',-' but uses './'. We don't
@ -128,13 +111,10 @@ void changeBase2Inline(unsigned char *src, int srcLen,
// '.' included in the encrypted names, so that it can be reserved for files
// with special meaning.
static const char B642AsciiTable[] = ",-0123456789";
void B64ToAscii(unsigned char *in, int length)
{
for(int offset=0; offset<length; ++offset)
{
void B64ToAscii(unsigned char *in, int length) {
for (int offset = 0; offset < length; ++offset) {
int ch = in[offset];
if(ch > 11)
{
if (ch > 11) {
if (ch > 37)
ch += 'a' - 38;
else
@ -150,18 +130,14 @@ static const unsigned char Ascii2B64Table[] =
" 01 23456789:; ";
// 0123456789 123456789 123456789 123456789 123456789 123456789 1234
// 0 1 2 3 4 5 6
void AsciiToB64(unsigned char *in, int length)
{
void AsciiToB64(unsigned char *in, int length) {
return AsciiToB64(in, in, length);
}
void AsciiToB64(unsigned char *out, const unsigned char *in, int length)
{
while(length--)
{
void AsciiToB64(unsigned char *out, const unsigned char *in, int length) {
while (length--) {
unsigned char ch = *in++;
if(ch >= 'A')
{
if (ch >= 'A') {
if (ch >= 'a')
ch += 38 - 'a';
else
@ -173,11 +149,8 @@ void AsciiToB64(unsigned char *out, const unsigned char *in, int length)
}
}
void B32ToAscii(unsigned char *buf, int len)
{
for(int offset=0; offset<len; ++offset)
{
void B32ToAscii(unsigned char *buf, int len) {
for (int offset = 0; offset < len; ++offset) {
int ch = buf[offset];
if (ch >= 0 && ch < 26)
ch += 'A';
@ -188,15 +161,12 @@ void B32ToAscii(unsigned char *buf, int len)
}
}
void AsciiToB32(unsigned char *in, int length)
{
void AsciiToB32(unsigned char *in, int length) {
return AsciiToB32(in, in, length);
}
void AsciiToB32(unsigned char *out, const unsigned char *in, int length)
{
while(length--)
{
void AsciiToB32(unsigned char *out, const unsigned char *in, int length) {
while (length--) {
unsigned char ch = *in++;
int lch = toupper(ch);
if (lch >= 'A')
@ -207,4 +177,3 @@ void AsciiToB32(unsigned char *out, const unsigned char *in, int length)
*out++ = (unsigned char)lch;
}
}

View File

@ -21,28 +21,22 @@
#ifndef _base64_incl_
#define _base64_incl_
inline int B64ToB256Bytes( int numB64Bytes )
{
inline int B64ToB256Bytes(int numB64Bytes) {
return (numB64Bytes * 6) / 8; // round down
}
inline int B32ToB256Bytes( int numB32Bytes )
{
inline int B32ToB256Bytes(int numB32Bytes) {
return (numB32Bytes * 5) / 8; // round down
}
inline int B256ToB64Bytes( int numB256Bytes )
{
inline int B256ToB64Bytes(int numB256Bytes) {
return (numB256Bytes * 8 + 5) / 6; // round up
}
inline int B256ToB32Bytes( int numB256Bytes )
{
inline int B256ToB32Bytes(int numB256Bytes) {
return (numB256Bytes * 8 + 4) / 5; // round up
}
/*
convert data between different bases - each being a power of 2.
*/
@ -52,10 +46,8 @@ void changeBase2(unsigned char *src, int srcLength, int srcPow2,
/*
same as changeBase2, but writes output over the top of input data.
*/
void changeBase2Inline(unsigned char *buf, int srcLength,
int srcPow2, int dst2Pow,
bool outputPartialLastByte);
void changeBase2Inline(unsigned char *buf, int srcLength, int srcPow2,
int dst2Pow, bool outputPartialLastByte);
// inplace translation from values [0,2^6] => base64 ASCII
void B64ToAscii(unsigned char *buf, int length);
@ -71,4 +63,3 @@ void AsciiToB32(unsigned char *buf, int length);
void AsciiToB32(unsigned char *out, const unsigned char *in, int length);
#endif

View File

@ -4,7 +4,6 @@
// This header stores workaround code for dealing with incompatible changes
// made to boost archive/serialization classes.
#if (BOOST_VERSION <= 104100)
// Easy case, boost archive serial numbers are sizeof(int)
BOOST_CLASS_VERSION(EncFSConfig, V6SubVersion)
@ -23,45 +22,39 @@ BOOST_CLASS_VERSION(EncFSConfig, V6SubVersion)
BOOST_CLASS_VERSION(EncFSConfig, 20)
namespace boost {
namespace archive {
namespace detail {
// Specialize iserializer class in order to get rid of version check
template <class Archive>
class iserializer<Archive, EncFSConfig> : public basic_iserializer
{
class iserializer<Archive, EncFSConfig> : public basic_iserializer {
private:
virtual void destroy(/*const*/ void *address) const {
boost::serialization::access::destroy(static_cast<EncFSConfig *>(address));
}
protected:
explicit iserializer() :
basic_iserializer(
boost::serialization::singleton<
BOOST_DEDUCED_TYPENAME
boost::serialization::type_info_implementation<EncFSConfig>::type
>::get_const_instance()
)
{}
explicit iserializer()
: basic_iserializer(boost::serialization::singleton<
BOOST_DEDUCED_TYPENAME boost::serialization::
type_info_implementation<
EncFSConfig>::type>::get_const_instance()) {}
public:
virtual BOOST_DLLEXPORT void load_object_data(
basic_iarchive & ar,
void *x,
const unsigned int file_version
) const BOOST_USED;
basic_iarchive &ar, void *x,
const unsigned int file_version) const BOOST_USED;
virtual bool class_info() const {
return boost::serialization::implementation_level<EncFSConfig>::value
>= boost::serialization::object_class_info;
return boost::serialization::implementation_level<EncFSConfig>::value >=
boost::serialization::object_class_info;
}
virtual bool tracking(const unsigned int /* flags */) const {
return boost::serialization::tracking_level<EncFSConfig>::value
== boost::serialization::track_always
|| ( boost::serialization::tracking_level<EncFSConfig>::value
== boost::serialization::track_selectively
&& serialized_as_pointer());
return boost::serialization::tracking_level<EncFSConfig>::value ==
boost::serialization::track_always ||
(boost::serialization::tracking_level<EncFSConfig>::value ==
boost::serialization::track_selectively &&
serialized_as_pointer());
}
virtual version_type version() const {
return version_type(::boost::serialization::version<EncFSConfig>::value);
@ -74,23 +67,15 @@ public:
template <class Archive>
BOOST_DLLEXPORT void iserializer<Archive, EncFSConfig>::load_object_data(
basic_iarchive & ar,
void *x,
const unsigned int file_version
) const {
basic_iarchive &ar, void *x, const unsigned int file_version) const {
boost::serialization::serialize_adl(
boost::serialization::smart_cast_reference<Archive &>(ar),
* static_cast<EncFSConfig *>(x),
file_version
);
*static_cast<EncFSConfig *>(x), file_version);
}
}
}
}
#endif
#endif // BOOST_VERSIONING_INCL

View File

@ -37,7 +37,6 @@
#include <sys/xattr.h>
#endif
#include <string>
#include <map>
@ -68,40 +67,36 @@ using namespace boost;
static RLogChannel *Info = DEF_CHANNEL("info", Log_Info);
static EncFS_Context * context()
{
static EncFS_Context *context() {
return (EncFS_Context *)fuse_get_context()->private_data;
}
// helper function -- apply a functor to a cipher path, given the plain path
template <typename T>
static int withCipherPath(const char *opName, const char *path,
int (*op)(EncFS_Context *, const string &name, T data ), T data,
bool passReturnCode = false )
{
int (*op)(EncFS_Context *, const string &name,
T data),
T data, bool passReturnCode = false) {
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
string cyName = FSRoot->cipherPath(path);
rLog(Info, "%s %s", opName, cyName.c_str());
res = op(ctx, cyName, data);
if(res == -1)
{
if (res == -1) {
int eno = errno;
rInfo("%s error: %s", opName, strerror(eno));
res = -eno;
} else if (!passReturnCode)
res = ESUCCESS;
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in %s", opName);
err.log(_RLWarningChannel);
}
@ -110,19 +105,16 @@ static int withCipherPath( const char *opName, const char *path,
// helper function -- apply a functor to a node
template <typename T>
static int withFileNode( const char *opName,
const char *path, struct fuse_file_info *fi,
int (*op)(FileNode *, T data ), T data )
{
static int withFileNode(const char *opName, const char *path,
struct fuse_file_info *fi,
int (*op)(FileNode *, T data), T data) {
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
shared_ptr<FileNode> fnode;
if (fi != NULL)
@ -134,10 +126,9 @@ static int withFileNode( const char *opName,
rLog(Info, "%s %s", opName, fnode->cipherName());
res = op(fnode.get(), data);
if(res < 0)
rInfo("%s error: %s", opName, strerror(-res));
} catch( rlog::Error &err )
{
if (res < 0) rInfo("%s error: %s", opName, strerror(-res));
}
catch (rlog::Error &err) {
rError("error caught in %s", opName);
err.log(_RLWarningChannel);
}
@ -155,21 +146,17 @@ static int withFileNode( const char *opName,
can be done here.
*/
int _do_getattr(FileNode *fnode, struct stat *stbuf)
{
int _do_getattr(FileNode *fnode, struct stat *stbuf) {
int res = fnode->getAttr(stbuf);
if(res == ESUCCESS && S_ISLNK(stbuf->st_mode))
{
if (res == ESUCCESS && S_ISLNK(stbuf->st_mode)) {
EncFS_Context *ctx = context();
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(FSRoot)
{
if (FSRoot) {
// determine plaintext link size.. Easiest to read and decrypt..
scoped_array<char> buf(new char[stbuf->st_size + 1]);
res = ::readlink(fnode->cipherName(), buf.get(), stbuf->st_size);
if(res >= 0)
{
if (res >= 0) {
// other functions expect c-strings to be null-terminated, which
// readlink doesn't provide
buf[res] = '\0';
@ -185,234 +172,198 @@ int _do_getattr(FileNode *fnode, struct stat *stbuf)
return res;
}
int encfs_getattr(const char *path, struct stat *stbuf)
{
int encfs_getattr(const char *path, struct stat *stbuf) {
return withFileNode("getattr", path, NULL, _do_getattr, stbuf);
}
int encfs_fgetattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{
struct fuse_file_info *fi) {
return withFileNode("fgetattr", path, fi, _do_getattr, stbuf);
}
int encfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler)
{
int encfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) {
EncFS_Context *ctx = context();
int res = ESUCCESS;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
DirTraverse dt = FSRoot->openDir(path);
rLog(Info, "getdir on %s", FSRoot->cipherPath(path).c_str());
if(dt.valid())
{
if (dt.valid()) {
int fileType = 0;
ino_t inode = 0;
std::string name = dt.nextPlaintextName(&fileType, &inode);
while( !name.empty() )
{
while (!name.empty()) {
res = filler(h, name.c_str(), fileType, inode);
if(res != ESUCCESS)
break;
if (res != ESUCCESS) break;
name = dt.nextPlaintextName(&fileType, &inode);
}
} else
{
} else {
rInfo("getdir request invalid, path: '%s'", path);
}
return res;
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("Error caught in getdir");
err.log(_RLWarningChannel);
return -EIO;
}
}
int encfs_mknod(const char *path, mode_t mode, dev_t rdev)
{
int encfs_mknod(const char *path, mode_t mode, dev_t rdev) {
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
shared_ptr<FileNode> fnode = FSRoot->lookupNode(path, "mknod");
rLog(Info, "mknod on %s, mode %i, dev %" PRIi64,
fnode->cipherName(), mode, (int64_t)rdev);
rLog(Info, "mknod on %s, mode %i, dev %" PRIi64, fnode->cipherName(), mode,
(int64_t)rdev);
uid_t uid = 0;
gid_t gid = 0;
if(ctx->publicFilesystem)
{
if (ctx->publicFilesystem) {
fuse_context *context = fuse_get_context();
uid = context->uid;
gid = context->gid;
}
res = fnode->mknod(mode, rdev, uid, gid);
// Is this error due to access problems?
if(ctx->publicFilesystem && -res == EACCES)
{
if (ctx->publicFilesystem && -res == EACCES) {
// try again using the parent dir's group
string parent = fnode->plaintextParent();
rInfo("trying public filesystem workaround for %s", parent.c_str());
shared_ptr<FileNode> dnode =
FSRoot->lookupNode( parent.c_str(), "mknod" );
shared_ptr<FileNode> dnode = FSRoot->lookupNode(parent.c_str(), "mknod");
struct stat st;
if (dnode->getAttr(&st) == 0)
res = fnode->mknod(mode, rdev, uid, st.st_gid);
}
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in mknod");
err.log(_RLWarningChannel);
}
return res;
}
int encfs_mkdir(const char *path, mode_t mode)
{
int encfs_mkdir(const char *path, mode_t mode) {
fuse_context *fctx = fuse_get_context();
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
uid_t uid = 0;
gid_t gid = 0;
if(ctx->publicFilesystem)
{
if (ctx->publicFilesystem) {
uid = fctx->uid;
gid = fctx->gid;
}
res = FSRoot->mkdir(path, mode, uid, gid);
// Is this error due to access problems?
if(ctx->publicFilesystem && -res == EACCES)
{
if (ctx->publicFilesystem && -res == EACCES) {
// try again using the parent dir's group
string parent = parentDirectory(path);
shared_ptr<FileNode> dnode =
FSRoot->lookupNode( parent.c_str(), "mkdir" );
shared_ptr<FileNode> dnode = FSRoot->lookupNode(parent.c_str(), "mkdir");
struct stat st;
if (dnode->getAttr(&st) == 0)
res = FSRoot->mkdir(path, mode, uid, st.st_gid);
}
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in mkdir");
err.log(_RLWarningChannel);
}
return res;
}
int encfs_unlink(const char *path)
{
int encfs_unlink(const char *path) {
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
// let DirNode handle it atomically so that it can handle race
// conditions
res = FSRoot->unlink(path);
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in unlink");
err.log(_RLWarningChannel);
}
return res;
}
int _do_rmdir(EncFS_Context *, const string &cipherPath, int )
{
int _do_rmdir(EncFS_Context *, const string &cipherPath, int) {
return rmdir(cipherPath.c_str());
}
int encfs_rmdir(const char *path)
{
int encfs_rmdir(const char *path) {
return withCipherPath("rmdir", path, _do_rmdir, 0);
}
int _do_readlink(EncFS_Context *ctx, const string &cyName,
tuple<char *, size_t> data )
{
tuple<char *, size_t> data) {
char *buf = data.get<0>();
size_t size = data.get<1>();
int res = ESUCCESS;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
res = ::readlink(cyName.c_str(), buf, size - 1);
if(res == -1)
return -errno;
if (res == -1) return -errno;
buf[res] = '\0'; // ensure null termination
string decodedName;
try
{
try {
decodedName = FSRoot->plainPath(buf);
} catch(...) { }
}
catch (...) {
}
if(!decodedName.empty())
{
if (!decodedName.empty()) {
strncpy(buf, decodedName.c_str(), size - 1);
buf[size - 1] = '\0';
return ESUCCESS;
} else
{
} else {
rWarning("Error decoding link");
return -1;
}
}
int encfs_readlink(const char *path, char *buf, size_t size)
{
return withCipherPath( "readlink", path, _do_readlink,
make_tuple(buf, size) );
int encfs_readlink(const char *path, char *buf, size_t size) {
return withCipherPath("readlink", path, _do_readlink, make_tuple(buf, size));
}
int encfs_symlink(const char *from, const char *to)
{
int encfs_symlink(const char *from, const char *to) {
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
// allow fully qualified names in symbolic links.
string fromCName = FSRoot->relativeCipherPath(from);
string toCName = FSRoot->cipherPath(to);
@ -423,121 +374,99 @@ int encfs_symlink(const char *from, const char *to)
// uid/gid provided by the fuse_context.
int olduid = -1;
int oldgid = -1;
if(ctx->publicFilesystem)
{
if (ctx->publicFilesystem) {
fuse_context *context = fuse_get_context();
olduid = setfsuid(context->uid);
oldgid = setfsgid(context->gid);
}
res = ::symlink(fromCName.c_str(), toCName.c_str());
if(olduid >= 0)
setfsuid( olduid );
if(oldgid >= 0)
setfsgid( oldgid );
if (olduid >= 0) setfsuid(olduid);
if (oldgid >= 0) setfsgid(oldgid);
if (res == -1)
res = -errno;
else
res = ESUCCESS;
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in symlink");
err.log(_RLWarningChannel);
}
return res;
}
int encfs_link(const char *from, const char *to)
{
int encfs_link(const char *from, const char *to) {
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
res = FSRoot->link(from, to);
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in link");
err.log(_RLWarningChannel);
}
return res;
}
int encfs_rename(const char *from, const char *to)
{
int encfs_rename(const char *from, const char *to) {
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
res = FSRoot->rename(from, to);
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in rename");
err.log(_RLWarningChannel);
}
return res;
}
int _do_chmod(EncFS_Context *, const string &cipherPath, mode_t mode)
{
int _do_chmod(EncFS_Context *, const string &cipherPath, mode_t mode) {
return chmod(cipherPath.c_str(), mode);
}
int encfs_chmod(const char *path, mode_t mode)
{
int encfs_chmod(const char *path, mode_t mode) {
return withCipherPath("chmod", path, _do_chmod, mode);
}
int _do_chown(EncFS_Context *, const string &cyName,
tuple<uid_t, gid_t> data)
{
int _do_chown(EncFS_Context *, const string &cyName, tuple<uid_t, gid_t> data) {
int res = lchown(cyName.c_str(), data.get<0>(), data.get<1>());
return (res == -1) ? -errno : ESUCCESS;
}
int encfs_chown(const char *path, uid_t uid, gid_t gid)
{
int encfs_chown(const char *path, uid_t uid, gid_t gid) {
return withCipherPath("chown", path, _do_chown, make_tuple(uid, gid));
}
int _do_truncate( FileNode *fnode, off_t size )
{
return fnode->truncate( size );
}
int _do_truncate(FileNode *fnode, off_t size) { return fnode->truncate(size); }
int encfs_truncate(const char *path, off_t size)
{
int encfs_truncate(const char *path, off_t size) {
return withFileNode("truncate", path, NULL, _do_truncate, size);
}
int encfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
{
int encfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) {
return withFileNode("ftruncate", path, fi, _do_truncate, size);
}
int _do_utime(EncFS_Context *, const string &cyName, struct utimbuf *buf)
{
int _do_utime(EncFS_Context *, const string &cyName, struct utimbuf *buf) {
int res = utime(cyName.c_str(), buf);
return (res == -1) ? -errno : ESUCCESS;
}
int encfs_utime(const char *path, struct utimbuf *buf)
{
int encfs_utime(const char *path, struct utimbuf *buf) {
return withCipherPath("utime", path, _do_utime, buf);
}
int _do_utimens(EncFS_Context *, const string &cyName,
const struct timespec ts[2])
{
const struct timespec ts[2]) {
struct timeval tv[2];
tv[0].tv_sec = ts[0].tv_sec;
tv[0].tv_usec = ts[0].tv_nsec / 1000;
@ -548,38 +477,32 @@ int _do_utimens(EncFS_Context *, const string &cyName,
return (res == -1) ? -errno : ESUCCESS;
}
int encfs_utimens(const char *path, const struct timespec ts[2] )
{
int encfs_utimens(const char *path, const struct timespec ts[2]) {
return withCipherPath("utimens", path, _do_utimens, ts);
}
int encfs_open(const char *path, struct fuse_file_info *file)
{
int encfs_open(const char *path, struct fuse_file_info *file) {
EncFS_Context *ctx = context();
int res = -EIO;
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if(!FSRoot)
return res;
if (!FSRoot) return res;
try
{
try {
shared_ptr<FileNode> fnode =
FSRoot->openNode(path, "open", file->flags, &res);
if(fnode)
{
if (fnode) {
rLog(Info, "encfs_open for %s, flags %i", fnode->cipherName(),
file->flags);
if( res >= 0 )
{
if (res >= 0) {
file->fh = (uintptr_t)ctx->putNode(path, fnode);
res = ESUCCESS;
}
}
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in open");
err.log(_RLWarningChannel);
}
@ -587,26 +510,22 @@ int encfs_open(const char *path, struct fuse_file_info *file)
return res;
}
int _do_flush(FileNode *fnode, int )
{
int _do_flush(FileNode *fnode, int) {
/* Flush can be called multiple times for an open file, so it doesn't
close the file. However it is important to call close() for some
underlying filesystems (like NFS).
*/
int res = fnode->open(O_RDONLY);
if(res >= 0)
{
if (res >= 0) {
int fh = res;
res = close(dup(fh));
if(res == -1)
res = -errno;
if (res == -1) res = -errno;
}
return res;
}
int encfs_flush(const char *path, struct fuse_file_info *fi)
{
int encfs_flush(const char *path, struct fuse_file_info *fi) {
return withFileNode("flush", path, fi, _do_flush, 0);
}
@ -615,47 +534,39 @@ Note: This is advisory -- it might benefit us to keep file nodes around for a
bit after they are released just in case they are reopened soon. But that
requires a cache layer.
*/
int encfs_release(const char *path, struct fuse_file_info *finfo)
{
int encfs_release(const char *path, struct fuse_file_info *finfo) {
EncFS_Context *ctx = context();
try
{
try {
ctx->eraseNode(path, (void *)(uintptr_t)finfo->fh);
return ESUCCESS;
} catch( rlog::Error &err )
{
}
catch (rlog::Error &err) {
rError("error caught in release");
err.log(_RLWarningChannel);
return -EIO;
}
}
int _do_read(FileNode *fnode, tuple<unsigned char *, size_t, off_t> data)
{
int _do_read(FileNode *fnode, tuple<unsigned char *, size_t, off_t> data) {
return fnode->read(data.get<2>(), data.get<0>(), data.get<1>());
}
int encfs_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *file)
{
struct fuse_file_info *file) {
return withFileNode("read", path, file, _do_read,
make_tuple((unsigned char *)buf, size, offset));
}
int _do_fsync(FileNode *fnode, int dataSync)
{
int _do_fsync(FileNode *fnode, int dataSync) {
return fnode->sync(dataSync != 0);
}
int encfs_fsync(const char *path, int dataSync,
struct fuse_file_info *file)
{
int encfs_fsync(const char *path, int dataSync, struct fuse_file_info *file) {
return withFileNode("fsync", path, file, _do_fsync, dataSync);
}
int _do_write(FileNode *fnode, tuple<const char *, size_t, off_t> data)
{
int _do_write(FileNode *fnode, tuple<const char *, size_t, off_t> data) {
size_t size = data.get<1>();
if (fnode->write(data.get<2>(), (unsigned char *)data.get<0>(), size))
return size;
@ -663,36 +574,31 @@ int _do_write(FileNode *fnode, tuple<const char *, size_t, off_t> data)
return -EIO;
}
int encfs_write(const char *path, const char *buf, size_t size,
off_t offset, struct fuse_file_info *file)
{
int encfs_write(const char *path, const char *buf, size_t size, off_t offset,
struct fuse_file_info *file) {
return withFileNode("write", path, file, _do_write,
make_tuple(buf, size, offset));
}
// statfs works even if encfs is detached..
int encfs_statfs(const char *path, struct statvfs *st)
{
int encfs_statfs(const char *path, struct statvfs *st) {
EncFS_Context *ctx = context();
int res = -EIO;
try
{
try {
(void)path; // path should always be '/' for now..
rAssert(st != NULL);
string cyName = ctx->rootCipherDir;
rLog(Info, "doing statfs of %s", cyName.c_str());
res = statvfs(cyName.c_str(), st);
if(!res)
{
if (!res) {
// adjust maximum name length..
st->f_namemax = 6 * (st->f_namemax - 2) / 8; // approx..
}
if(res == -1)
res = -errno;
} catch( rlog::Error &err )
{
if (res == -1) res = -errno;
}
catch (rlog::Error &err) {
rError("error caught in statfs");
err.log(_RLWarningChannel);
}
@ -701,89 +607,74 @@ int encfs_statfs(const char *path, struct statvfs *st)
#ifdef HAVE_XATTR
#ifdef XATTR_ADD_OPT
int _do_setxattr(EncFS_Context *, const string &cyName,
tuple<const char *, const char *, size_t, uint32_t> data)
{
tuple<const char *, const char *, size_t, uint32_t> data) {
int options = 0;
return ::setxattr( cyName.c_str(), data.get<0>(), data.get<1>(),
data.get<2>(), data.get<3>(), options );
return ::setxattr(cyName.c_str(), data.get<0>(), data.get<1>(), data.get<2>(),
data.get<3>(), options);
}
int encfs_setxattr( const char *path, const char *name,
const char *value, size_t size, int flags, uint32_t position )
{
int encfs_setxattr(const char *path, const char *name, const char *value,
size_t size, int flags, uint32_t position) {
(void)flags;
return withCipherPath("setxattr", path, _do_setxattr,
make_tuple(name, value, size, position));
}
#else
int _do_setxattr(EncFS_Context *, const string &cyName,
tuple<const char *, const char *, size_t, int> data)
{
return ::setxattr( cyName.c_str(), data.get<0>(), data.get<1>(),
data.get<2>(), data.get<3>() );
tuple<const char *, const char *, size_t, int> data) {
return ::setxattr(cyName.c_str(), data.get<0>(), data.get<1>(), data.get<2>(),
data.get<3>());
}
int encfs_setxattr( const char *path, const char *name,
const char *value, size_t size, int flags )
{
int encfs_setxattr(const char *path, const char *name, const char *value,
size_t size, int flags) {
return withCipherPath("setxattr", path, _do_setxattr,
make_tuple(name, value, size, flags));
}
#endif
#ifdef XATTR_ADD_OPT
int _do_getxattr(EncFS_Context *, const string &cyName,
tuple<const char *, void *, size_t, uint32_t> data)
{
tuple<const char *, void *, size_t, uint32_t> data) {
int options = 0;
return ::getxattr( cyName.c_str(), data.get<0>(),
data.get<1>(), data.get<2>(), data.get<3>(), options );
return ::getxattr(cyName.c_str(), data.get<0>(), data.get<1>(), data.get<2>(),
data.get<3>(), options);
}
int encfs_getxattr( const char *path, const char *name,
char *value, size_t size, uint32_t position )
{
int encfs_getxattr(const char *path, const char *name, char *value, size_t size,
uint32_t position) {
return withCipherPath("getxattr", path, _do_getxattr,
make_tuple(name, (void *)value, size, position), true);
}
#else
int _do_getxattr(EncFS_Context *, const string &cyName,
tuple<const char *, void *, size_t> data)
{
return ::getxattr( cyName.c_str(), data.get<0>(),
data.get<1>(), data.get<2>());
tuple<const char *, void *, size_t> data) {
return ::getxattr(cyName.c_str(), data.get<0>(), data.get<1>(),
data.get<2>());
}
int encfs_getxattr( const char *path, const char *name,
char *value, size_t size )
{
int encfs_getxattr(const char *path, const char *name, char *value,
size_t size) {
return withCipherPath("getxattr", path, _do_getxattr,
make_tuple(name, (void *)value, size), true);
}
#endif
int _do_listxattr(EncFS_Context *, const string &cyName,
tuple<char *, size_t> data)
{
tuple<char *, size_t> data) {
#ifdef XATTR_ADD_OPT
int options = 0;
int res = ::listxattr( cyName.c_str(), data.get<0>(), data.get<1>(),
options );
int res = ::listxattr(cyName.c_str(), data.get<0>(), data.get<1>(), options);
#else
int res = ::listxattr(cyName.c_str(), data.get<0>(), data.get<1>());
#endif
return (res == -1) ? -errno : res;
}
int encfs_listxattr( const char *path, char *list, size_t size )
{
int encfs_listxattr(const char *path, char *list, size_t size) {
return withCipherPath("listxattr", path, _do_listxattr,
make_tuple(list, size), true);
}
int _do_removexattr(EncFS_Context *, const string &cyName, const char *name)
{
int _do_removexattr(EncFS_Context *, const string &cyName, const char *name) {
#ifdef XATTR_ADD_OPT
int options = 0;
int res = ::removexattr(cyName.c_str(), name, options);
@ -793,10 +684,8 @@ int _do_removexattr(EncFS_Context *, const string &cyName, const char *name)
return (res == -1) ? -errno : res;
}
int encfs_removexattr( const char *path, const char *name )
{
int encfs_removexattr(const char *path, const char *name) {
return withCipherPath("removexattr", path, _do_removexattr, name);
}
#endif // HAVE_XATTR

View File

@ -32,26 +32,22 @@
#ifndef linux
#include <cerrno>
static __inline int setfsuid(uid_t uid)
{
static __inline int setfsuid(uid_t uid) {
uid_t olduid = geteuid();
seteuid(uid);
if (errno != EINVAL)
errno = 0;
if (errno != EINVAL) errno = 0;
return olduid;
}
static __inline int setfsgid(gid_t gid)
{
static __inline int setfsgid(gid_t gid) {
gid_t oldgid = getegid();
setegid(gid);
if (errno != EINVAL)
errno = 0;
if (errno != EINVAL) errno = 0;
return oldgid;
}
@ -72,8 +68,7 @@ int encfs_link(const char *from, const char *to);
int encfs_chmod(const char *path, mode_t mode);
int encfs_chown(const char *path, uid_t uid, gid_t gid);
int encfs_truncate(const char *path, off_t size);
int encfs_ftruncate(const char *path, off_t size,
struct fuse_file_info *fi);
int encfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi);
int encfs_utime(const char *path, struct utimbuf *buf);
int encfs_open(const char *path, struct fuse_file_info *info);
int encfs_release(const char *path, struct fuse_file_info *info);
@ -90,8 +85,8 @@ int encfs_fsync(const char *path, int flags, struct fuse_file_info *info);
#ifdef XATTR_ADD_OPT
int encfs_setxattr(const char *path, const char *name, const char *value,
size_t size, int flags, uint32_t position);
int encfs_getxattr( const char *path, const char *name, char *value,
size_t size, uint32_t position );
int encfs_getxattr(const char *path, const char *name, char *value, size_t size,
uint32_t position);
#else
int encfs_setxattr(const char *path, const char *name, const char *value,
size_t size, int flags);
@ -106,4 +101,3 @@ int encfs_removexattr( const char *path, const char *name );
int encfs_utimens(const char *path, const struct timespec ts[2]);
#endif

View File

@ -15,7 +15,6 @@
* more details.
*/
#include "encfs.h"
#include "config.h"
@ -67,16 +66,14 @@ static int cmd_cat( int argc, char **argv );
static int cmd_export(int argc, char **argv);
static int cmd_showKey(int argc, char **argv);
struct CommandOpts
{
struct CommandOpts {
const char *name;
int minOptions;
int maxOptions;
int (*func)(int argc, char **argv);
const char *argStr;
const char *usageStr;
} commands[] =
{
} commands[] = {
{"info", 1, 1, showInfo, "(root dir)",
// xgroup(usage)
gettext_noop(" -- show information (Default command)")},
@ -88,7 +85,8 @@ struct CommandOpts
gettext_noop(" -- change password for volume")},
{"autopasswd", 1, 1, chpasswdAutomaticly, "(root dir)",
// xgroup(usage)
gettext_noop(" -- change password for volume, taking password"
gettext_noop(
" -- change password for volume, taking password"
" from standard input.\n\tNo prompts are issued.")},
{"ls", 1, 2, cmd_ls, 0, 0},
{"showcruft", 1, 1, cmd_showcruft, "(root dir)",
@ -97,10 +95,12 @@ struct CommandOpts
{"cat", 2, 2, cmd_cat, "(root dir) path",
// xgroup(usage)
gettext_noop(" -- decodes the file and cats it to standard out")},
{"decode", 1, 100, cmd_decode, "[--extpass=prog] (root dir) [encoded-name ...]",
{"decode", 1, 100, cmd_decode,
"[--extpass=prog] (root dir) [encoded-name ...]",
// xgroup(usage)
gettext_noop(" -- decodes name and prints plaintext version")},
{"encode", 1, 100, cmd_encode, "[--extpass=prog] (root dir) [plaintext-name ...]",
{"encode", 1, 100, cmd_encode,
"[--extpass=prog] (root dir) [plaintext-name ...]",
// xgroup(usage)
gettext_noop(" -- encodes a filename and print result")},
{"export", 2, 2, cmd_export, "(root dir) path",
@ -109,26 +109,20 @@ struct CommandOpts
{"--version", 0, 0, showVersion, "",
// xgroup(usage)
gettext_noop(" -- print version number and exit")},
{0,0,0,0,0,0}
};
{0, 0, 0, 0, 0, 0}};
static
void usage(const char *name)
{
cerr << format(_("encfsctl version %s")) % VERSION << "\n"
<< _("Usage:\n")
static void usage(const char *name) {
cerr << format(_("encfsctl version %s")) % VERSION << "\n" << _("Usage:\n")
// displays usage commands, eg "./encfs (root dir) ..."
// xgroup(usage)
<< format(_("%s (root dir)\n"
" -- displays information about the filesystem, or \n")) % name;
<< format(
_("%s (root dir)\n"
" -- displays information about the filesystem, or \n")) %
name;
int offset = 0;
while(commands[offset].name != 0)
{
if( commands[offset].argStr != 0 )
{
while (commands[offset].name != 0) {
if (commands[offset].argStr != 0) {
cerr << "encfsctl " << commands[offset].name << " "
<< commands[offset].argStr << "\n"
<< gettext(commands[offset].usageStr) << "\n";
@ -138,26 +132,20 @@ void usage(const char *name)
cerr << "\n"
// xgroup(usage)
<< format(_("Example: \n%s info ~/.crypt\n")) % name
<< "\n";
<< format(_("Example: \n%s info ~/.crypt\n")) % name << "\n";
}
static bool checkDir( string &rootDir )
{
if( !isDirectory( rootDir.c_str() ))
{
cerr << format(_("directory %s does not exist.\n")) %
rootDir.c_str();
static bool checkDir(string &rootDir) {
if (!isDirectory(rootDir.c_str())) {
cerr << format(_("directory %s does not exist.\n")) % rootDir.c_str();
return false;
}
if(rootDir[ rootDir.length()-1 ] != '/')
rootDir.append("/");
if (rootDir[rootDir.length() - 1] != '/') rootDir.append("/");
return true;
}
static int showVersion( int argc, char **argv )
{
static int showVersion(int argc, char **argv) {
(void)argc;
(void)argv;
// xgroup(usage)
@ -166,19 +154,16 @@ static int showVersion( int argc, char **argv )
return EXIT_SUCCESS;
}
static int showInfo( int argc, char **argv )
{
static int showInfo(int argc, char **argv) {
(void)argc;
string rootDir = argv[1];
if( !checkDir( rootDir ))
return EXIT_FAILURE;
if (!checkDir(rootDir)) return EXIT_FAILURE;
shared_ptr<EncFSConfig> config(new EncFSConfig);
ConfigType type = readConfig(rootDir, config);
// show information stored in config..
switch(type)
{
switch (type) {
case Config_None:
// xgroup(diag)
cout << _("Unable to load or parse config file\n");
@ -190,25 +175,31 @@ static int showInfo( int argc, char **argv )
return EXIT_FAILURE;
case Config_V3:
// xgroup(diag)
cout << "\n" << format(_("Version 3 configuration; "
"created by %s\n")) % config->creator.c_str();
cout << "\n" << format(
_("Version 3 configuration; "
"created by %s\n")) %
config->creator.c_str();
break;
case Config_V4:
// xgroup(diag)
cout << "\n" << format(_("Version 4 configuration; "
"created by %s\n")) % config->creator.c_str();
cout << "\n" << format(
_("Version 4 configuration; "
"created by %s\n")) %
config->creator.c_str();
break;
case Config_V5:
// xgroup(diag)
cout << "\n" << format(_("Version 5 configuration; "
"created by %s (revision %i)\n")) % config->creator %
config->subVersion;
cout << "\n" << format(
_("Version 5 configuration; "
"created by %s (revision %i)\n")) %
config->creator % config->subVersion;
break;
case Config_V6:
// xgroup(diag)
cout << "\n" << format(_("Version 6 configuration; "
"created by %s (revision %i)\n")) % config->creator %
config->subVersion;
cout << "\n" << format(
_("Version 6 configuration; "
"created by %s (revision %i)\n")) %
config->creator % config->subVersion;
break;
}
@ -217,29 +208,21 @@ static int showInfo( int argc, char **argv )
return EXIT_SUCCESS;
}
static RootPtr initRootInfo(int &argc, char ** &argv)
{
static RootPtr initRootInfo(int &argc, char **&argv) {
RootPtr result;
shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
opts->createIfNotFound = false;
opts->checkKey = false;
static struct option long_options[] = {
{"extpass", 1, 0, 'p'},
{0,0,0,0}
};
static struct option long_options[] = {{"extpass", 1, 0, 'p'}, {0, 0, 0, 0}};
for(;;)
{
for (;;) {
int option_index = 0;
int res = getopt_long( argc, argv, "",
long_options, &option_index);
if(res == -1)
break;
int res = getopt_long(argc, argv, "", long_options, &option_index);
if (res == -1) break;
switch(res)
{
switch (res) {
case 'p':
opts->passwordProgram.assign(optarg);
break;
@ -252,18 +235,15 @@ static RootPtr initRootInfo(int &argc, char ** &argv)
argc -= optind;
argv += optind;
if(argc == 0)
{
if (argc == 0) {
cerr << _("Incorrect number of arguments") << "\n";
} else
{
} else {
opts->rootDir = string(argv[0]);
--argc;
++argv;
if(checkDir( opts->rootDir ))
result = initFS( NULL, opts );
if (checkDir(opts->rootDir)) result = initFS(NULL, opts);
if (!result)
cerr << _("Unable to initialize encrypted filesystem - check path.\n");
@ -272,13 +252,11 @@ static RootPtr initRootInfo(int &argc, char ** &argv)
return result;
}
static RootPtr initRootInfo(const char* crootDir)
{
static RootPtr initRootInfo(const char *crootDir) {
string rootDir(crootDir);
RootPtr result;
if(checkDir( rootDir ))
{
if (checkDir(rootDir)) {
shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
opts->rootDir = rootDir;
opts->createIfNotFound = false;
@ -292,18 +270,16 @@ static RootPtr initRootInfo(const char* crootDir)
return result;
}
static int cmd_showKey( int argc, char **argv )
{
static int cmd_showKey(int argc, char **argv) {
(void)argc;
RootPtr rootInfo = initRootInfo(argv[1]);
if (!rootInfo)
return EXIT_FAILURE;
else
{
else {
// encode with itself
string b64Key = rootInfo->cipher->encodeAsString(
rootInfo->volumeKey, rootInfo->volumeKey );
string b64Key = rootInfo->cipher->encodeAsString(rootInfo->volumeKey,
rootInfo->volumeKey);
cout << b64Key << "\n";
@ -311,71 +287,55 @@ static int cmd_showKey( int argc, char **argv )
}
}
static int cmd_decode( int argc, char **argv )
{
static int cmd_decode(int argc, char **argv) {
RootPtr rootInfo = initRootInfo(argc, argv);
if(!rootInfo)
return EXIT_FAILURE;
if (!rootInfo) return EXIT_FAILURE;
if(argc > 0)
{
for(int i=0; i<argc; ++i)
{
if (argc > 0) {
for (int i = 0; i < argc; ++i) {
string name = rootInfo->root->plainPath(argv[i]);
cout << name << "\n";
}
} else
{
} else {
char buf[PATH_MAX + 1];
while(cin.getline(buf,PATH_MAX))
{
while (cin.getline(buf, PATH_MAX)) {
cout << rootInfo->root->plainPath(buf) << "\n";
}
}
return EXIT_SUCCESS;
}
static int cmd_encode( int argc, char **argv )
{
static int cmd_encode(int argc, char **argv) {
RootPtr rootInfo = initRootInfo(argc, argv);
if(!rootInfo)
return EXIT_FAILURE;
if (!rootInfo) return EXIT_FAILURE;
if(argc > 0)
{
for(int i=0; i<argc; ++i)
{
if (argc > 0) {
for (int i = 0; i < argc; ++i) {
string name = rootInfo->root->cipherPathWithoutRoot(argv[i]);
cout << name << "\n";
}
} else
{
} else {
char buf[PATH_MAX + 1];
while(cin.getline(buf,PATH_MAX))
{
while (cin.getline(buf, PATH_MAX)) {
cout << rootInfo->root->cipherPathWithoutRoot(buf) << "\n";
}
}
return EXIT_SUCCESS;
}
static int cmd_ls( int argc, char **argv )
{
static int cmd_ls(int argc, char **argv) {
(void)argc;
RootPtr rootInfo = initRootInfo(argv[1]);
if(!rootInfo)
return EXIT_FAILURE;
if (!rootInfo) return EXIT_FAILURE;
// show files in directory
{
DirTraverse dt = rootInfo->root->openDir("/");
if(dt.valid())
{
if (dt.valid()) {
for (string name = dt.nextPlaintextName(); !name.empty();
name = dt.nextPlaintextName())
{
name = dt.nextPlaintextName()) {
shared_ptr<FileNode> fnode =
rootInfo->root->lookupNode(name.c_str(), "encfsctl-ls");
struct stat stbuf;
@ -386,8 +346,7 @@ static int cmd_ls( int argc, char **argv )
stm.tm_year += 1900;
// TODO: when I add "%s" to the end and name.c_str(), I get a
// seg fault from within strlen. Why ???
printf("%11i %4i-%02i-%02i %02i:%02i:%02i %s\n",
int(stbuf.st_size),
printf("%11i %4i-%02i-%02i %02i:%02i:%02i %s\n", int(stbuf.st_size),
int(stm.tm_year), int(stm.tm_mon), int(stm.tm_mday),
int(stm.tm_hour), int(stm.tm_min), int(stm.tm_sec),
name.c_str());
@ -400,66 +359,55 @@ static int cmd_ls( int argc, char **argv )
// apply an operation to every block in the file
template <typename T>
int processContents( const shared_ptr<EncFS_Root> &rootInfo,
const char *path, T &op )
{
int processContents(const shared_ptr<EncFS_Root> &rootInfo, const char *path,
T &op) {
int errCode = 0;
shared_ptr<FileNode> node = rootInfo->root->openNode( path, "encfsctl",
O_RDONLY, &errCode );
shared_ptr<FileNode> node =
rootInfo->root->openNode(path, "encfsctl", O_RDONLY, &errCode);
if(!node)
{
if (!node) {
// try treating filename as an enciphered path
string plainName = rootInfo->root->plainPath(path);
node = rootInfo->root->lookupNode(plainName.c_str(), "encfsctl");
if(node)
{
if (node) {
errCode = node->open(O_RDONLY);
if(errCode < 0)
node.reset();
if (errCode < 0) node.reset();
}
}
if(!node)
{
if (!node) {
cerr << "unable to open " << path << "\n";
return errCode;
} else
{
} else {
unsigned char buf[512];
int blocks = (node->getSize() + sizeof(buf) - 1) / sizeof(buf);
// read all the data in blocks
for(int i=0; i<blocks; ++i)
{
for (int i = 0; i < blocks; ++i) {
int bytes = node->read(i * sizeof(buf), buf, sizeof(buf));
int res = op(buf, bytes);
if(res < 0)
return res;
if (res < 0) return res;
}
}
return 0;
}
class WriteOutput
{
class WriteOutput {
int _fd;
public:
WriteOutput(int fd) { _fd = fd; }
~WriteOutput() { close(_fd); }
int operator()(const void *buf, int count)
{
int operator()(const void *buf, int count) {
return (int)write(_fd, buf, count);
}
};
static int cmd_cat( int argc, char **argv )
{
static int cmd_cat(int argc, char **argv) {
(void)argc;
RootPtr rootInfo = initRootInfo(argv[1]);
if(!rootInfo)
return EXIT_FAILURE;
if (!rootInfo) return EXIT_FAILURE;
const char *path = argv[2];
WriteOutput output(STDOUT_FILENO);
@ -469,13 +417,11 @@ static int cmd_cat( int argc, char **argv )
}
static int copyLink(const struct stat &stBuf,
const shared_ptr<EncFS_Root> &rootInfo,
const string &cpath, const string &destName )
{
const shared_ptr<EncFS_Root> &rootInfo, const string &cpath,
const string &destName) {
scoped_array<char> buf(new char[stBuf.st_size + 1]);
int res = ::readlink(cpath.c_str(), buf.get(), stBuf.st_size);
if(res == -1)
{
if (res == -1) {
cerr << "unable to readlink of " << cpath << "\n";
return EXIT_FAILURE;
}
@ -484,46 +430,36 @@ static int copyLink(const struct stat &stBuf,
string decodedLink = rootInfo->root->plainPath(buf.get());
res = ::symlink(decodedLink.c_str(), destName.c_str());
if(res == -1)
{
cerr << "unable to create symlink for " << cpath
<< " to " << decodedLink << "\n";
if (res == -1) {
cerr << "unable to create symlink for " << cpath << " to " << decodedLink
<< "\n";
}
return EXIT_SUCCESS;
}
static int copyContents(const shared_ptr<EncFS_Root> &rootInfo,
const char* encfsName, const char* targetName)
{
shared_ptr<FileNode> node =
rootInfo->root->lookupNode( encfsName, "encfsctl" );
const char *encfsName, const char *targetName) {
shared_ptr<FileNode> node = rootInfo->root->lookupNode(encfsName, "encfsctl");
if(!node)
{
if (!node) {
cerr << "unable to open " << encfsName << "\n";
return EXIT_FAILURE;
} else
{
} else {
struct stat st;
if(node->getAttr(&st) != 0)
return EXIT_FAILURE;
if (node->getAttr(&st) != 0) return EXIT_FAILURE;
if((st.st_mode & S_IFLNK) == S_IFLNK)
{
if ((st.st_mode & S_IFLNK) == S_IFLNK) {
string d = rootInfo->root->cipherPath(encfsName);
char linkContents[PATH_MAX + 2];
if(readlink (d.c_str(), linkContents, PATH_MAX + 1) <= 0)
{
if (readlink(d.c_str(), linkContents, PATH_MAX + 1) <= 0) {
cerr << "unable to read link " << encfsName << "\n";
return EXIT_FAILURE;
}
symlink(rootInfo->root->plainPath(linkContents).c_str(),
targetName);
} else
{
symlink(rootInfo->root->plainPath(linkContents).c_str(), targetName);
} else {
int outfd = creat(targetName, st.st_mode);
WriteOutput output(outfd);
@ -533,8 +469,7 @@ static int copyContents(const shared_ptr<EncFS_Root> &rootInfo,
return EXIT_SUCCESS;
}
static bool endsWith(const string &str, char ch)
{
static bool endsWith(const string &str, char ch) {
if (str.empty())
return false;
else
@ -542,12 +477,9 @@ static bool endsWith(const string &str, char ch)
}
static int traverseDirs(const shared_ptr<EncFS_Root> &rootInfo,
string volumeDir, string destDir)
{
if(!endsWith(volumeDir, '/'))
volumeDir.append("/");
if(!endsWith(destDir, '/'))
destDir.append("/");
string volumeDir, string destDir) {
if (!endsWith(volumeDir, '/')) volumeDir.append("/");
if (!endsWith(destDir, '/')) destDir.append("/");
// Lookup directory node so we can create a destination directory
// with the same permissions
@ -555,63 +487,49 @@ static int traverseDirs(const shared_ptr<EncFS_Root> &rootInfo,
struct stat st;
shared_ptr<FileNode> dirNode =
rootInfo->root->lookupNode(volumeDir.c_str(), "encfsctl");
if(dirNode->getAttr(&st))
return EXIT_FAILURE;
if (dirNode->getAttr(&st)) return EXIT_FAILURE;
mkdir(destDir.c_str(), st.st_mode);
}
// show files in directory
DirTraverse dt = rootInfo->root->openDir(volumeDir.c_str());
if(dt.valid())
{
if (dt.valid()) {
for (string name = dt.nextPlaintextName(); !name.empty();
name = dt.nextPlaintextName())
{
name = dt.nextPlaintextName()) {
// Recurse to subdirectories
if(name != "." && name != "..")
{
if (name != "." && name != "..") {
string plainPath = volumeDir + name;
string cpath = rootInfo->root->cipherPath(plainPath.c_str());
string destName = destDir + name;
int r = EXIT_SUCCESS;
struct stat stBuf;
if( !lstat( cpath.c_str(), &stBuf ))
{
if( S_ISDIR( stBuf.st_mode ) )
{
traverseDirs(rootInfo, (plainPath + '/').c_str(),
destName + '/');
} else if( S_ISLNK( stBuf.st_mode ))
{
if (!lstat(cpath.c_str(), &stBuf)) {
if (S_ISDIR(stBuf.st_mode)) {
traverseDirs(rootInfo, (plainPath + '/').c_str(), destName + '/');
} else if (S_ISLNK(stBuf.st_mode)) {
r = copyLink(stBuf, rootInfo, cpath, destName);
} else
{
r = copyContents(rootInfo, plainPath.c_str(),
destName.c_str());
} else {
r = copyContents(rootInfo, plainPath.c_str(), destName.c_str());
}
} else
{
} else {
r = EXIT_FAILURE;
}
if(r != EXIT_SUCCESS)
return r;
if (r != EXIT_SUCCESS) return r;
}
}
}
return EXIT_SUCCESS;
}
static int cmd_export( int argc, char **argv )
{
static int cmd_export(int argc, char **argv) {
(void)argc;
RootPtr rootInfo = initRootInfo(argv[1]);
if(!rootInfo)
return EXIT_FAILURE;
if (!rootInfo) return EXIT_FAILURE;
string destDir = argv[2];
// if the dir doesn't exist, then create it (with user permission)
@ -621,22 +539,18 @@ static int cmd_export( int argc, char **argv )
return traverseDirs(rootInfo, "/", destDir);
}
int showcruft( const shared_ptr<EncFS_Root> &rootInfo, const char *dirName )
{
int showcruft(const shared_ptr<EncFS_Root> &rootInfo, const char *dirName) {
int found = 0;
DirTraverse dt = rootInfo->root->openDir(dirName);
if(dt.valid())
{
if (dt.valid()) {
bool showedDir = false;
for (string name = dt.nextInvalid(); !name.empty();
name = dt.nextInvalid())
{
name = dt.nextInvalid()) {
string cpath = rootInfo->root->cipherPath(dirName);
cpath += '/';
cpath += name;
if(!showedDir)
{
if (!showedDir) {
// just before showing a list of files in a directory
cout << format(_("In directory %s: \n")) % dirName;
showedDir = true;
@ -647,13 +561,10 @@ int showcruft( const shared_ptr<EncFS_Root> &rootInfo, const char *dirName )
// now go back and look for directories to recurse into..
dt = rootInfo->root->openDir(dirName);
if(dt.valid())
{
if (dt.valid()) {
for (string name = dt.nextPlaintextName(); !name.empty();
name = dt.nextPlaintextName())
{
if( name == "." || name == "..")
continue;
name = dt.nextPlaintextName()) {
if (name == "." || name == "..") continue;
string plainPath = dirName;
plainPath += '/';
@ -674,45 +585,38 @@ int showcruft( const shared_ptr<EncFS_Root> &rootInfo, const char *dirName )
iterate recursively through the filesystem and print out names of files
which have filenames which cannot be decoded with the given key..
*/
static int cmd_showcruft( int argc, char **argv )
{
static int cmd_showcruft(int argc, char **argv) {
(void)argc;
RootPtr rootInfo = initRootInfo(argv[1]);
if(!rootInfo)
return EXIT_FAILURE;
if (!rootInfo) return EXIT_FAILURE;
int filesFound = showcruft(rootInfo, "/");
cerr << format(
ngettext("Found %i invalid file.", "Found %i invalid files.",
filesFound)) % filesFound << "\n";
cerr << format(ngettext("Found %i invalid file.", "Found %i invalid files.",
filesFound)) %
filesFound << "\n";
return EXIT_SUCCESS;
}
static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
{
static int do_chpasswd(bool useStdin, bool annotate, int argc, char **argv) {
(void)argc;
string rootDir = argv[1];
if( !checkDir( rootDir ))
return EXIT_FAILURE;
if (!checkDir(rootDir)) return EXIT_FAILURE;
shared_ptr<EncFSConfig> config(new EncFSConfig);
ConfigType cfgType = readConfig(rootDir, config);
if(cfgType == Config_None)
{
if (cfgType == Config_None) {
cout << _("Unable to load or parse config file\n");
return EXIT_FAILURE;
}
// instanciate proper cipher
shared_ptr<Cipher> cipher = Cipher::New(
config->cipherIface, config->keySize );
if(!cipher)
{
shared_ptr<Cipher> cipher = Cipher::New(config->cipherIface, config->keySize);
if (!cipher) {
cout << format(_("Unable to find specified cipher \"%s\"\n")) %
config->cipherIface.name();
return EXIT_FAILURE;
@ -720,18 +624,15 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
// ask for existing password
cout << _("Enter current Encfs password\n");
if (annotate)
cerr << "$PROMPT$ passwd" << endl;
if (annotate) cerr << "$PROMPT$ passwd" << endl;
CipherKey userKey = config->getUserKey(useStdin);
if(!userKey)
return EXIT_FAILURE;
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);
if(!volumeKey)
{
if (!volumeKey) {
cout << _("Invalid password\n");
return EXIT_FAILURE;
}
@ -742,19 +643,15 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
// reinitialize salt and iteration count
config->kdfIterations = 0; // generate new
if( useStdin )
{
if (annotate)
cerr << "$PROMPT$ new_passwd" << endl;
if (useStdin) {
if (annotate) cerr << "$PROMPT$ new_passwd" << endl;
userKey = config->getUserKey(true);
}
else
} else
userKey = config->getNewUserKey();
// re-encode the volume key using the new user key and write it out..
int result = EXIT_FAILURE;
if(userKey)
{
if (userKey) {
int encodedKeySize = cipher->encodedKeySize();
unsigned char *keyBuf = new unsigned char[encodedKeySize];
@ -765,17 +662,14 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
config->assignKeyData(keyBuf, encodedKeySize);
delete[] keyBuf;
if(saveConfig( cfgType, rootDir, config ))
{
if (saveConfig(cfgType, rootDir, config)) {
// password modified -- changes volume key of filesystem..
cout << _("Volume Key successfully updated.\n");
result = EXIT_SUCCESS;
} else
{
} else {
cout << _("Error saving modified config file.\n");
}
} else
{
} else {
cout << _("Error creating key\n");
}
@ -784,19 +678,15 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
return result;
}
static int chpasswd( int argc, char **argv )
{
static int chpasswd(int argc, char **argv) {
return do_chpasswd(false, false, argc, argv);
}
static int chpasswdAutomaticly( int argc, char **argv )
{
static int chpasswdAutomaticly(int argc, char **argv) {
return do_chpasswd(true, false, argc, argv);
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
RLogInit(argc, argv);
#if defined(ENABLE_NLS) && defined(LOCALEDIR)
@ -817,38 +707,29 @@ int main(int argc, char **argv)
// slog->subscribeTo( GetGlobalChannel("debug") );
#endif
if(argc < 2)
{
if (argc < 2) {
usage(argv[0]);
return EXIT_FAILURE;
}
if(argc == 2 && !(*argv[1] == '-' && *(argv[1]+1) == '-'))
{
if (argc == 2 && !(*argv[1] == '-' && *(argv[1] + 1) == '-')) {
// default command when only 1 argument given -- treat the argument as
// a directory..
return showInfo(argc, argv);
} else
{
} else {
// find the specified command
int offset = 0;
while(commands[offset].name != 0)
{
if(!strcmp( argv[1], commands[offset].name ))
break;
while (commands[offset].name != 0) {
if (!strcmp(argv[1], commands[offset].name)) break;
++offset;
}
if(commands[offset].name == 0)
{
if (commands[offset].name == 0) {
cerr << format(_("invalid command: \"%s\"")) % argv[1] << "\n";
} else
{
} else {
if ((argc - 2 < commands[offset].minOptions) ||
(argc-2 > commands[offset].maxOptions))
{
cerr << format(
_("Incorrect number of arguments for command \"%s\"")) %
(argc - 2 > commands[offset].maxOptions)) {
cerr << format(_("Incorrect number of arguments for command \"%s\"")) %
argv[1] << "\n";
} else
return (*commands[offset].func)(argc - 1, argv + 1);

View File

@ -28,5 +28,3 @@
#define _(STR) gettext(STR)
#endif

View File

@ -59,10 +59,7 @@ extern "C" void fuse_unmount_compat22(const char *mountpoint);
#define fuse_unmount fuse_unmount_compat22
#ifndef MAX
inline static int MAX(int a, int b)
{
return (a > b) ? a : b;
}
inline static int MAX(int a, int b) { return (a > b) ? a : b; }
#endif
using namespace std;
@ -74,8 +71,7 @@ using boost::scoped_ptr;
// Maximum number of arguments that we're going to pass on to fuse. Doesn't
// affect how many arguments we can handle, just how many we can pass on..
const int MaxFuseArgs = 32;
struct EncFS_Args
{
struct EncFS_Args {
string mountPoint; // where to make filesystem visible
bool isDaemon; // true == spawn in background, log to syslog
bool isThreaded; // true == threaded
@ -90,13 +86,11 @@ struct EncFS_Args
// In case someone sends me a log dump, I want to know how what options are
// in effect. Not internationalized, since it is something that is mostly
// useful for me!
string toString()
{
string toString() {
ostringstream ss;
ss << (isDaemon ? "(daemon) " : "(fg) ");
ss << (isThreaded ? "(threaded) " : "(UP) ");
if(idleTimeout > 0)
ss << "(timeout " << idleTimeout << ") ";
if (idleTimeout > 0) ss << "(timeout " << idleTimeout << ") ";
if (opts->checkKey) ss << "(keyCheck) ";
if (opts->forceDecode) ss << "(forceDecode) ";
if (opts->ownerCreate) ss << "(ownerCreate) ";
@ -105,45 +99,49 @@ struct EncFS_Args
if (opts->reverseEncryption) ss << "(reverseEncryption) ";
if (opts->mountOnDemand) ss << "(mountOnDemand) ";
if (opts->delayMount) ss << "(delayMount) ";
for(int i=0; i<fuseArgc; ++i)
ss << fuseArgv[i] << ' ';
for (int i = 0; i < fuseArgc; ++i) ss << fuseArgv[i] << ' ';
return ss.str();
}
EncFS_Args()
: opts( new EncFS_Opts() )
{
}
EncFS_Args() : opts(new EncFS_Opts()) {}
};
static int oldStderr = STDERR_FILENO;
static
void usage(const char *name)
{
static void usage(const char *name) {
// xgroup(usage)
cerr << format( _("Build: encfs version %s")) % VERSION
<< "\n\n"
cerr << format(_("Build: encfs version %s")) % VERSION << "\n\n"
// xgroup(usage)
<< format(_("Usage: %s [options] rootDir mountPoint [-- [FUSE Mount Options]]")) % name << "\n\n"
<< format(
_("Usage: %s [options] rootDir mountPoint [-- [FUSE Mount "
"Options]]")) %
name << "\n\n"
// xgroup(usage)
<< _("Common Options:\n"
" -H\t\t\t" "show optional FUSE Mount Options\n"
" -s\t\t\t" "disable multithreaded operation\n"
" -f\t\t\t" "run in foreground (don't spawn daemon).\n"
" -H\t\t\t"
"show optional FUSE Mount Options\n"
" -s\t\t\t"
"disable multithreaded operation\n"
" -f\t\t\t"
"run in foreground (don't spawn daemon).\n"
"\t\t\tError messages will be sent to stderr\n"
"\t\t\tinstead of syslog.\n")
// xgroup(usage)
<< _(" -v, --verbose\t\t" "verbose: output encfs debug messages\n"
" -i, --idle=MINUTES\t""Auto unmount after period of inactivity\n"
" --anykey\t\t" "Do not verify correct key is being used\n"
" --forcedecode\t\t" "decode data even if an error is detected\n"
<< _(" -v, --verbose\t\t"
"verbose: output encfs debug messages\n"
" -i, --idle=MINUTES\t"
"Auto unmount after period of inactivity\n"
" --anykey\t\t"
"Do not verify correct key is being used\n"
" --forcedecode\t\t"
"decode data even if an error is detected\n"
"\t\t\t(for filesystems using MAC block headers)\n")
<< _(" --public\t\t" "act as a typical multi-user filesystem\n"
"\t\t\t(encfs must be run as root)\n")
<< _(" --reverse\t\t" "reverse encryption\n")
<< _(" --public\t\t"
"act as a typical multi-user filesystem\n"
"\t\t\t(encfs must be run as root)\n") << _(" --reverse\t\t"
"reverse encryption\n")
// xgroup(usage)
<< _(" --extpass=program\tUse external program for password prompt\n"
@ -152,13 +150,10 @@ void usage(const char *name)
" encfs ~/.crypt ~/crypt\n"
"\n")
// xgroup(usage)
<< _("For more information, see the man page encfs(1)") << "\n"
<< endl;
<< _("For more information, see the man page encfs(1)") << "\n" << endl;
}
static
void FuseUsage()
{
static void FuseUsage() {
// xgroup(usage)
cerr << _("encfs [options] rootDir mountPoint -- [FUSE Mount Options]\n"
"valid FUSE Mount Options follow:\n") << endl;
@ -168,22 +163,20 @@ void FuseUsage()
fuse_main(argc, const_cast<char **>(argv), (fuse_operations *)NULL, NULL);
}
#define PUSHARG(ARG) do { \
#define PUSHARG(ARG) \
do { \
rAssert(out->fuseArgc < MaxFuseArgs); \
out->fuseArgv[out->fuseArgc++] = (ARG); } while(0)
out->fuseArgv[out->fuseArgc++] = (ARG); \
} while (0)
static
string slashTerminate( const string &src )
{
static string slashTerminate(const string &src) {
string result = src;
if( result[ result.length()-1 ] != '/' )
result.append( "/" );
if (result[result.length() - 1] != '/') result.append("/");
return result;
}
static
bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
{
static bool processArgs(int argc, char *argv[],
const shared_ptr<EncFS_Args> &out) {
// set defaults
out->isDaemon = true;
out->isThreaded = true;
@ -230,11 +223,9 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
{"reverse", 0, 0, 'r'}, // reverse encryption
{"standard", 0, 0, '1'}, // standard configuration
{"paranoia", 0, 0, '2'}, // standard configuration
{0,0,0,0}
};
{0, 0, 0, 0}};
while (1)
{
while (1) {
int option_index = 0;
// 's' : single-threaded mode
@ -245,14 +236,12 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
// 'm' : mount-on-demand
// 'S' : password from stdin
// 'o' : arguments meant for fuse
int res = getopt_long( argc, argv, "HsSfvdmi:o:",
long_options, &option_index);
int res =
getopt_long(argc, argv, "HsSfvdmi:o:", long_options, &option_index);
if(res == -1)
break;
if (res == -1) break;
switch( res )
{
switch (res) {
case '1':
out->opts->configMode = Config_Standard;
break;
@ -311,8 +300,7 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
case 'P':
if (geteuid() != 0)
rWarning(_("option '--public' ignored for non-root user"));
else
{
else {
out->opts->ownerCreate = true;
// add 'allow_other' option
// add 'default_permissions' option (default)
@ -341,11 +329,9 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
}
}
if(!out->isThreaded)
PUSHARG("-s");
if (!out->isThreaded) PUSHARG("-s");
if(useDefaultFlags)
{
if (useDefaultFlags) {
PUSHARG("-o");
PUSHARG("use_ino");
PUSHARG("-o");
@ -354,24 +340,20 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
// we should have at least 2 arguments left over - the source directory and
// the mount point.
if(optind+2 <= argc)
{
if (optind + 2 <= argc) {
out->opts->rootDir = slashTerminate(argv[optind++]);
out->mountPoint = argv[optind++];
} else
{
} else {
// no mount point specified
rWarning(_("Missing one or more arguments, aborting."));
return false;
}
// If there are still extra unparsed arguments, pass them onto FUSE..
if(optind < argc)
{
if (optind < argc) {
rAssert(out->fuseArgc < MaxFuseArgs);
while(optind < argc)
{
while (optind < argc) {
rAssert(out->fuseArgc < MaxFuseArgs);
out->fuseArgv[out->fuseArgc++] = argv[optind];
++optind;
@ -379,27 +361,21 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
}
// sanity check
if(out->isDaemon &&
(!isAbsolutePath( out->mountPoint.c_str() ) ||
!isAbsolutePath( out->opts->rootDir.c_str() ) )
)
{
if (out->isDaemon && (!isAbsolutePath(out->mountPoint.c_str()) ||
!isAbsolutePath(out->opts->rootDir.c_str()))) {
cerr <<
// xgroup(usage)
_("When specifying daemon mode, you must use absolute paths "
"(beginning with '/')")
<< endl;
"(beginning with '/')") << endl;
return false;
}
// the raw directory may not be a subdirectory of the mount point.
{
string testMountPoint = slashTerminate(out->mountPoint);
string testRootDir =
out->opts->rootDir.substr(0, testMountPoint.length());
string testRootDir = out->opts->rootDir.substr(0, testMountPoint.length());
if( testMountPoint == testRootDir )
{
if (testMountPoint == testRootDir) {
cerr <<
// xgroup(usage)
_("The raw directory may not be a subdirectory of the "
@ -408,36 +384,30 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
}
}
if(out->opts->delayMount && ! out->opts->mountOnDemand)
{
if (out->opts->delayMount && !out->opts->mountOnDemand) {
cerr <<
// xgroup(usage)
_("You must use mount-on-demand with delay-mount")
<< endl;
_("You must use mount-on-demand with delay-mount") << endl;
return false;
}
if(out->opts->mountOnDemand && out->opts->passwordProgram.empty())
{
if (out->opts->mountOnDemand && out->opts->passwordProgram.empty()) {
cerr <<
// xgroup(usage)
_("Must set password program when using mount-on-demand")
<< endl;
_("Must set password program when using mount-on-demand") << endl;
return false;
}
// check that the directories exist, or that we can create them..
if (!isDirectory(out->opts->rootDir.c_str()) &&
!userAllowMkdir( out->opts->annotate? 1:0,
out->opts->rootDir.c_str() ,0700))
{
!userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(),
0700)) {
rWarning(_("Unable to locate root directory, aborting."));
return false;
}
if (!isDirectory(out->mountPoint.c_str()) &&
!userAllowMkdir( out->opts->annotate? 2:0,
out->mountPoint.c_str(),0700))
{
!userAllowMkdir(out->opts->annotate ? 2 : 0, out->mountPoint.c_str(),
0700)) {
rWarning(_("Unable to locate mount point, aborting."));
return false;
}
@ -450,8 +420,7 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
static void *idleMonitor(void *);
void *encfs_init(fuse_conn_info *conn)
{
void *encfs_init(fuse_conn_info *conn) {
EncFS_Context *ctx = (EncFS_Context *)fuse_get_context()->private_data;
// set fuse connection options
@ -459,22 +428,20 @@ void *encfs_init(fuse_conn_info *conn)
// if an idle timeout is specified, then setup a thread to monitor the
// filesystem.
if(ctx->args->idleTimeout > 0)
{
if (ctx->args->idleTimeout > 0) {
rDebug("starting idle monitoring thread");
ctx->running = true;
int res = pthread_create( &ctx->monitorThread, 0, idleMonitor,
(void*)ctx );
if(res != 0)
{
rError("error starting idle monitor thread, "
"res = %i, errno = %i", res, errno);
int res = pthread_create(&ctx->monitorThread, 0, idleMonitor, (void *)ctx);
if (res != 0) {
rError(
"error starting idle monitor thread, "
"res = %i, errno = %i",
res, errno);
}
}
if(ctx->args->isDaemon && oldStderr >= 0)
{
if (ctx->args->isDaemon && oldStderr >= 0) {
rInfo("Closing stderr");
close(oldStderr);
oldStderr = -1;
@ -483,11 +450,9 @@ void *encfs_init(fuse_conn_info *conn)
return (void *)ctx;
}
void encfs_destroy( void *_ctx )
{
void encfs_destroy(void *_ctx) {
EncFS_Context *ctx = (EncFS_Context *)_ctx;
if(ctx->args->idleTimeout > 0)
{
if (ctx->args->idleTimeout > 0) {
ctx->running = false;
// wake up the thread if it is waiting..
@ -501,8 +466,7 @@ void encfs_destroy( void *_ctx )
}
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
// initialize the logging library
RLogInit(argc, argv);
@ -526,14 +490,12 @@ int main(int argc, char *argv[])
for (int i = 0; i < MaxFuseArgs; ++i)
encfsArgs->fuseArgv[i] = NULL; // libfuse expects null args..
if(argc == 1 || !processArgs(argc, argv, encfsArgs))
{
if (argc == 1 || !processArgs(argc, argv, encfsArgs)) {
usage(argv[0]);
return EXIT_FAILURE;
}
if(encfsArgs->isVerbose)
{
if (encfsArgs->isVerbose) {
// subscribe to more logging channels..
slog->subscribeTo(GetGlobalChannel("info"));
slog->subscribeTo(GetGlobalChannel("debug"));
@ -611,8 +573,7 @@ int main(int argc, char *argv[])
int returnCode = EXIT_FAILURE;
if( rootInfo )
{
if (rootInfo) {
// turn off delayMount, as our prior call to initFS has already
// respected any delay, and we want future calls to actually
// mount.
@ -623,8 +584,7 @@ int main(int argc, char *argv[])
ctx->args = encfsArgs;
ctx->opts = encfsArgs->opts;
if(encfsArgs->isThreaded == false && encfsArgs->idleTimeout > 0)
{
if (encfsArgs->isThreaded == false && encfsArgs->idleTimeout > 0) {
// xgroup(usage)
cerr << _("Note: requested single-threaded mode, but an idle\n"
"timeout was specified. The filesystem will operate\n"
@ -636,8 +596,7 @@ int main(int argc, char *argv[])
// pass-thru calls..
umask(0);
if(encfsArgs->isDaemon)
{
if (encfsArgs->isDaemon) {
// switch to logging just warning and error messages via syslog
logNode.reset(new SyslogNode("encfs"));
logNode->subscribeTo(GetGlobalChannel("warning"));
@ -651,12 +610,10 @@ int main(int argc, char *argv[])
oldStderr = dup(STDERR_FILENO);
}
try
{
try {
time_t startTime, endTime;
if (encfsArgs->opts->annotate)
cerr << "$STATUS$ fuse_main_start" << endl;
if (encfsArgs->opts->annotate) cerr << "$STATUS$ fuse_main_start" << endl;
// FIXME: workaround for fuse_main returning an error on normal
// exit. Only print information if fuse_main returned
@ -665,20 +622,17 @@ int main(int argc, char *argv[])
// fuse_main returns an error code in newer versions of fuse..
int res = fuse_main(encfsArgs->fuseArgc,
const_cast<char**>(encfsArgs->fuseArgv),
&encfs_oper, (void*)ctx);
const_cast<char **>(encfsArgs->fuseArgv), &encfs_oper,
(void *)ctx);
time(&endTime);
if (encfsArgs->opts->annotate)
cerr << "$STATUS$ fuse_main_end" << endl;
if (encfsArgs->opts->annotate) cerr << "$STATUS$ fuse_main_end" << endl;
if(res == 0)
returnCode = EXIT_SUCCESS;
if (res == 0) returnCode = EXIT_SUCCESS;
if(res != 0 && encfsArgs->isDaemon && (oldStderr >= 0)
&& (endTime - startTime <= 1) )
{
if (res != 0 && encfsArgs->isDaemon && (oldStderr >= 0) &&
(endTime - startTime <= 1)) {
// the users will not have seen any message from fuse, so say a
// few words in libfuse's memory..
FILE *out = fdopen(oldStderr, "a");
@ -688,12 +642,12 @@ int main(int argc, char *argv[])
" - invalid options -- see usage message\n"));
fclose(out);
}
} catch(std::exception &ex)
{
}
catch (std::exception &ex) {
rError(_("Internal error: Caught exception from main loop: %s"),
ex.what());
} catch(...)
{
}
catch (...) {
rError(_("Internal error: Caught unexpected exception"));
}
}
@ -718,9 +672,7 @@ int main(int argc, char *argv[])
const int ActivityCheckInterval = 10;
static bool unmountFS(EncFS_Context *ctx);
static
void * idleMonitor(void *_arg)
{
static void *idleMonitor(void *_arg) {
EncFS_Context *ctx = (EncFS_Context *)_arg;
shared_ptr<EncFS_Args> arg = ctx->args;
@ -729,8 +681,7 @@ void * idleMonitor(void *_arg)
pthread_mutex_lock(&ctx->wakeupMutex);
while(ctx->running)
{
while (ctx->running) {
int usage = ctx->getAndResetUsageCounter();
if (usage == 0 && ctx->isMounted())
@ -738,11 +689,9 @@ void * idleMonitor(void *_arg)
else
idleCycles = 0;
if(idleCycles >= timeoutCycles)
{
if (idleCycles >= timeoutCycles) {
int openCount = ctx->openFileCount();
if( openCount == 0 && unmountFS( ctx ) )
{
if (openCount == 0 && unmountFS(ctx)) {
// wait for main thread to wake us up
pthread_cond_wait(&ctx->wakeupCond, &ctx->wakeupMutex);
break;
@ -751,16 +700,14 @@ void * idleMonitor(void *_arg)
rDebug("num open files: %i", openCount);
}
rDebug("idle cycle count: %i, timeout after %i", idleCycles,
timeoutCycles);
rDebug("idle cycle count: %i, timeout after %i", idleCycles, timeoutCycles);
struct timeval currentTime;
gettimeofday(&currentTime, 0);
struct timespec wakeupTime;
wakeupTime.tv_sec = currentTime.tv_sec + ActivityCheckInterval;
wakeupTime.tv_nsec = currentTime.tv_usec * 1000;
pthread_cond_timedwait( &ctx->wakeupCond,
&ctx->wakeupMutex, &wakeupTime );
pthread_cond_timedwait(&ctx->wakeupCond, &ctx->wakeupMutex, &wakeupTime);
}
pthread_mutex_unlock(&ctx->wakeupMutex);
@ -770,18 +717,15 @@ void * idleMonitor(void *_arg)
return 0;
}
static bool unmountFS(EncFS_Context *ctx)
{
static bool unmountFS(EncFS_Context *ctx) {
shared_ptr<EncFS_Args> arg = ctx->args;
if( arg->opts->mountOnDemand )
{
if (arg->opts->mountOnDemand) {
rDebug("Detaching filesystem %s due to inactivity",
arg->mountPoint.c_str());
ctx->setRoot(shared_ptr<DirNode>());
return false;
} else
{
} else {
// Time to unmount!
// xgroup(diag)
rWarning(_("Unmounting filesystem %s due to inactivity"),
@ -790,4 +734,3 @@ static bool unmountFS(EncFS_Context *ctx)
return true;
}
}

View File

@ -31,8 +31,7 @@
using namespace std;
void genKey( const shared_ptr<Cipher> &cipher )
{
void genKey(const shared_ptr<Cipher> &cipher) {
CipherKey key = cipher->newRandomKey();
// encode with itself
@ -41,13 +40,11 @@ void genKey( const shared_ptr<Cipher> &cipher )
cout << b64Key << "\n";
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
pid_t pid = getpid();
cerr << "pid = " << pid << "\n";
if(argc != 3)
{
if (argc != 3) {
cerr << "usage: makeKey [AES|Blowfish] [128|160|192|224|256]\n";
return 1;
}
@ -63,4 +60,3 @@ int main(int argc, char **argv)
// openssl_shutdown(false);
}

View File

@ -31,39 +31,30 @@
#include <openssl/engine.h>
#endif
unsigned long pthreads_thread_id()
{
return (unsigned long)pthread_self();
}
unsigned long pthreads_thread_id() { return (unsigned long)pthread_self(); }
static pthread_mutex_t *crypto_locks = NULL;
void pthreads_locking_callback( int mode, int n,
const char *caller_file, int caller_line )
{
void pthreads_locking_callback(int mode, int n, const char *caller_file,
int caller_line) {
(void)caller_file;
(void)caller_line;
if(!crypto_locks)
{
if (!crypto_locks) {
rDebug("Allocating %i locks for OpenSSL", CRYPTO_num_locks());
crypto_locks = new pthread_mutex_t[CRYPTO_num_locks()];
for (int i = 0; i < CRYPTO_num_locks(); ++i)
pthread_mutex_init(crypto_locks + i, 0);
}
if(mode & CRYPTO_LOCK)
{
if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(crypto_locks + n);
} else
{
} else {
pthread_mutex_unlock(crypto_locks + n);
}
}
void pthreads_locking_cleanup()
{
if(crypto_locks)
{
void pthreads_locking_cleanup() {
if (crypto_locks) {
for (int i = 0; i < CRYPTO_num_locks(); ++i)
pthread_mutex_destroy(crypto_locks + i);
delete[] crypto_locks;
@ -71,8 +62,7 @@ void pthreads_locking_cleanup()
}
}
void openssl_init(bool threaded)
{
void openssl_init(bool threaded) {
// initialize the SSL library
SSL_load_error_strings();
SSL_library_init();
@ -88,8 +78,7 @@ void openssl_init(bool threaded)
ENGINE_register_all_complete();
#endif // NO_ENGINE
if(threaded)
{
if (threaded) {
// provide locking functions to OpenSSL since we'll be running with
// threads accessing openssl in parallel.
CRYPTO_set_id_callback(pthreads_thread_id);
@ -97,13 +86,10 @@ void openssl_init(bool threaded)
}
}
void openssl_shutdown(bool threaded)
{
void openssl_shutdown(bool threaded) {
#ifndef OPENSSL_NO_ENGINE
ENGINE_cleanup();
#endif
if(threaded)
pthreads_locking_cleanup();
if (threaded) pthreads_locking_cleanup();
}

View File

@ -25,5 +25,3 @@ void openssl_init(bool isThreaded);
void openssl_shutdown(bool isThreaded);
#endif

View File

@ -1,4 +1,5 @@
/* $OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $ */
/* $OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $
*/
/*
* Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com>
@ -28,7 +29,8 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $";
static const char rcsid[] =
"$OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $";
#endif /* LIBC_SCCS and not lint */
//#include "includes.h"
@ -64,9 +66,7 @@ static volatile sig_atomic_t signo;
static void handler(int);
char *
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
{
char *readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) {
ssize_t nr;
int input, output, save_errno;
char ch, *p, *end;
@ -113,8 +113,7 @@ restart:
/* Turn off echo if possible. */
if (tcgetattr(input, &oterm) == 0) {
memcpy(&term, &oterm, sizeof(term));
if (!(flags & RPP_ECHO_ON))
term.c_lflag &= ~(ECHO | ECHONL);
if (!(flags & RPP_ECHO_ON)) term.c_lflag &= ~(ECHO | ECHONL);
#ifdef VSTATUS
if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
term.c_cc[VSTATUS] = _POSIX_VDISABLE;
@ -129,21 +128,17 @@ restart:
end = buf + bufsiz - 1;
for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) {
if (p < end) {
if ((flags & RPP_SEVENBIT))
ch &= 0x7f;
if ((flags & RPP_SEVENBIT)) ch &= 0x7f;
if (isalpha(ch)) {
if ((flags & RPP_FORCELOWER))
ch = tolower(ch);
if ((flags & RPP_FORCEUPPER))
ch = toupper(ch);
if ((flags & RPP_FORCELOWER)) ch = tolower(ch);
if ((flags & RPP_FORCEUPPER)) ch = toupper(ch);
}
*p++ = ch;
}
}
*p = '\0';
save_errno = errno;
if (!(term.c_lflag & ECHO))
(void)write(output, "\n", 1);
if (!(term.c_lflag & ECHO)) (void)write(output, "\n", 1);
/* Restore old terminal settings and signals. */
if (memcmp(&term, &oterm, sizeof(term)) != 0)
@ -155,8 +150,7 @@ restart:
(void)sigaction(SIGTSTP, &savetstp, NULL);
(void)sigaction(SIGTTIN, &savettin, NULL);
(void)sigaction(SIGTTOU, &savettou, NULL);
if (input != STDIN_FILENO)
(void)close(input);
if (input != STDIN_FILENO) (void)close(input);
/*
* If we were interrupted by a signal, resend it to ourselves
@ -188,8 +182,4 @@ getpass(const char *prompt)
}
#endif
static void handler(int s)
{
signo = s;
}
static void handler(int s) { signo = s; }

View File

@ -47,22 +47,18 @@
#endif
#endif
using namespace std;
using namespace rel;
using namespace rlog;
const int FSBlockSize = 256;
static
int checkErrorPropogation( const shared_ptr<Cipher> &cipher,
int size, int byteToChange, const CipherKey &key )
{
static int checkErrorPropogation(const shared_ptr<Cipher> &cipher, int size,
int byteToChange, const CipherKey &key) {
MemBlock orig = MemoryPool::allocate(size);
MemBlock data = MemoryPool::allocate(size);
for(int i=0; i<size; ++i)
{
for (int i = 0; i < size; ++i) {
unsigned char tmp = rand();
orig.data[i] = tmp;
data.data[i] = tmp;
@ -74,11 +70,9 @@ int checkErrorPropogation( const shared_ptr<Cipher> &cipher,
cipher->blockEncode(data.data, size, 0, key);
// intoduce an error in the encoded data, so we can check error propogation
if(byteToChange >= 0 && byteToChange < size)
{
if (byteToChange >= 0 && byteToChange < size) {
unsigned char previousValue = data.data[byteToChange];
do
{
do {
data.data[byteToChange] = rand();
} while (data.data[byteToChange] == previousValue);
}
@ -89,10 +83,8 @@ int checkErrorPropogation( const shared_ptr<Cipher> &cipher,
cipher->blockDecode(data.data, size, 0, key);
int numByteErrors = 0;
for(int i=0; i<size; ++i)
{
if( data.data[i] != orig.data[i] )
++numByteErrors;
for (int i = 0; i < size; ++i) {
if (data.data[i] != orig.data[i]) ++numByteErrors;
}
MemoryPool::release(data);
@ -103,56 +95,32 @@ int checkErrorPropogation( const shared_ptr<Cipher> &cipher,
const char TEST_ROOTDIR[] = "/foo";
static
bool testNameCoding( DirNode &dirNode, bool verbose )
{
static bool testNameCoding(DirNode &dirNode, bool verbose) {
// encrypt a name
const char *name[] = {
"1234567",
"12345678",
"123456789",
"123456789ABCDEF",
"123456789ABCDEF0",
"123456789ABCDEF01",
"test-name",
"test-name2",
"test",
"../test",
"/foo/bar/blah",
"test-name.21",
"test-name.22",
"test-name.o",
"1.test",
"2.test",
"a/b/c/d",
"a/c/d/e",
"b/c/d/e",
"b/a/c/d",
NULL
};
"1234567", "12345678", "123456789",
"123456789ABCDEF", "123456789ABCDEF0", "123456789ABCDEF01",
"test-name", "test-name2", "test",
"../test", "/foo/bar/blah", "test-name.21",
"test-name.22", "test-name.o", "1.test",
"2.test", "a/b/c/d", "a/c/d/e",
"b/c/d/e", "b/a/c/d", NULL};
const char **orig = name;
while(*orig)
{
if(verbose)
cerr << " coding name \"" << *orig << "\"";
while (*orig) {
if (verbose) cerr << " coding name \"" << *orig << "\"";
string encName = dirNode.relativeCipherPath(*orig);
if(verbose)
cerr << " -> \"" << encName.c_str() << "\"";
if (verbose) cerr << " -> \"" << encName.c_str() << "\"";
// decrypt name
string decName = dirNode.plainPath(encName.c_str());
if(decName == *orig)
{
if(verbose)
cerr << " OK\n";
} else
{
if(verbose)
cerr << " FAILED (got " << decName << ")\n";
if (decName == *orig) {
if (verbose) cerr << " OK\n";
} else {
if (verbose) cerr << " FAILED (got " << decName << ")\n";
return false;
}
@ -162,15 +130,13 @@ bool testNameCoding( DirNode &dirNode, bool verbose )
return true;
}
bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
{
bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
// create a random key
if (verbose)
cerr << "Generating new key, output will be different on each run\n\n";
CipherKey key = cipher->newRandomKey();
if(verbose)
cerr << "Testing key save / restore :";
if (verbose) cerr << "Testing key save / restore :";
{
CipherKey encodingKey = cipher->newRandomKey();
int encodedKeySize = cipher->encodedKeySize();
@ -178,27 +144,20 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
cipher->writeKey(key, keyBuf, encodingKey);
CipherKey key2 = cipher->readKey(keyBuf, encodingKey);
if(!key2)
{
if(verbose)
cerr << " FAILED (decode error)\n";
if (!key2) {
if (verbose) cerr << " FAILED (decode error)\n";
return false;
}
if(cipher->compareKey( key, key2 ))
{
if(verbose)
cerr << " OK\n";
} else
{
if(verbose)
cerr << " FAILED\n";
if (cipher->compareKey(key, key2)) {
if (verbose) cerr << " OK\n";
} else {
if (verbose) cerr << " FAILED\n";
return false;
}
}
if(verbose)
cerr << "Testing Config interface load / store :";
if (verbose) cerr << "Testing Config interface load / store :";
{
CipherKey encodingKey = cipher->newRandomKey();
int encodedKeySize = cipher->encodedKeySize();
@ -236,21 +195,15 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
// try decoding key..
CipherKey key2 = cipher->readKey(cfg2.getKeyData(), encodingKey);
if(!key2)
{
if(verbose)
cerr << " FAILED (decode error)\n";
if (!key2) {
if (verbose) cerr << " FAILED (decode error)\n";
return false;
}
if(cipher->compareKey( key, key2 ))
{
if(verbose)
cerr << " OK\n";
} else
{
if(verbose)
cerr << " FAILED\n";
if (cipher->compareKey(key, key2)) {
if (verbose) cerr << " OK\n";
} else {
if (verbose) cerr << " FAILED\n";
return false;
}
}
@ -268,14 +221,13 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false;
fsCfg->nameCoding.reset( new StreamNameIO(
StreamNameIO::CurrentInterface(), cipher, key ) );
fsCfg->nameCoding.reset(
new StreamNameIO(StreamNameIO::CurrentInterface(), cipher, key));
fsCfg->nameCoding->setChainedNameIV(true);
DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);
if(!testNameCoding( dirNode, verbose ))
return false;
if (!testNameCoding(dirNode, verbose)) return false;
}
if (verbose)
@ -283,166 +235,135 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
{
fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false;
fsCfg->nameCoding.reset( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key,
fsCfg->nameCoding.reset(new BlockNameIO(BlockNameIO::CurrentInterface(),
cipher, key,
cipher->cipherBlockSize()));
fsCfg->nameCoding->setChainedNameIV(true);
DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);
if(!testNameCoding( dirNode, verbose ))
return false;
if (!testNameCoding(dirNode, verbose)) return false;
}
if (verbose)
cerr << "Testing name encode/decode (block coding w/ IV chaining, base32)\n";
cerr
<< "Testing name encode/decode (block coding w/ IV chaining, base32)\n";
{
fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false;
fsCfg->nameCoding.reset( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key,
fsCfg->nameCoding.reset(new BlockNameIO(BlockNameIO::CurrentInterface(),
cipher, key,
cipher->cipherBlockSize(), true));
fsCfg->nameCoding->setChainedNameIV(true);
DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);
if(!testNameCoding( dirNode, verbose ))
return false;
if (!testNameCoding(dirNode, verbose)) return false;
}
if(!verbose)
{
if (!verbose) {
{
// test stream mode, this time without IV chaining
fsCfg->nameCoding =
shared_ptr<NameIO>( new StreamNameIO(
StreamNameIO::CurrentInterface(), cipher, key ) );
fsCfg->nameCoding = shared_ptr<NameIO>(
new StreamNameIO(StreamNameIO::CurrentInterface(), cipher, key));
fsCfg->nameCoding->setChainedNameIV(false);
DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);
if(!testNameCoding( dirNode, verbose ))
return false;
if (!testNameCoding(dirNode, verbose)) return false;
}
{
// test block mode, this time without IV chaining
fsCfg->nameCoding = shared_ptr<NameIO>( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key,
fsCfg->nameCoding = shared_ptr<NameIO>(
new BlockNameIO(BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize()));
fsCfg->nameCoding->setChainedNameIV(false);
DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);
if(!testNameCoding( dirNode, verbose ))
return false;
if (!testNameCoding(dirNode, verbose)) return false;
}
}
if(verbose)
cerr << "Testing block encode/decode on full block - ";
if (verbose) cerr << "Testing block encode/decode on full block - ";
{
int numErrors = checkErrorPropogation( cipher,
FSBlockSize, -1, key );
if(numErrors)
{
if(verbose)
cerr << " FAILED!\n";
int numErrors = checkErrorPropogation(cipher, FSBlockSize, -1, key);
if (numErrors) {
if (verbose) cerr << " FAILED!\n";
return false;
} else
{
if(verbose)
cerr << " OK\n";
} else {
if (verbose) cerr << " OK\n";
}
}
if(verbose)
cerr << "Testing block encode/decode on partial block - ";
if (verbose) cerr << "Testing block encode/decode on partial block - ";
{
int numErrors = checkErrorPropogation( cipher,
FSBlockSize-1, -1, key );
if(numErrors)
{
if(verbose)
cerr << " FAILED!\n";
int numErrors = checkErrorPropogation(cipher, FSBlockSize - 1, -1, key);
if (numErrors) {
if (verbose) cerr << " FAILED!\n";
return false;
} else
{
if(verbose)
cerr << " OK\n";
} else {
if (verbose) cerr << " OK\n";
}
}
if(verbose)
cerr << "Checking error propogation in partial block:\n";
if (verbose) cerr << "Checking error propogation in partial block:\n";
{
int minChanges = FSBlockSize - 1;
int maxChanges = 0;
int minAt = 0;
int maxAt = 0;
for(int i=0; i<FSBlockSize-1; ++i)
{
int numErrors = checkErrorPropogation( cipher,
FSBlockSize-1, i, key );
for (int i = 0; i < FSBlockSize - 1; ++i) {
int numErrors = checkErrorPropogation(cipher, FSBlockSize - 1, i, key);
if(numErrors < minChanges)
{
if (numErrors < minChanges) {
minChanges = numErrors;
minAt = i;
}
if(numErrors > maxChanges)
{
if (numErrors > maxChanges) {
maxChanges = numErrors;
maxAt = i;
}
}
if(verbose)
{
if (verbose) {
cerr << "modification of 1 byte affected between " << minChanges
<< " and " << maxChanges << " decoded bytes\n";
cerr << "minimum change at byte " << minAt
<< " and maximum at byte " << maxAt << "\n";
cerr << "minimum change at byte " << minAt << " and maximum at byte "
<< maxAt << "\n";
}
}
if(verbose)
cerr << "Checking error propogation on full block:\n";
if (verbose) cerr << "Checking error propogation on full block:\n";
{
int minChanges = FSBlockSize;
int maxChanges = 0;
int minAt = 0;
int maxAt = 0;
for(int i=0; i<FSBlockSize; ++i)
{
int numErrors = checkErrorPropogation( cipher,
FSBlockSize, i, key );
for (int i = 0; i < FSBlockSize; ++i) {
int numErrors = checkErrorPropogation(cipher, FSBlockSize, i, key);
if(numErrors < minChanges)
{
if (numErrors < minChanges) {
minChanges = numErrors;
minAt = i;
}
if(numErrors > maxChanges)
{
if (numErrors > maxChanges) {
maxChanges = numErrors;
maxAt = i;
}
}
if(verbose)
{
if (verbose) {
cerr << "modification of 1 byte affected between " << minChanges
<< " and " << maxChanges << " decoded bytes\n";
cerr << "minimum change at byte " << minAt
<< " and maximum at byte " << maxAt << "\n";
cerr << "minimum change at byte " << minAt << " and maximum at byte "
<< maxAt << "\n";
}
}
return true;
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
RLogInit(argc, argv);
StdioNode stdLog(STDERR_FILENO);
@ -467,17 +388,13 @@ int main(int argc, char *argv[])
srand(time(0));
// get a list of the available algorithms
std::list<Cipher::CipherAlgorithm> algorithms =
Cipher::GetAlgorithmList();
std::list<Cipher::CipherAlgorithm> algorithms = Cipher::GetAlgorithmList();
std::list<Cipher::CipherAlgorithm>::const_iterator it;
cerr << "Supported Crypto interfaces:\n";
for(it = algorithms.begin(); it != algorithms.end(); ++it)
{
cerr << it->name
<< " ( " << it->iface.name() << " "
<< it->iface.current() << ":"
<< it->iface.revision() << ":"
<< it->iface.age() << " ) : " << it->description << "\n";
for (it = algorithms.begin(); it != algorithms.end(); ++it) {
cerr << it->name << " ( " << it->iface.name() << " " << it->iface.current()
<< ":" << it->iface.revision() << ":" << it->iface.age()
<< " ) : " << it->description << "\n";
cerr << " - key length " << it->keyLength.min() << " to "
<< it->keyLength.max() << " , block size " << it->blockSize.min()
<< " to " << it->blockSize.max() << "\n";
@ -485,29 +402,24 @@ int main(int argc, char *argv[])
cerr << "\n";
cerr << "Testing interfaces\n";
for(it = algorithms.begin(); it != algorithms.end(); ++it)
{
for (it = algorithms.begin(); it != algorithms.end(); ++it) {
int blockSize = it->blockSize.closest(256);
for (int keySize = it->keyLength.min(); keySize <= it->keyLength.max();
keySize += it->keyLength.inc())
{
cerr << it->name << ", key length " << keySize
<< ", block size " << blockSize << ": ";
keySize += it->keyLength.inc()) {
cerr << it->name << ", key length " << keySize << ", block size "
<< blockSize << ": ";
shared_ptr<Cipher> cipher = Cipher::New(it->name, keySize);
if(!cipher)
{
if (!cipher) {
cerr << "FAILED TO CREATE\n";
} else
{
try
{
} else {
try {
if (runTests(cipher, false))
cerr << "OK\n";
else
cerr << "FAILED\n";
} catch( rlog::Error &er )
{
}
catch (rlog::Error &er) {
cerr << "Error: " << er.what() << "\n";
}
}
@ -516,11 +428,9 @@ int main(int argc, char *argv[])
// run one test with verbose output too..
shared_ptr<Cipher> cipher = Cipher::New("AES", 192);
if(!cipher)
{
if (!cipher) {
cerr << "\nNo AES cipher found, skipping verbose test.\n";
} else
{
} else {
cerr << "\nVerbose output for " << cipher->interface().name()
<< " test, key length " << cipher->keySize() * 8 << ", block size "
<< FSBlockSize << ":\n";
@ -532,6 +442,3 @@ int main(int argc, char *argv[])
return 0;
}