mirror of
https://github.com/vgough/encfs.git
synced 2024-11-21 15:33:16 +01:00
reformat using clang
This commit is contained in:
parent
744f56b95d
commit
b3c851982f
52
.clang-format
Normal file
52
.clang-format
Normal 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
|
||||||
|
...
|
||||||
|
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -27,406 +27,347 @@
|
|||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
template<typename Type>
|
template <typename Type>
|
||||||
inline Type min( Type A, Type B )
|
inline Type min(Type A, Type B) {
|
||||||
{
|
return (B < A) ? B : A;
|
||||||
return (B < A) ? B : A;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clearCache( IORequest &req, int blockSize )
|
static void clearCache(IORequest &req, int blockSize) {
|
||||||
{
|
memset(req.data, 0, blockSize);
|
||||||
memset( req.data, 0, blockSize );
|
req.dataLen = 0;
|
||||||
req.dataLen = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockFileIO::BlockFileIO( int blockSize, const FSConfigPtr &cfg )
|
BlockFileIO::BlockFileIO(int blockSize, const FSConfigPtr &cfg)
|
||||||
: _blockSize( blockSize )
|
: _blockSize(blockSize), _allowHoles(cfg->config->allowHoles) {
|
||||||
, _allowHoles( cfg->config->allowHoles )
|
rAssert(_blockSize > 1);
|
||||||
{
|
_cache.data = new unsigned char[_blockSize];
|
||||||
rAssert( _blockSize > 1 );
|
|
||||||
_cache.data = new unsigned char [ _blockSize ];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockFileIO::~BlockFileIO()
|
BlockFileIO::~BlockFileIO() {
|
||||||
{
|
clearCache(_cache, _blockSize);
|
||||||
clearCache( _cache, _blockSize );
|
delete[] _cache.data;
|
||||||
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 can satisfy the request even if _cache.dataLen is too short, because
|
// we always request a full block during reads..
|
||||||
// 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;
|
||||||
// satisfy request from cache
|
if (_cache.dataLen < len) len = _cache.dataLen;
|
||||||
int len = req.dataLen;
|
memcpy(req.data, _cache.data, len);
|
||||||
if(_cache.dataLen < len)
|
return len;
|
||||||
len = _cache.dataLen;
|
} else {
|
||||||
memcpy( req.data, _cache.data, len );
|
if (_cache.dataLen > 0) clearCache(_cache, _blockSize);
|
||||||
return len;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
if(_cache.dataLen > 0)
|
|
||||||
clearCache( _cache, _blockSize );
|
|
||||||
|
|
||||||
// cache results of read -- issue reads for full blocks
|
// cache results of read -- issue reads for full blocks
|
||||||
IORequest tmp;
|
IORequest tmp;
|
||||||
tmp.offset = req.offset;
|
tmp.offset = req.offset;
|
||||||
tmp.data = _cache.data;
|
tmp.data = _cache.data;
|
||||||
tmp.dataLen = _blockSize;
|
tmp.dataLen = _blockSize;
|
||||||
ssize_t result = readOneBlock( tmp );
|
ssize_t result = readOneBlock(tmp);
|
||||||
if(result > 0)
|
if (result > 0) {
|
||||||
{
|
_cache.offset = req.offset;
|
||||||
_cache.offset = req.offset;
|
_cache.dataLen = result; // the amount we really have
|
||||||
_cache.dataLen = result; // the amount we really have
|
if (result > req.dataLen)
|
||||||
if(result > req.dataLen)
|
result = req.dataLen; // only as much as requested
|
||||||
result = req.dataLen; // only as much as requested
|
memcpy(req.data, _cache.data, result);
|
||||||
memcpy( req.data, _cache.data, result );
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// read completely within a single block -- can be handled as-is by
|
|
||||||
// readOneBloc().
|
|
||||||
return cacheReadOneBlock( req );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
size_t size = req.dataLen;
|
|
||||||
|
|
||||||
// if the request is larger then a block, then request each block
|
|
||||||
// individually
|
|
||||||
MemBlock mb; // in case we need to allocate a temporary block..
|
|
||||||
IORequest blockReq; // for requests we may need to make
|
|
||||||
blockReq.dataLen = _blockSize;
|
|
||||||
blockReq.data = NULL;
|
|
||||||
|
|
||||||
unsigned char *out = req.data;
|
|
||||||
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 );
|
|
||||||
blockReq.data = mb.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t readSize = cacheReadOneBlock( blockReq );
|
|
||||||
if(unlikely(readSize <= partialOffset))
|
|
||||||
break; // didn't get enough bytes
|
|
||||||
|
|
||||||
int cpySize = min( (size_t)(readSize - partialOffset), size );
|
|
||||||
rAssert(cpySize <= readSize);
|
|
||||||
|
|
||||||
// if we read to a temporary buffer, then move the data
|
|
||||||
if(blockReq.data != out)
|
|
||||||
memcpy( out, blockReq.data + partialOffset, cpySize );
|
|
||||||
|
|
||||||
result += cpySize;
|
|
||||||
size -= cpySize;
|
|
||||||
out += cpySize;
|
|
||||||
++blockNum;
|
|
||||||
partialOffset = 0;
|
|
||||||
|
|
||||||
if(unlikely(readSize < _blockSize))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mb.data)
|
|
||||||
MemoryPool::release( mb );
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockFileIO::write( const IORequest &req )
|
bool BlockFileIO::cacheWriteOneBlock(const IORequest &req) {
|
||||||
{
|
// cache results of write (before pass-thru, because it may be modified
|
||||||
rAssert( _blockSize != 0 );
|
// 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);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
off_t fileSize = getSize();
|
ssize_t BlockFileIO::read(const IORequest &req) const {
|
||||||
|
rAssert(_blockSize != 0);
|
||||||
|
|
||||||
// where write request begins
|
int partialOffset = req.offset % _blockSize;
|
||||||
off_t blockNum = req.offset / _blockSize;
|
off_t blockNum = req.offset / _blockSize;
|
||||||
int partialOffset = req.offset % _blockSize;
|
ssize_t result = 0;
|
||||||
|
|
||||||
// last block of file (for testing write overlaps with file boundary)
|
if (partialOffset == 0 && req.dataLen <= _blockSize) {
|
||||||
off_t lastFileBlock = fileSize / _blockSize;
|
// read completely within a single block -- can be handled as-is by
|
||||||
ssize_t lastBlockSize = fileSize % _blockSize;
|
// readOneBloc().
|
||||||
|
return cacheReadOneBlock(req);
|
||||||
off_t lastNonEmptyBlock = lastFileBlock;
|
} else {
|
||||||
if(lastBlockSize == 0)
|
|
||||||
--lastNonEmptyBlock;
|
|
||||||
|
|
||||||
if( req.offset > fileSize )
|
|
||||||
{
|
|
||||||
// extend file first to fill hole with 0's..
|
|
||||||
const bool forceWrite = false;
|
|
||||||
padFile( fileSize, req.offset, forceWrite );
|
|
||||||
}
|
|
||||||
|
|
||||||
// check against edge cases where we can just let the base class handle the
|
|
||||||
// request as-is..
|
|
||||||
if(partialOffset == 0 && req.dataLen <= _blockSize)
|
|
||||||
{
|
|
||||||
// if writing a full block.. pretty safe..
|
|
||||||
if( req.dataLen == _blockSize )
|
|
||||||
return cacheWriteOneBlock( req );
|
|
||||||
|
|
||||||
// if writing a partial block, but at least as much as what is
|
|
||||||
// already there..
|
|
||||||
if(blockNum == lastFileBlock && req.dataLen >= lastBlockSize)
|
|
||||||
return cacheWriteOneBlock( req );
|
|
||||||
}
|
|
||||||
|
|
||||||
// have to merge data with existing block(s)..
|
|
||||||
MemBlock mb;
|
|
||||||
|
|
||||||
IORequest blockReq;
|
|
||||||
blockReq.data = NULL;
|
|
||||||
blockReq.dataLen = _blockSize;
|
|
||||||
|
|
||||||
bool ok = true;
|
|
||||||
size_t size = req.dataLen;
|
size_t size = req.dataLen;
|
||||||
unsigned char *inPtr = req.data;
|
|
||||||
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
|
// if the request is larger then a block, then request each block
|
||||||
// no merging with existing data..
|
// individually
|
||||||
if( (toCopy == _blockSize)
|
MemBlock mb; // in case we need to allocate a temporary block..
|
||||||
||(partialOffset == 0 && blockReq.offset + toCopy >= fileSize))
|
IORequest blockReq; // for requests we may need to make
|
||||||
{
|
blockReq.dataLen = _blockSize;
|
||||||
// write directly from buffer
|
blockReq.data = NULL;
|
||||||
blockReq.data = inPtr;
|
|
||||||
blockReq.dataLen = toCopy;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
// need a temporary buffer, since we have to either merge or pad
|
|
||||||
// the data.
|
|
||||||
if(!mb.data)
|
|
||||||
mb = MemoryPool::allocate( _blockSize );
|
|
||||||
memset( mb.data, 0, _blockSize );
|
|
||||||
blockReq.data = mb.data;
|
|
||||||
|
|
||||||
if(blockNum > lastNonEmptyBlock)
|
unsigned char *out = req.data;
|
||||||
{
|
while (size) {
|
||||||
// just pad..
|
blockReq.offset = blockNum * _blockSize;
|
||||||
blockReq.dataLen = toCopy + partialOffset;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
// have to merge with existing block data..
|
|
||||||
blockReq.dataLen = _blockSize;
|
|
||||||
blockReq.dataLen = cacheReadOneBlock( blockReq );
|
|
||||||
|
|
||||||
// extend data if necessary..
|
// if we're reading a full block, then read directly into the
|
||||||
if( partialOffset + toCopy > blockReq.dataLen )
|
// result buffer instead of using a temporary
|
||||||
blockReq.dataLen = partialOffset + toCopy;
|
if (partialOffset == 0 && size >= (size_t)_blockSize)
|
||||||
}
|
blockReq.data = out;
|
||||||
// merge in the data to be written..
|
else {
|
||||||
memcpy( blockReq.data + partialOffset, inPtr, toCopy );
|
if (!mb.data) mb = MemoryPool::allocate(_blockSize);
|
||||||
}
|
blockReq.data = mb.data;
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, write the damn thing!
|
ssize_t readSize = cacheReadOneBlock(blockReq);
|
||||||
if(!cacheWriteOneBlock( blockReq ))
|
if (unlikely(readSize <= partialOffset))
|
||||||
{
|
break; // didn't get enough bytes
|
||||||
ok = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare to start all over with the next block..
|
int cpySize = min((size_t)(readSize - partialOffset), size);
|
||||||
size -= toCopy;
|
rAssert(cpySize <= readSize);
|
||||||
inPtr += toCopy;
|
|
||||||
++blockNum;
|
// if we read to a temporary buffer, then move the data
|
||||||
partialOffset = 0;
|
if (blockReq.data != out)
|
||||||
|
memcpy(out, blockReq.data + partialOffset, cpySize);
|
||||||
|
|
||||||
|
result += cpySize;
|
||||||
|
size -= cpySize;
|
||||||
|
out += cpySize;
|
||||||
|
++blockNum;
|
||||||
|
partialOffset = 0;
|
||||||
|
|
||||||
|
if (unlikely(readSize < _blockSize)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mb.data)
|
if (mb.data) MemoryPool::release(mb);
|
||||||
MemoryPool::release( mb );
|
}
|
||||||
|
|
||||||
return ok;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BlockFileIO::blockSize() const
|
bool BlockFileIO::write(const IORequest &req) {
|
||||||
{
|
rAssert(_blockSize != 0);
|
||||||
return _blockSize;
|
|
||||||
|
off_t fileSize = getSize();
|
||||||
|
|
||||||
|
// where write request begins
|
||||||
|
off_t blockNum = req.offset / _blockSize;
|
||||||
|
int partialOffset = req.offset % _blockSize;
|
||||||
|
|
||||||
|
// last block of file (for testing write overlaps with file boundary)
|
||||||
|
off_t lastFileBlock = fileSize / _blockSize;
|
||||||
|
ssize_t lastBlockSize = fileSize % _blockSize;
|
||||||
|
|
||||||
|
off_t lastNonEmptyBlock = lastFileBlock;
|
||||||
|
if (lastBlockSize == 0) --lastNonEmptyBlock;
|
||||||
|
|
||||||
|
if (req.offset > fileSize) {
|
||||||
|
// extend file first to fill hole with 0's..
|
||||||
|
const bool forceWrite = false;
|
||||||
|
padFile(fileSize, req.offset, forceWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check against edge cases where we can just let the base class handle the
|
||||||
|
// request as-is..
|
||||||
|
if (partialOffset == 0 && req.dataLen <= _blockSize) {
|
||||||
|
// if writing a full block.. pretty safe..
|
||||||
|
if (req.dataLen == _blockSize) return cacheWriteOneBlock(req);
|
||||||
|
|
||||||
|
// if writing a partial block, but at least as much as what is
|
||||||
|
// already there..
|
||||||
|
if (blockNum == lastFileBlock && req.dataLen >= lastBlockSize)
|
||||||
|
return cacheWriteOneBlock(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
// have to merge data with existing block(s)..
|
||||||
|
MemBlock mb;
|
||||||
|
|
||||||
|
IORequest blockReq;
|
||||||
|
blockReq.data = NULL;
|
||||||
|
blockReq.dataLen = _blockSize;
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
size_t size = req.dataLen;
|
||||||
|
unsigned char *inPtr = req.data;
|
||||||
|
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)) {
|
||||||
|
// write directly from buffer
|
||||||
|
blockReq.data = inPtr;
|
||||||
|
blockReq.dataLen = toCopy;
|
||||||
|
} else {
|
||||||
|
// need a temporary buffer, since we have to either merge or pad
|
||||||
|
// the data.
|
||||||
|
if (!mb.data) mb = MemoryPool::allocate(_blockSize);
|
||||||
|
memset(mb.data, 0, _blockSize);
|
||||||
|
blockReq.data = mb.data;
|
||||||
|
|
||||||
|
if (blockNum > lastNonEmptyBlock) {
|
||||||
|
// just pad..
|
||||||
|
blockReq.dataLen = toCopy + partialOffset;
|
||||||
|
} else {
|
||||||
|
// have to merge with existing block data..
|
||||||
|
blockReq.dataLen = _blockSize;
|
||||||
|
blockReq.dataLen = cacheReadOneBlock(blockReq);
|
||||||
|
|
||||||
|
// extend data if necessary..
|
||||||
|
if (partialOffset + toCopy > blockReq.dataLen)
|
||||||
|
blockReq.dataLen = partialOffset + toCopy;
|
||||||
|
}
|
||||||
|
// merge in the data to be written..
|
||||||
|
memcpy(blockReq.data + partialOffset, inPtr, toCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, write the damn thing!
|
||||||
|
if (!cacheWriteOneBlock(blockReq)) {
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare to start all over with the next block..
|
||||||
|
size -= toCopy;
|
||||||
|
inPtr += toCopy;
|
||||||
|
++blockNum;
|
||||||
|
partialOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb.data) MemoryPool::release(mb);
|
||||||
|
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockFileIO::padFile( off_t oldSize, off_t newSize, bool forceWrite )
|
int BlockFileIO::blockSize() const { return _blockSize; }
|
||||||
{
|
|
||||||
off_t oldLastBlock = oldSize / _blockSize;
|
void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
|
||||||
off_t newLastBlock = newSize / _blockSize;
|
off_t oldLastBlock = oldSize / _blockSize;
|
||||||
int newBlockSize = newSize % _blockSize;
|
off_t newLastBlock = newSize / _blockSize;
|
||||||
|
int newBlockSize = newSize % _blockSize;
|
||||||
|
|
||||||
|
IORequest req;
|
||||||
|
MemBlock mb;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
mb = MemoryPool::allocate(_blockSize);
|
||||||
|
req.data = mb.data;
|
||||||
|
|
||||||
|
req.offset = oldLastBlock * _blockSize;
|
||||||
|
req.dataLen = oldSize % _blockSize;
|
||||||
|
int outSize = newSize % _blockSize; // outSize > req.dataLen
|
||||||
|
|
||||||
|
if (outSize) {
|
||||||
|
memset(mb.data, 0, outSize);
|
||||||
|
cacheReadOneBlock(req);
|
||||||
|
req.dataLen = outSize;
|
||||||
|
cacheWriteOneBlock(req);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
rDebug("optimization: not padding last block");
|
||||||
|
} else {
|
||||||
|
mb = MemoryPool::allocate(_blockSize);
|
||||||
|
req.data = mb.data;
|
||||||
|
|
||||||
|
// 1. extend the first block to full length
|
||||||
|
// 2. write the middle empty blocks
|
||||||
|
// 3. write the last block
|
||||||
|
|
||||||
|
req.offset = oldLastBlock * _blockSize;
|
||||||
|
req.dataLen = oldSize % _blockSize;
|
||||||
|
|
||||||
|
// 1. req.dataLen == 0, iff oldSize was already a multiple of blocksize
|
||||||
|
if (req.dataLen != 0) {
|
||||||
|
rDebug("padding block %" PRIi64, oldLastBlock);
|
||||||
|
memset(mb.data, 0, _blockSize);
|
||||||
|
cacheReadOneBlock(req);
|
||||||
|
req.dataLen = _blockSize; // expand to full block size
|
||||||
|
cacheWriteOneBlock(req);
|
||||||
|
++oldLastBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2, pad zero blocks unless holes are allowed
|
||||||
|
if (!_allowHoles) {
|
||||||
|
for (; oldLastBlock != newLastBlock; ++oldLastBlock) {
|
||||||
|
rDebug("padding block %" PRIi64, oldLastBlock);
|
||||||
|
req.offset = oldLastBlock * _blockSize;
|
||||||
|
req.dataLen = _blockSize;
|
||||||
|
memset(mb.data, 0, req.dataLen);
|
||||||
|
cacheWriteOneBlock(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. only necessary if write is forced and block is non 0 length
|
||||||
|
if (forceWrite && newBlockSize) {
|
||||||
|
req.offset = newLastBlock * _blockSize;
|
||||||
|
req.dataLen = newBlockSize;
|
||||||
|
memset(mb.data, 0, req.dataLen);
|
||||||
|
cacheWriteOneBlock(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb.data) MemoryPool::release(mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BlockFileIO::truncateBase(off_t size, FileIO *base) {
|
||||||
|
int partialBlock = size % _blockSize;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
off_t oldSize = getSize();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
const bool forceWrite = true;
|
||||||
|
padFile(oldSize, size, forceWrite);
|
||||||
|
} else if (size == oldSize) {
|
||||||
|
// the easiest case, but least likely....
|
||||||
|
} 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..
|
||||||
|
off_t blockNum = size / _blockSize;
|
||||||
|
MemBlock mb = MemoryPool::allocate(_blockSize);
|
||||||
|
|
||||||
IORequest req;
|
IORequest req;
|
||||||
MemBlock mb;
|
req.offset = blockNum * _blockSize;
|
||||||
|
req.dataLen = _blockSize;
|
||||||
|
req.data = mb.data;
|
||||||
|
|
||||||
if(oldLastBlock == newLastBlock)
|
ssize_t rdSz = cacheReadOneBlock(req);
|
||||||
{
|
|
||||||
// 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 )
|
|
||||||
{
|
|
||||||
mb = MemoryPool::allocate( _blockSize );
|
|
||||||
req.data = mb.data;
|
|
||||||
|
|
||||||
req.offset = oldLastBlock * _blockSize;
|
// do the truncate
|
||||||
req.dataLen = oldSize % _blockSize;
|
if (base) res = base->truncate(size);
|
||||||
int outSize = newSize % _blockSize; // outSize > req.dataLen
|
|
||||||
|
|
||||||
if(outSize)
|
// write back out partial block
|
||||||
{
|
req.dataLen = partialBlock;
|
||||||
memset( mb.data, 0, outSize );
|
bool wrRes = cacheWriteOneBlock(req);
|
||||||
cacheReadOneBlock( req );
|
|
||||||
req.dataLen = outSize;
|
|
||||||
cacheWriteOneBlock( req );
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
rDebug("optimization: not padding last block");
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
mb = MemoryPool::allocate( _blockSize );
|
|
||||||
req.data = mb.data;
|
|
||||||
|
|
||||||
// 1. extend the first block to full length
|
if ((rdSz < 0) || (!wrRes)) {
|
||||||
// 2. write the middle empty blocks
|
// rwarning - unlikely to ever occur..
|
||||||
// 3. write the last block
|
rWarning(_("truncate failure: read %i bytes, partial block of %i"),
|
||||||
|
(int)rdSz, partialBlock);
|
||||||
req.offset = oldLastBlock * _blockSize;
|
|
||||||
req.dataLen = oldSize % _blockSize;
|
|
||||||
|
|
||||||
// 1. req.dataLen == 0, iff oldSize was already a multiple of blocksize
|
|
||||||
if(req.dataLen != 0)
|
|
||||||
{
|
|
||||||
rDebug("padding block %" PRIi64, oldLastBlock);
|
|
||||||
memset( mb.data, 0, _blockSize );
|
|
||||||
cacheReadOneBlock( req );
|
|
||||||
req.dataLen = _blockSize; // expand to full block size
|
|
||||||
cacheWriteOneBlock( req );
|
|
||||||
++oldLastBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2, pad zero blocks unless holes are allowed
|
|
||||||
if(!_allowHoles)
|
|
||||||
{
|
|
||||||
for(; oldLastBlock != newLastBlock; ++oldLastBlock)
|
|
||||||
{
|
|
||||||
rDebug("padding block %" PRIi64, oldLastBlock);
|
|
||||||
req.offset = oldLastBlock * _blockSize;
|
|
||||||
req.dataLen = _blockSize;
|
|
||||||
memset( mb.data, 0, req.dataLen );
|
|
||||||
cacheWriteOneBlock( req );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. only necessary if write is forced and block is non 0 length
|
|
||||||
if(forceWrite && newBlockSize)
|
|
||||||
{
|
|
||||||
req.offset = newLastBlock * _blockSize;
|
|
||||||
req.dataLen = newBlockSize;
|
|
||||||
memset( mb.data, 0, req.dataLen );
|
|
||||||
cacheWriteOneBlock( req );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mb.data)
|
MemoryPool::release(mb);
|
||||||
MemoryPool::release( mb );
|
} else {
|
||||||
|
// truncating on a block bounday. No need to re-encode the last
|
||||||
|
// block..
|
||||||
|
if (base) res = base->truncate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BlockFileIO::truncateBase( off_t size, FileIO *base )
|
|
||||||
{
|
|
||||||
int partialBlock = size % _blockSize;
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
off_t oldSize = getSize();
|
|
||||||
|
|
||||||
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 );
|
|
||||||
|
|
||||||
const bool forceWrite = true;
|
|
||||||
padFile( oldSize, size, forceWrite );
|
|
||||||
} else
|
|
||||||
if( size == oldSize )
|
|
||||||
{
|
|
||||||
// the easiest case, but least likely....
|
|
||||||
} 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..
|
|
||||||
off_t blockNum = size / _blockSize;
|
|
||||||
MemBlock mb = MemoryPool::allocate( _blockSize );
|
|
||||||
|
|
||||||
IORequest req;
|
|
||||||
req.offset = blockNum * _blockSize;
|
|
||||||
req.dataLen = _blockSize;
|
|
||||||
req.data = mb.data;
|
|
||||||
|
|
||||||
ssize_t rdSz = cacheReadOneBlock( req );
|
|
||||||
|
|
||||||
// do the truncate
|
|
||||||
if(base)
|
|
||||||
res = base->truncate( size );
|
|
||||||
|
|
||||||
// write back out partial block
|
|
||||||
req.dataLen = partialBlock;
|
|
||||||
bool wrRes = cacheWriteOneBlock( req );
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
// truncating on a block bounday. No need to re-encode the last
|
|
||||||
// block..
|
|
||||||
if(base)
|
|
||||||
res = base->truncate( size );
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -26,43 +26,40 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Implements block scatter / gather interface. Requires derived classes to
|
Implements block scatter / gather interface. Requires derived classes to
|
||||||
implement readOneBlock() / writeOneBlock() at a minimum.
|
implement readOneBlock() / writeOneBlock() at a minimum.
|
||||||
|
|
||||||
When a partial block write is requested it will be turned into a read of
|
When a partial block write is requested it will be turned into a read of
|
||||||
the existing block, merge with the write request, and a write of the full
|
the existing block, merge with the write request, and a write of the full
|
||||||
block.
|
block.
|
||||||
*/
|
*/
|
||||||
class BlockFileIO : public FileIO
|
class BlockFileIO : public FileIO {
|
||||||
{
|
public:
|
||||||
public:
|
BlockFileIO(int blockSize, const FSConfigPtr &cfg);
|
||||||
BlockFileIO( int blockSize, const FSConfigPtr &cfg );
|
virtual ~BlockFileIO();
|
||||||
virtual ~BlockFileIO();
|
|
||||||
|
|
||||||
// implemented in terms of blocks.
|
// implemented in terms of blocks.
|
||||||
virtual ssize_t read( const IORequest &req ) const;
|
virtual ssize_t read(const IORequest &req) const;
|
||||||
virtual bool write( const IORequest &req );
|
virtual bool write(const IORequest &req);
|
||||||
|
|
||||||
virtual int blockSize() const;
|
virtual int blockSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
int truncateBase(off_t size, FileIO *base);
|
||||||
|
void padFile(off_t oldSize, off_t newSize, bool forceWrite);
|
||||||
|
|
||||||
int truncateBase( off_t size, FileIO *base );
|
// same as read(), except that the request.offset field is guarenteed to be
|
||||||
void padFile( off_t oldSize, off_t newSize, bool forceWrite );
|
// block aligned, and the request size will not be larger then 1 block.
|
||||||
|
virtual ssize_t readOneBlock(const IORequest &req) const = 0;
|
||||||
|
virtual bool writeOneBlock(const IORequest &req) = 0;
|
||||||
|
|
||||||
// same as read(), except that the request.offset field is guarenteed to be
|
ssize_t cacheReadOneBlock(const IORequest &req) const;
|
||||||
// block aligned, and the request size will not be larger then 1 block.
|
bool cacheWriteOneBlock(const IORequest &req);
|
||||||
virtual ssize_t readOneBlock( const IORequest &req ) const =0;
|
|
||||||
virtual bool writeOneBlock( const IORequest &req ) =0;
|
|
||||||
|
|
||||||
ssize_t cacheReadOneBlock( const IORequest &req ) const;
|
|
||||||
bool cacheWriteOneBlock( const IORequest &req );
|
|
||||||
|
|
||||||
int _blockSize;
|
int _blockSize;
|
||||||
bool _allowHoles;
|
bool _allowHoles;
|
||||||
|
|
||||||
// cache last block for speed...
|
// cache last block for speed...
|
||||||
mutable IORequest _cache;
|
mutable IORequest _cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -33,44 +33,42 @@
|
|||||||
using namespace rlog;
|
using namespace rlog;
|
||||||
using namespace rel;
|
using namespace rel;
|
||||||
|
|
||||||
static RLogChannel * Info = DEF_CHANNEL( "info/nameio", Log_Info );
|
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) {
|
||||||
|
int blockSize = 8;
|
||||||
|
if (cipher) blockSize = cipher->cipherBlockSize();
|
||||||
|
|
||||||
static shared_ptr<NameIO> NewBlockNameIO( const Interface &iface,
|
return shared_ptr<NameIO>(
|
||||||
const shared_ptr<Cipher> &cipher, const CipherKey &key )
|
new BlockNameIO(iface, cipher, key, blockSize, false));
|
||||||
{
|
|
||||||
int blockSize = 8;
|
|
||||||
if(cipher)
|
|
||||||
blockSize = cipher->cipherBlockSize();
|
|
||||||
|
|
||||||
return shared_ptr<NameIO>(
|
|
||||||
new BlockNameIO( iface, cipher, key, blockSize, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static shared_ptr<NameIO> NewBlockNameIO32( const Interface &iface,
|
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;
|
int blockSize = 8;
|
||||||
if(cipher)
|
if (cipher) blockSize = cipher->cipherBlockSize();
|
||||||
blockSize = cipher->cipherBlockSize();
|
|
||||||
|
|
||||||
return shared_ptr<NameIO>(
|
return shared_ptr<NameIO>(
|
||||||
new BlockNameIO( iface, cipher, key, blockSize, true));
|
new BlockNameIO(iface, cipher, key, blockSize, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool BlockIO_registered = NameIO::Register("Block",
|
static bool BlockIO_registered = NameIO::Register(
|
||||||
// description of block name encoding algorithm..
|
"Block",
|
||||||
// xgroup(setup)
|
// description of block name encoding algorithm..
|
||||||
gettext_noop("Block encoding, hides file name size somewhat"),
|
// xgroup(setup)
|
||||||
BlockNameIO::CurrentInterface(false),
|
gettext_noop("Block encoding, hides file name size somewhat"),
|
||||||
NewBlockNameIO);
|
BlockNameIO::CurrentInterface(false), NewBlockNameIO);
|
||||||
|
|
||||||
static bool BlockIO32_registered = NameIO::Register("Block32",
|
static bool BlockIO32_registered = NameIO::Register(
|
||||||
// description of block name encoding algorithm..
|
"Block32",
|
||||||
// xgroup(setup)
|
// description of block name encoding algorithm..
|
||||||
gettext_noop("Block encoding with base32 output for case-sensitive systems"),
|
// xgroup(setup)
|
||||||
BlockNameIO::CurrentInterface(true),
|
gettext_noop(
|
||||||
NewBlockNameIO32);
|
"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.
|
- Version 1.0 computed MAC over the filename, but not the padding bytes.
|
||||||
@ -89,180 +87,153 @@ static bool BlockIO32_registered = NameIO::Register("Block32",
|
|||||||
- Version 4.0 adds support for base32, creating names more suitable for
|
- Version 4.0 adds support for base32, creating names more suitable for
|
||||||
case-insensitive filesystems (eg Mac).
|
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
|
||||||
// implement major version 4 plus support for two prior versions
|
if (caseSensitive)
|
||||||
if (caseSensitive)
|
return Interface("nameio/block32", 4, 0, 2);
|
||||||
return Interface("nameio/block32", 4, 0, 2);
|
else
|
||||||
else
|
return Interface("nameio/block", 4, 0, 2);
|
||||||
return Interface("nameio/block", 4, 0, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockNameIO::BlockNameIO( const rel::Interface &iface,
|
BlockNameIO::BlockNameIO(const rel::Interface &iface,
|
||||||
const shared_ptr<Cipher> &cipher,
|
const shared_ptr<Cipher> &cipher, const CipherKey &key,
|
||||||
const CipherKey &key, int blockSize,
|
int blockSize, bool caseSensitiveEncoding)
|
||||||
bool caseSensitiveEncoding )
|
: _interface(iface.current()),
|
||||||
: _interface( iface.current() )
|
_bs(blockSize),
|
||||||
, _bs( blockSize )
|
_cipher(cipher),
|
||||||
, _cipher( cipher )
|
_key(key),
|
||||||
, _key( key )
|
_caseSensitive(caseSensitiveEncoding) {
|
||||||
, _caseSensitive( caseSensitiveEncoding )
|
// just to be safe..
|
||||||
{
|
rAssert(blockSize < 128);
|
||||||
// just to be safe..
|
|
||||||
rAssert( blockSize < 128 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockNameIO::~BlockNameIO()
|
BlockNameIO::~BlockNameIO() {}
|
||||||
{
|
|
||||||
|
Interface BlockNameIO::interface() const {
|
||||||
|
return CurrentInterface(_caseSensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface BlockNameIO::interface() const
|
int BlockNameIO::maxEncodedNameLen(int plaintextNameLen) const {
|
||||||
{
|
// number of blocks, rounded up.. Only an estimate at this point, err on
|
||||||
return CurrentInterface(_caseSensitive);
|
// the size of too much space rather then too little.
|
||||||
|
int numBlocks = (plaintextNameLen + _bs) / _bs;
|
||||||
|
int encodedNameLen = numBlocks * _bs + 2; // 2 checksum bytes
|
||||||
|
if (_caseSensitive)
|
||||||
|
return B256ToB32Bytes(encodedNameLen);
|
||||||
|
else
|
||||||
|
return B256ToB64Bytes(encodedNameLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
int BlockNameIO::maxEncodedNameLen( int plaintextNameLen ) const
|
int BlockNameIO::maxDecodedNameLen(int encodedNameLen) const {
|
||||||
{
|
int decLen256 = _caseSensitive ? B32ToB256Bytes(encodedNameLen)
|
||||||
// number of blocks, rounded up.. Only an estimate at this point, err on
|
: B64ToB256Bytes(encodedNameLen);
|
||||||
// the size of too much space rather then too little.
|
return decLen256 - 2; // 2 checksum bytes removed..
|
||||||
int numBlocks = ( plaintextNameLen + _bs ) / _bs;
|
|
||||||
int encodedNameLen = numBlocks * _bs + 2; // 2 checksum bytes
|
|
||||||
if (_caseSensitive)
|
|
||||||
return B256ToB32Bytes( encodedNameLen );
|
|
||||||
else
|
|
||||||
return B256ToB64Bytes( encodedNameLen );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int BlockNameIO::maxDecodedNameLen( int encodedNameLen ) const
|
int BlockNameIO::encodeName(const char *plaintextName, int length, uint64_t *iv,
|
||||||
{
|
char *encodedName) const {
|
||||||
int decLen256 = _caseSensitive ?
|
// copy the data into the encoding buffer..
|
||||||
B32ToB256Bytes( encodedNameLen ) :
|
memcpy(encodedName + 2, plaintextName, length);
|
||||||
B64ToB256Bytes( encodedNameLen );
|
|
||||||
return decLen256 - 2; // 2 checksum bytes removed..
|
// Pad encryption buffer to block boundary..
|
||||||
|
int padding = _bs - length % _bs;
|
||||||
|
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;
|
||||||
|
|
||||||
|
// include padding in MAC computation
|
||||||
|
unsigned int mac = _cipher->MAC_16((unsigned char *)encodedName + 2,
|
||||||
|
length + padding, _key, iv);
|
||||||
|
|
||||||
|
// add checksum bytes
|
||||||
|
encodedName[0] = (mac >> 8) & 0xff;
|
||||||
|
encodedName[1] = (mac) & 0xff;
|
||||||
|
|
||||||
|
_cipher->blockEncode((unsigned char *)encodedName + 2, length + padding,
|
||||||
|
(uint64_t)mac ^ tmpIV, _key);
|
||||||
|
|
||||||
|
// convert to base 64 ascii
|
||||||
|
int encodedStreamLen = length + 2 + padding;
|
||||||
|
int encLen;
|
||||||
|
|
||||||
|
if (_caseSensitive) {
|
||||||
|
encLen = B256ToB32Bytes(encodedStreamLen);
|
||||||
|
|
||||||
|
changeBase2Inline((unsigned char *)encodedName, encodedStreamLen, 8, 5,
|
||||||
|
true);
|
||||||
|
B32ToAscii((unsigned char *)encodedName, encLen);
|
||||||
|
} else {
|
||||||
|
encLen = B256ToB64Bytes(encodedStreamLen);
|
||||||
|
|
||||||
|
changeBase2Inline((unsigned char *)encodedName, encodedStreamLen, 8, 6,
|
||||||
|
true);
|
||||||
|
B64ToAscii((unsigned char *)encodedName, encLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return encLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BlockNameIO::encodeName( const char *plaintextName, int length,
|
int BlockNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
|
||||||
uint64_t *iv, char *encodedName ) const
|
char *plaintextName) const {
|
||||||
{
|
int decLen256 =
|
||||||
// copy the data into the encoding buffer..
|
_caseSensitive ? B32ToB256Bytes(length) : B64ToB256Bytes(length);
|
||||||
memcpy( encodedName+2, plaintextName, length );
|
int decodedStreamLen = decLen256 - 2;
|
||||||
|
|
||||||
// Pad encryption buffer to block boundary..
|
|
||||||
int padding = _bs - length % _bs;
|
|
||||||
if(padding == 0)
|
|
||||||
padding = _bs; // padding a full extra block!
|
|
||||||
|
|
||||||
memset( encodedName+length+2, (unsigned char)padding, padding );
|
// don't bother trying to decode files which are too small
|
||||||
|
if (decodedStreamLen < _bs) throw ERROR("Filename too small to decode");
|
||||||
// store the IV before it is modified by the MAC call.
|
|
||||||
uint64_t tmpIV = 0;
|
|
||||||
if( iv && _interface >= 3 )
|
|
||||||
tmpIV = *iv;
|
|
||||||
|
|
||||||
// include padding in MAC computation
|
BUFFER_INIT(tmpBuf, 32, (unsigned int)length);
|
||||||
unsigned int mac = _cipher->MAC_16( (unsigned char *)encodedName+2,
|
|
||||||
length+padding, _key, iv );
|
|
||||||
|
|
||||||
// add checksum bytes
|
// decode into tmpBuf,
|
||||||
encodedName[0] = (mac >> 8) & 0xff;
|
if (_caseSensitive) {
|
||||||
encodedName[1] = (mac ) & 0xff;
|
AsciiToB32((unsigned char *)tmpBuf, (unsigned char *)encodedName, length);
|
||||||
|
changeBase2Inline((unsigned char *)tmpBuf, length, 5, 8, false);
|
||||||
|
} else {
|
||||||
|
AsciiToB64((unsigned char *)tmpBuf, (unsigned char *)encodedName, length);
|
||||||
|
changeBase2Inline((unsigned char *)tmpBuf, length, 6, 8, false);
|
||||||
|
}
|
||||||
|
|
||||||
_cipher->blockEncode( (unsigned char *)encodedName+2, length+padding,
|
// pull out the header information
|
||||||
(uint64_t)mac ^ tmpIV, _key);
|
unsigned int mac = ((unsigned int)((unsigned char)tmpBuf[0])) << 8 |
|
||||||
|
((unsigned int)((unsigned char)tmpBuf[1]));
|
||||||
|
|
||||||
// convert to base 64 ascii
|
uint64_t tmpIV = 0;
|
||||||
int encodedStreamLen = length + 2 + padding;
|
if (iv && _interface >= 3) tmpIV = *iv;
|
||||||
int encLen;
|
|
||||||
|
|
||||||
if (_caseSensitive)
|
|
||||||
{
|
|
||||||
encLen = B256ToB32Bytes( encodedStreamLen );
|
|
||||||
|
|
||||||
changeBase2Inline( (unsigned char *)encodedName, encodedStreamLen,
|
_cipher->blockDecode((unsigned char *)tmpBuf + 2, decodedStreamLen,
|
||||||
8, 5, true );
|
(uint64_t)mac ^ tmpIV, _key);
|
||||||
B32ToAscii( (unsigned char *)encodedName, encLen );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
encLen = B256ToB64Bytes( encodedStreamLen );
|
|
||||||
|
|
||||||
changeBase2Inline( (unsigned char *)encodedName, encodedStreamLen,
|
// find out true string length
|
||||||
8, 6, true );
|
int padding = (unsigned char)tmpBuf[2 + decodedStreamLen - 1];
|
||||||
B64ToAscii( (unsigned char *)encodedName, encLen );
|
int finalSize = decodedStreamLen - padding;
|
||||||
}
|
|
||||||
|
|
||||||
return encLen;
|
// might happen if there is an error decoding..
|
||||||
}
|
if (padding > _bs || finalSize < 0) {
|
||||||
|
rDebug("padding, _bx, finalSize = %i, %i, %i", padding, _bs, finalSize);
|
||||||
int BlockNameIO::decodeName( const char *encodedName, int length,
|
throw ERROR("invalid padding size");
|
||||||
uint64_t *iv, char *plaintextName ) const
|
}
|
||||||
{
|
|
||||||
int decLen256 = _caseSensitive ?
|
// copy out the result..
|
||||||
B32ToB256Bytes( length ) :
|
memcpy(plaintextName, tmpBuf + 2, finalSize);
|
||||||
B64ToB256Bytes( length );
|
plaintextName[finalSize] = '\0';
|
||||||
int decodedStreamLen = decLen256 - 2;
|
|
||||||
|
// check the mac
|
||||||
// don't bother trying to decode files which are too small
|
unsigned int mac2 = _cipher->MAC_16((const unsigned char *)tmpBuf + 2,
|
||||||
if(decodedStreamLen < _bs)
|
decodedStreamLen, _key, iv);
|
||||||
throw ERROR("Filename too small to decode");
|
|
||||||
|
BUFFER_RESET(tmpBuf);
|
||||||
BUFFER_INIT( tmpBuf, 32, (unsigned int)length );
|
|
||||||
|
if (mac2 != mac) {
|
||||||
// decode into tmpBuf,
|
rDebug("checksum mismatch: expected %u, got %u", mac, mac2);
|
||||||
if (_caseSensitive)
|
rDebug("on decode of %i bytes", finalSize);
|
||||||
{
|
throw ERROR("checksum mismatch in filename decode");
|
||||||
AsciiToB32((unsigned char *)tmpBuf, (unsigned char *)encodedName, length);
|
}
|
||||||
changeBase2Inline((unsigned char *)tmpBuf, length, 5, 8, false);
|
|
||||||
} else
|
return finalSize;
|
||||||
{
|
|
||||||
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]));
|
|
||||||
|
|
||||||
uint64_t tmpIV = 0;
|
|
||||||
if( iv && _interface >= 3 )
|
|
||||||
tmpIV = *iv;
|
|
||||||
|
|
||||||
_cipher->blockDecode( (unsigned char *)tmpBuf+2, decodedStreamLen,
|
|
||||||
(uint64_t)mac ^ tmpIV, _key);
|
|
||||||
|
|
||||||
// find out true string length
|
|
||||||
int padding = (unsigned char)tmpBuf[2+decodedStreamLen-1];
|
|
||||||
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);
|
|
||||||
throw ERROR( "invalid padding size" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy out the result..
|
|
||||||
memcpy(plaintextName, tmpBuf+2, finalSize);
|
|
||||||
plaintextName[finalSize] = '\0';
|
|
||||||
|
|
||||||
// check the mac
|
|
||||||
unsigned int mac2 = _cipher->MAC_16((const unsigned char *)tmpBuf+2,
|
|
||||||
decodedStreamLen, _key, iv);
|
|
||||||
|
|
||||||
BUFFER_RESET( tmpBuf );
|
|
||||||
|
|
||||||
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" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return finalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockNameIO::Enabled()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BlockNameIO::Enabled() { return true; }
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -32,38 +32,35 @@ class Cipher;
|
|||||||
mode to encode filenames. The filenames are padded to be a multiple of the
|
mode to encode filenames. The filenames are padded to be a multiple of the
|
||||||
cipher block size.
|
cipher block size.
|
||||||
*/
|
*/
|
||||||
class BlockNameIO : public NameIO
|
class BlockNameIO : public NameIO {
|
||||||
{
|
public:
|
||||||
public:
|
static rel::Interface CurrentInterface(bool caseSensitive = false);
|
||||||
static rel::Interface CurrentInterface(bool caseSensitive = false);
|
|
||||||
|
|
||||||
BlockNameIO( const rel::Interface &iface,
|
BlockNameIO(const rel::Interface &iface, const shared_ptr<Cipher> &cipher,
|
||||||
const shared_ptr<Cipher> &cipher,
|
const CipherKey &key, int blockSize,
|
||||||
const CipherKey &key, int blockSize,
|
bool caseSensitiveEncoding = false);
|
||||||
bool caseSensitiveEncoding = false );
|
virtual ~BlockNameIO();
|
||||||
virtual ~BlockNameIO();
|
|
||||||
|
|
||||||
virtual rel::Interface interface() const;
|
virtual rel::Interface interface() const;
|
||||||
|
|
||||||
virtual int maxEncodedNameLen( int plaintextNameLen ) const;
|
virtual int maxEncodedNameLen(int plaintextNameLen) const;
|
||||||
virtual int maxDecodedNameLen( int encodedNameLen ) const;
|
virtual int maxDecodedNameLen(int encodedNameLen) const;
|
||||||
|
|
||||||
// hack to help with static builds
|
// hack to help with static builds
|
||||||
static bool Enabled();
|
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;
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
int _interface;
|
virtual int encodeName(const char *plaintextName, int length, uint64_t *iv,
|
||||||
int _bs;
|
char *encodedName) const;
|
||||||
shared_ptr<Cipher> _cipher;
|
virtual int decodeName(const char *encodedName, int length, uint64_t *iv,
|
||||||
CipherKey _key;
|
char *plaintextName) const;
|
||||||
bool _caseSensitive;
|
|
||||||
|
private:
|
||||||
|
int _interface;
|
||||||
|
int _bs;
|
||||||
|
shared_ptr<Cipher> _cipher;
|
||||||
|
CipherKey _key;
|
||||||
|
bool _caseSensitive;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
285
encfs/Cipher.cpp
285
encfs/Cipher.cpp
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -38,191 +38,164 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace rel;
|
using namespace rel;
|
||||||
|
|
||||||
#define REF_MODULE(TYPE) \
|
#define REF_MODULE(TYPE) \
|
||||||
if( !TYPE::Enabled() ) \
|
if (!TYPE::Enabled()) cerr << "referenceModule: should never happen\n";
|
||||||
cerr << "referenceModule: should never happen\n";
|
|
||||||
|
|
||||||
static
|
static void AddSymbolReferences() {
|
||||||
void AddSymbolReferences()
|
REF_MODULE(SSL_Cipher)
|
||||||
{
|
REF_MODULE(NullCipher)
|
||||||
REF_MODULE(SSL_Cipher)
|
|
||||||
REF_MODULE(NullCipher)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CipherAlg {
|
||||||
struct CipherAlg
|
bool hidden;
|
||||||
{
|
Cipher::CipherConstructor constructor;
|
||||||
bool hidden;
|
string description;
|
||||||
Cipher::CipherConstructor constructor;
|
Interface iface;
|
||||||
string description;
|
Range keyLength;
|
||||||
Interface iface;
|
Range blockSize;
|
||||||
Range keyLength;
|
|
||||||
Range blockSize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef multimap< string, CipherAlg> CipherMap_t;
|
typedef multimap<string, CipherAlg> CipherMap_t;
|
||||||
static CipherMap_t *gCipherMap = NULL;
|
static CipherMap_t *gCipherMap = NULL;
|
||||||
|
|
||||||
std::list<Cipher::CipherAlgorithm>
|
std::list<Cipher::CipherAlgorithm> Cipher::GetAlgorithmList(
|
||||||
Cipher::GetAlgorithmList( bool includeHidden )
|
bool includeHidden) {
|
||||||
{
|
AddSymbolReferences();
|
||||||
AddSymbolReferences();
|
|
||||||
|
|
||||||
list<CipherAlgorithm> result;
|
list<CipherAlgorithm> result;
|
||||||
|
|
||||||
if(!gCipherMap)
|
if (!gCipherMap) return result;
|
||||||
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) {
|
||||||
|
CipherAlgorithm tmp;
|
||||||
|
tmp.name = it->first;
|
||||||
|
tmp.description = it->second.description;
|
||||||
|
tmp.iface = it->second.iface;
|
||||||
|
tmp.keyLength = it->second.keyLength;
|
||||||
|
tmp.blockSize = it->second.blockSize;
|
||||||
|
|
||||||
|
result.push_back(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Cipher::Register(const char *name, const char *description,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
CipherAlg ca;
|
||||||
|
ca.hidden = hidden;
|
||||||
|
ca.constructor = fn;
|
||||||
|
ca.description = description;
|
||||||
|
ca.iface = iface;
|
||||||
|
ca.keyLength = keyLength;
|
||||||
|
ca.blockSize = blockSize;
|
||||||
|
|
||||||
|
gCipherMap->insert(make_pair(string(name), ca));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
|
||||||
|
shared_ptr<Cipher> result;
|
||||||
|
|
||||||
|
if (gCipherMap) {
|
||||||
|
CipherMap_t::const_iterator it = gCipherMap->find(name);
|
||||||
|
if (it != gCipherMap->end()) {
|
||||||
|
CipherConstructor fn = it->second.constructor;
|
||||||
|
// use current interface..
|
||||||
|
result = (*fn)(it->second.iface, keyLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) {
|
||||||
|
shared_ptr<Cipher> result;
|
||||||
|
if (gCipherMap) {
|
||||||
CipherMap_t::const_iterator it;
|
CipherMap_t::const_iterator it;
|
||||||
CipherMap_t::const_iterator mapEnd = gCipherMap->end();
|
CipherMap_t::const_iterator mapEnd = gCipherMap->end();
|
||||||
for(it = gCipherMap->begin(); it != mapEnd; ++it)
|
|
||||||
{
|
|
||||||
if(includeHidden || !it->second.hidden)
|
|
||||||
{
|
|
||||||
CipherAlgorithm tmp;
|
|
||||||
tmp.name = it->first;
|
|
||||||
tmp.description = it->second.description;
|
|
||||||
tmp.iface = it->second.iface;
|
|
||||||
tmp.keyLength = it->second.keyLength;
|
|
||||||
tmp.blockSize = it->second.blockSize;
|
|
||||||
|
|
||||||
result.push_back( tmp );
|
for (it = gCipherMap->begin(); it != mapEnd; ++it) {
|
||||||
}
|
// TODO: we should look for the newest implementation..
|
||||||
|
if (it->second.iface.implements(iface)) {
|
||||||
|
CipherConstructor fn = it->second.constructor;
|
||||||
|
// pass in requested interface..
|
||||||
|
result = (*fn)(iface, keyLen);
|
||||||
|
|
||||||
|
// if we're not going to compare the options, then just stop
|
||||||
|
// now..
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cipher::Register(const char *name, const char *description,
|
Cipher::Cipher() {}
|
||||||
const Interface &iface, CipherConstructor fn, bool hidden)
|
|
||||||
{
|
Cipher::~Cipher() {}
|
||||||
Range keyLength(-1,-1,1);
|
|
||||||
Range blockSize(-1,-1,1);
|
unsigned int Cipher::MAC_32(const unsigned char *src, int len,
|
||||||
return Cipher::Register( name, description, iface,
|
const CipherKey &key, uint64_t *chainedIV) const {
|
||||||
keyLength, blockSize, fn, hidden );
|
uint64_t mac64 = MAC_64(src, len, key, chainedIV);
|
||||||
|
|
||||||
|
unsigned int mac32 = ((mac64 >> 32) & 0xffffffff) ^ (mac64 & 0xffffffff);
|
||||||
|
|
||||||
|
return mac32;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cipher::Register(const char *name, const char *description,
|
unsigned int Cipher::MAC_16(const unsigned char *src, int len,
|
||||||
const Interface &iface, const Range &keyLength,
|
const CipherKey &key, uint64_t *chainedIV) const {
|
||||||
const Range &blockSize,
|
uint64_t mac64 = MAC_64(src, len, key, chainedIV);
|
||||||
CipherConstructor fn, bool hidden)
|
|
||||||
{
|
|
||||||
if(!gCipherMap)
|
|
||||||
gCipherMap = new CipherMap_t;
|
|
||||||
|
|
||||||
CipherAlg ca;
|
unsigned int mac32 = ((mac64 >> 32) & 0xffffffff) ^ (mac64 & 0xffffffff);
|
||||||
ca.hidden = hidden;
|
unsigned int mac16 = ((mac32 >> 16) & 0xffff) ^ (mac32 & 0xffff);
|
||||||
ca.constructor = fn;
|
|
||||||
ca.description = description;
|
|
||||||
ca.iface = iface;
|
|
||||||
ca.keyLength = keyLength;
|
|
||||||
ca.blockSize = blockSize;
|
|
||||||
|
|
||||||
gCipherMap->insert( make_pair(string(name), ca) );
|
return mac16;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<Cipher> Cipher::New(const string &name, int keyLen)
|
bool Cipher::nameEncode(unsigned char *data, int len, uint64_t iv64,
|
||||||
{
|
const CipherKey &key) const {
|
||||||
shared_ptr<Cipher> result;
|
return streamEncode(data, len, iv64, key);
|
||||||
|
|
||||||
if(gCipherMap)
|
|
||||||
{
|
|
||||||
CipherMap_t::const_iterator it = gCipherMap->find( name );
|
|
||||||
if(it != gCipherMap->end())
|
|
||||||
{
|
|
||||||
CipherConstructor fn = it->second.constructor;
|
|
||||||
// use current interface..
|
|
||||||
result = (*fn)( it->second.iface, keyLen );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<Cipher> Cipher::New( const Interface &iface, int keyLen )
|
bool Cipher::nameDecode(unsigned char *data, int len, uint64_t iv64,
|
||||||
{
|
const CipherKey &key) const {
|
||||||
shared_ptr<Cipher> result;
|
return streamDecode(data, len, iv64, key);
|
||||||
if(gCipherMap)
|
|
||||||
{
|
|
||||||
CipherMap_t::const_iterator it;
|
|
||||||
CipherMap_t::const_iterator mapEnd = gCipherMap->end();
|
|
||||||
|
|
||||||
for(it = gCipherMap->begin(); it != mapEnd; ++it)
|
|
||||||
{
|
|
||||||
// TODO: we should look for the newest implementation..
|
|
||||||
if( it->second.iface.implements( iface ) )
|
|
||||||
{
|
|
||||||
CipherConstructor fn = it->second.constructor;
|
|
||||||
// pass in requested interface..
|
|
||||||
result = (*fn)( iface, keyLen );
|
|
||||||
|
|
||||||
// if we're not going to compare the options, then just stop
|
|
||||||
// now..
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cipher::Cipher()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Cipher::~Cipher()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Cipher::MAC_32( const unsigned char *src, int len,
|
|
||||||
const CipherKey &key, uint64_t *chainedIV ) const
|
|
||||||
{
|
|
||||||
uint64_t mac64 = MAC_64( src, len, key, chainedIV );
|
|
||||||
|
|
||||||
unsigned int mac32 = ((mac64 >> 32) & 0xffffffff) ^ (mac64 & 0xffffffff);
|
|
||||||
|
|
||||||
return mac32;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Cipher::MAC_16( const unsigned char *src, int len,
|
|
||||||
const CipherKey &key, uint64_t *chainedIV ) const
|
|
||||||
{
|
|
||||||
uint64_t mac64 = MAC_64( src, len, key, chainedIV );
|
|
||||||
|
|
||||||
unsigned int mac32 = ((mac64 >> 32) & 0xffffffff) ^ (mac64 & 0xffffffff);
|
|
||||||
unsigned int mac16 = ((mac32 >> 16) & 0xffff) ^ (mac32 & 0xffff);
|
|
||||||
|
|
||||||
return mac16;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
return streamDecode( data, len, iv64, key );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string Cipher::encodeAsString(const CipherKey &key,
|
string Cipher::encodeAsString(const CipherKey &key,
|
||||||
const CipherKey &encodingKey )
|
const CipherKey &encodingKey) {
|
||||||
{
|
int encodedKeySize = this->encodedKeySize();
|
||||||
int encodedKeySize = this->encodedKeySize();
|
unsigned char *keyBuf = new unsigned char[encodedKeySize];
|
||||||
unsigned char *keyBuf = new unsigned char[ encodedKeySize ];
|
|
||||||
|
|
||||||
// write the key, encoding it with itself.
|
// write the key, encoding it with itself.
|
||||||
this->writeKey( key, keyBuf, encodingKey );
|
this->writeKey(key, keyBuf, encodingKey);
|
||||||
|
|
||||||
int b64Len = B256ToB64Bytes( encodedKeySize );
|
int b64Len = B256ToB64Bytes(encodedKeySize);
|
||||||
unsigned char *b64Key = new unsigned char[ b64Len + 1 ];
|
unsigned char *b64Key = new unsigned char[b64Len + 1];
|
||||||
|
|
||||||
changeBase2( keyBuf, encodedKeySize, 8, b64Key, b64Len, 6 );
|
changeBase2(keyBuf, encodedKeySize, 8, b64Key, b64Len, 6);
|
||||||
B64ToAscii( b64Key, b64Len );
|
B64ToAscii(b64Key, b64Len);
|
||||||
b64Key[ b64Len - 1 ] = '\0';
|
b64Key[b64Len - 1] = '\0';
|
||||||
|
|
||||||
return string( (const char *)b64Key );
|
return string((const char *)b64Key);
|
||||||
}
|
}
|
||||||
|
203
encfs/Cipher.h
203
encfs/Cipher.h
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -37,129 +37,116 @@
|
|||||||
Cipher's should register themselves so they can be instanciated via
|
Cipher's should register themselves so they can be instanciated via
|
||||||
Cipher::New().
|
Cipher::New().
|
||||||
*/
|
*/
|
||||||
class Cipher
|
class Cipher {
|
||||||
{
|
public:
|
||||||
public:
|
// if no key length was indicated when cipher was registered, then keyLen
|
||||||
// if no key length was indicated when cipher was registered, then keyLen
|
// <= 0 will be used.
|
||||||
// <= 0 will be used.
|
typedef shared_ptr<Cipher>(*CipherConstructor)(const rel::Interface &iface,
|
||||||
typedef shared_ptr<Cipher> (*CipherConstructor)( const rel::Interface &iface,
|
int keyLenBits);
|
||||||
int keyLenBits );
|
|
||||||
|
|
||||||
struct CipherAlgorithm
|
struct CipherAlgorithm {
|
||||||
{
|
std::string name;
|
||||||
std::string name;
|
std::string description;
|
||||||
std::string description;
|
rel::Interface iface;
|
||||||
rel::Interface iface;
|
Range keyLength;
|
||||||
Range keyLength;
|
Range blockSize;
|
||||||
Range blockSize;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
typedef std::list<CipherAlgorithm> AlgorithmList;
|
||||||
|
static AlgorithmList GetAlgorithmList(bool includeHidden = false);
|
||||||
|
|
||||||
typedef std::list<CipherAlgorithm> AlgorithmList;
|
static shared_ptr<Cipher> New(const rel::Interface &iface, int keyLen = -1);
|
||||||
static AlgorithmList GetAlgorithmList( bool includeHidden = false );
|
static shared_ptr<Cipher> New(const std::string &cipherName, int keyLen = -1);
|
||||||
|
|
||||||
|
static bool Register(const char *cipherName, const char *description,
|
||||||
|
const rel::Interface &iface,
|
||||||
|
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 shared_ptr<Cipher> New( const rel::Interface &iface,
|
Cipher();
|
||||||
int keyLen = -1);
|
virtual ~Cipher();
|
||||||
static shared_ptr<Cipher> New( const std::string &cipherName,
|
|
||||||
int keyLen = -1 );
|
|
||||||
|
|
||||||
|
virtual rel::Interface interface() const = 0;
|
||||||
|
|
||||||
static bool Register(const char *cipherName,
|
// create a new key based on a password
|
||||||
const char *description,
|
// if iterationCount == 0, then iteration count will be determined
|
||||||
const rel::Interface &iface,
|
// by newKey function and filled in.
|
||||||
CipherConstructor constructor,
|
// If iterationCount == 0, then desiredFunctionDuration is how many
|
||||||
bool hidden = false);
|
// milliseconds the password derivation function should take to run.
|
||||||
static bool Register(const char *cipherName,
|
virtual CipherKey newKey(const char *password, int passwdLength,
|
||||||
const char *description,
|
int &iterationCount, long desiredFunctionDuration,
|
||||||
const rel::Interface &iface,
|
const unsigned char *salt, int saltLen) = 0;
|
||||||
const Range &keyLength, const Range &blockSize,
|
// deprecated - for backward compatibility
|
||||||
CipherConstructor constructor,
|
virtual CipherKey newKey(const char *password, int passwdLength) = 0;
|
||||||
bool hidden = false);
|
// create a new random key
|
||||||
|
virtual CipherKey newRandomKey() = 0;
|
||||||
|
|
||||||
|
// data must be len encodedKeySize()
|
||||||
|
virtual CipherKey readKey(const unsigned char *data,
|
||||||
|
const CipherKey &encodingKey,
|
||||||
|
bool checkKey = true) = 0;
|
||||||
|
virtual void writeKey(const CipherKey &key, unsigned char *data,
|
||||||
|
const CipherKey &encodingKey) = 0;
|
||||||
|
|
||||||
Cipher();
|
virtual std::string encodeAsString(const CipherKey &key,
|
||||||
virtual ~Cipher();
|
const CipherKey &encodingKey);
|
||||||
|
|
||||||
virtual rel::Interface interface() const =0;
|
// for testing purposes
|
||||||
|
virtual bool compareKey(const CipherKey &A, const CipherKey &B) const = 0;
|
||||||
|
|
||||||
// create a new key based on a password
|
// meta-data about the cypher
|
||||||
// if iterationCount == 0, then iteration count will be determined
|
virtual int keySize() const = 0;
|
||||||
// by newKey function and filled in.
|
virtual int encodedKeySize() const = 0; // size
|
||||||
// If iterationCount == 0, then desiredFunctionDuration is how many
|
virtual int cipherBlockSize() const = 0; // size of a cipher block
|
||||||
// milliseconds the password derivation function should take to run.
|
|
||||||
virtual CipherKey newKey(const char *password, int passwdLength,
|
|
||||||
int &iterationCount, long desiredFunctionDuration,
|
|
||||||
const unsigned char *salt, int saltLen) =0;
|
|
||||||
// deprecated - for backward compatibility
|
|
||||||
virtual CipherKey newKey(const char *password, int passwdLength ) =0;
|
|
||||||
// create a new random key
|
|
||||||
virtual CipherKey newRandomKey() =0;
|
|
||||||
|
|
||||||
// data must be len encodedKeySize()
|
// fill the supplied buffer with random data
|
||||||
virtual CipherKey readKey(const unsigned char *data,
|
// The data may be pseudo random and might not be suitable for key
|
||||||
const CipherKey &encodingKey,
|
// generation. For generating keys, uses newRandomKey() instead.
|
||||||
bool checkKey = true) =0;
|
// Returns true on success, false on failure.
|
||||||
virtual void writeKey(const CipherKey &key, unsigned char *data,
|
virtual bool randomize(unsigned char *buf, int len,
|
||||||
const CipherKey &encodingKey) =0;
|
bool strongRandom) const = 0;
|
||||||
|
|
||||||
virtual std::string encodeAsString(const CipherKey &key,
|
// 64 bit MAC of the data with the given key
|
||||||
const CipherKey &encodingKey );
|
virtual uint64_t MAC_64(const unsigned char *src, int len,
|
||||||
|
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;
|
||||||
|
|
||||||
// for testing purposes
|
// functional interfaces
|
||||||
virtual bool compareKey( const CipherKey &A, const CipherKey &B ) const =0;
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
// meta-data about the cypher
|
/*
|
||||||
virtual int keySize() const=0;
|
These are just aliases of streamEncode / streamDecode, but there are
|
||||||
virtual int encodedKeySize() const=0; // size
|
provided here for backward compatibility for earlier ciphers that has
|
||||||
virtual int cipherBlockSize() const=0; // size of a cipher block
|
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;
|
||||||
|
|
||||||
// fill the supplied buffer with random data
|
/*
|
||||||
// The data may be pseudo random and might not be suitable for key
|
Block encoding of data in-place. The data size should be a multiple of
|
||||||
// generation. For generating keys, uses newRandomKey() instead.
|
the cipher block size.
|
||||||
// Returns true on success, false on failure.
|
*/
|
||||||
virtual bool randomize( unsigned char *buf, int len,
|
virtual bool blockEncode(unsigned char *buf, int size, uint64_t iv64,
|
||||||
bool strongRandom ) const =0;
|
const CipherKey &key) const = 0;
|
||||||
|
virtual bool blockDecode(unsigned char *buf, int size, uint64_t iv64,
|
||||||
// 64 bit MAC of the data with the given key
|
const CipherKey &key) const = 0;
|
||||||
virtual uint64_t MAC_64( const unsigned char *src, int len,
|
|
||||||
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;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
/*
|
|
||||||
These are just aliases of streamEncode / streamDecode, but there are
|
|
||||||
provided here for backward compatibility for earlier ciphers that has
|
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -37,401 +37,326 @@
|
|||||||
*/
|
*/
|
||||||
static rel::Interface CipherFileIO_iface("FileIO/Cipher", 2, 0, 1);
|
static rel::Interface CipherFileIO_iface("FileIO/Cipher", 2, 0, 1);
|
||||||
|
|
||||||
const int HEADER_SIZE = 8; // 64 bit initialization vector..
|
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;
|
||||||
int blockBoundary = fsBlockSize % cipherBlockSize ;
|
if (blockBoundary != 0) {
|
||||||
if(blockBoundary != 0)
|
rError("CipherFileIO: blocks should be multiple of cipher block size");
|
||||||
{
|
return true;
|
||||||
rError("CipherFileIO: blocks should be multiple of cipher block size");
|
} else
|
||||||
return true;
|
return false;
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherFileIO::CipherFileIO( const shared_ptr<FileIO> &_base,
|
CipherFileIO::CipherFileIO(const shared_ptr<FileIO> &_base,
|
||||||
const FSConfigPtr &cfg)
|
const FSConfigPtr &cfg)
|
||||||
: BlockFileIO( cfg->config->blockSize, cfg )
|
: BlockFileIO(cfg->config->blockSize, cfg),
|
||||||
, base( _base )
|
base(_base),
|
||||||
, haveHeader( cfg->config->uniqueIV )
|
haveHeader(cfg->config->uniqueIV),
|
||||||
, externalIV( 0 )
|
externalIV(0),
|
||||||
, fileIV( 0 )
|
fileIV(0),
|
||||||
, lastFlags( 0 )
|
lastFlags(0) {
|
||||||
{
|
fsConfig = cfg;
|
||||||
fsConfig = cfg;
|
cipher = cfg->cipher;
|
||||||
cipher = cfg->cipher;
|
key = cfg->key;
|
||||||
key = cfg->key;
|
|
||||||
|
|
||||||
static bool warnOnce = false;
|
static bool warnOnce = false;
|
||||||
|
|
||||||
if(!warnOnce)
|
if (!warnOnce)
|
||||||
warnOnce = checkSize( fsConfig->config->blockSize,
|
warnOnce = checkSize(fsConfig->config->blockSize,
|
||||||
fsConfig->cipher->cipherBlockSize() );
|
fsConfig->cipher->cipherBlockSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherFileIO::~CipherFileIO()
|
CipherFileIO::~CipherFileIO() {}
|
||||||
{
|
|
||||||
|
rel::Interface CipherFileIO::interface() const { return CipherFileIO_iface; }
|
||||||
|
|
||||||
|
int CipherFileIO::open(int flags) {
|
||||||
|
int res = base->open(flags);
|
||||||
|
|
||||||
|
if (res >= 0) lastFlags = flags;
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
rel::Interface CipherFileIO::interface() const
|
void CipherFileIO::setFileName(const char *fileName) {
|
||||||
{
|
base->setFileName(fileName);
|
||||||
return CipherFileIO_iface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CipherFileIO::open( int flags )
|
const char *CipherFileIO::getFileName() const { return base->getFileName(); }
|
||||||
{
|
|
||||||
int res = base->open( flags );
|
|
||||||
|
|
||||||
if( res >= 0 )
|
|
||||||
lastFlags = flags;
|
|
||||||
|
|
||||||
return res;
|
bool CipherFileIO::setIV(uint64_t iv) {
|
||||||
}
|
rDebug("in setIV, current IV = %" PRIu64 ", new IV = %" PRIu64
|
||||||
|
", fileIV = %" PRIu64,
|
||||||
void CipherFileIO::setFileName( const char *fileName )
|
externalIV, iv, fileIV);
|
||||||
{
|
if (externalIV == 0) {
|
||||||
base->setFileName( fileName );
|
// 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;
|
||||||
const char *CipherFileIO::getFileName() const
|
if (fileIV != 0)
|
||||||
{
|
rWarning("fileIV initialized before externalIV! (%" PRIu64 ", %" PRIu64
|
||||||
return base->getFileName();
|
")",
|
||||||
}
|
fileIV, externalIV);
|
||||||
|
} else if (haveHeader) {
|
||||||
bool CipherFileIO::setIV( uint64_t iv )
|
// we have an old IV, and now a new IV, so we need to update the fileIV
|
||||||
{
|
// on disk.
|
||||||
rDebug("in setIV, current IV = %" PRIu64 ", new IV = %" PRIu64
|
if (fileIV == 0) {
|
||||||
", fileIV = %" PRIu64,
|
// ensure the file is open for read/write..
|
||||||
externalIV, iv, fileIV);
|
int newFlags = lastFlags | O_RDWR;
|
||||||
if(externalIV == 0)
|
int res = base->open(newFlags);
|
||||||
{
|
if (res < 0) {
|
||||||
// we're just being told about which IV to use. since we haven't
|
if (res == -EISDIR) {
|
||||||
// initialized the fileIV, there is no need to just yet..
|
// duh -- there are no file headers for directories!
|
||||||
externalIV = iv;
|
externalIV = iv;
|
||||||
if(fileIV != 0)
|
return base->setIV(iv);
|
||||||
rWarning("fileIV initialized before externalIV! (%" PRIu64
|
} else {
|
||||||
", %" PRIu64 ")", fileIV, externalIV);
|
rDebug("writeHeader failed to re-open for write");
|
||||||
} else
|
return false;
|
||||||
if(haveHeader)
|
}
|
||||||
{
|
}
|
||||||
// we have an old IV, and now a new IV, so we need to update the fileIV
|
initHeader();
|
||||||
// on disk.
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// duh -- there are no file headers for directories!
|
|
||||||
externalIV = iv;
|
|
||||||
return base->setIV( iv );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
rDebug("writeHeader failed to re-open for write");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
initHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t oldIV = externalIV;
|
|
||||||
externalIV = iv;
|
|
||||||
if(!writeHeader())
|
|
||||||
{
|
|
||||||
externalIV = oldIV;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return base->setIV( iv );
|
uint64_t oldIV = externalIV;
|
||||||
}
|
externalIV = iv;
|
||||||
|
if (!writeHeader()) {
|
||||||
int CipherFileIO::getAttr( struct stat *stbuf ) const
|
externalIV = oldIV;
|
||||||
{
|
return false;
|
||||||
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))
|
|
||||||
{
|
|
||||||
rAssert(stbuf->st_size >= HEADER_SIZE);
|
|
||||||
stbuf->st_size -= HEADER_SIZE;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return base->setIV(iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t CipherFileIO::getSize() const
|
int CipherFileIO::getAttr(struct stat *stbuf) const {
|
||||||
{
|
int res = base->getAttr(stbuf);
|
||||||
off_t size = base->getSize();
|
// adjust size if we have a file header
|
||||||
// No check on S_ISREG here -- don't call getSize over getAttr unless this
|
if ((res == 0) && haveHeader && S_ISREG(stbuf->st_mode) &&
|
||||||
// is a normal file!
|
(stbuf->st_size > 0)) {
|
||||||
if(haveHeader && size > 0)
|
rAssert(stbuf->st_size >= HEADER_SIZE);
|
||||||
{
|
stbuf->st_size -= HEADER_SIZE;
|
||||||
rAssert(size >= HEADER_SIZE);
|
}
|
||||||
size -= HEADER_SIZE;
|
|
||||||
}
|
return res;
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CipherFileIO::initHeader( )
|
off_t CipherFileIO::getSize() const {
|
||||||
{
|
off_t size = base->getSize();
|
||||||
// check if the file has a header, and read it if it does.. Otherwise,
|
// No check on S_ISREG here -- don't call getSize over getAttr unless this
|
||||||
// create one.
|
// is a normal file!
|
||||||
off_t rawSize = base->getSize();
|
if (haveHeader && size > 0) {
|
||||||
if(rawSize >= HEADER_SIZE)
|
rAssert(size >= HEADER_SIZE);
|
||||||
{
|
size -= HEADER_SIZE;
|
||||||
rDebug("reading existing header, rawSize = %" PRIi64, rawSize);
|
}
|
||||||
// has a header.. read it
|
return size;
|
||||||
unsigned char buf[8] = {0};
|
|
||||||
|
|
||||||
IORequest req;
|
|
||||||
req.offset = 0;
|
|
||||||
req.data = buf;
|
|
||||||
req.dataLen = 8;
|
|
||||||
base->read( req );
|
|
||||||
|
|
||||||
cipher->streamDecode( buf, sizeof(buf),
|
|
||||||
externalIV, key );
|
|
||||||
|
|
||||||
fileIV = 0;
|
|
||||||
for(int i=0; i<8; ++i)
|
|
||||||
fileIV = (fileIV << 8) | (uint64_t)buf[i];
|
|
||||||
|
|
||||||
rAssert(fileIV != 0); // 0 is never used..
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
rDebug("creating new file IV header");
|
|
||||||
|
|
||||||
unsigned char buf[8] = {0};
|
|
||||||
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];
|
|
||||||
|
|
||||||
if(fileIV == 0)
|
|
||||||
rWarning("Unexpected result: randomize returned 8 null bytes!");
|
|
||||||
} while(fileIV == 0); // don't accept 0 as an option..
|
|
||||||
|
|
||||||
if( base->isWritable() )
|
|
||||||
{
|
|
||||||
cipher->streamEncode( buf, sizeof(buf), externalIV, key );
|
|
||||||
|
|
||||||
IORequest req;
|
|
||||||
req.offset = 0;
|
|
||||||
req.data = buf;
|
|
||||||
req.dataLen = 8;
|
|
||||||
|
|
||||||
base->write( req );
|
|
||||||
} else
|
|
||||||
rDebug("base not writable, IV not written..");
|
|
||||||
}
|
|
||||||
rDebug("initHeader finished, fileIV = %" PRIu64 , fileIV);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CipherFileIO::writeHeader( )
|
void CipherFileIO::initHeader() {
|
||||||
{
|
// check if the file has a header, and read it if it does.. Otherwise,
|
||||||
if( !base->isWritable() )
|
// create one.
|
||||||
{
|
off_t rawSize = base->getSize();
|
||||||
// open for write..
|
if (rawSize >= HEADER_SIZE) {
|
||||||
int newFlags = lastFlags | O_RDWR;
|
rDebug("reading existing header, rawSize = %" PRIi64, rawSize);
|
||||||
if( base->open( newFlags ) < 0 )
|
// has a header.. read it
|
||||||
{
|
|
||||||
rDebug("writeHeader failed to re-open for write");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fileIV == 0)
|
|
||||||
rError("Internal error: fileIV == 0 in writeHeader!!!");
|
|
||||||
rDebug("writing fileIV %" PRIu64 , fileIV);
|
|
||||||
|
|
||||||
unsigned char buf[8] = {0};
|
unsigned char buf[8] = {0};
|
||||||
for(int i=0; i<8; ++i)
|
|
||||||
{
|
|
||||||
buf[sizeof(buf)-1-i] = (unsigned char)(fileIV & 0xff);
|
|
||||||
fileIV >>= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
cipher->streamEncode( buf, sizeof(buf), externalIV, key );
|
|
||||||
|
|
||||||
IORequest req;
|
IORequest req;
|
||||||
req.offset = 0;
|
req.offset = 0;
|
||||||
req.data = buf;
|
req.data = buf;
|
||||||
req.dataLen = 8;
|
req.dataLen = 8;
|
||||||
|
base->read(req);
|
||||||
|
|
||||||
base->write( req );
|
cipher->streamDecode(buf, sizeof(buf), externalIV, key);
|
||||||
|
|
||||||
return true;
|
fileIV = 0;
|
||||||
|
for (int i = 0; i < 8; ++i) fileIV = (fileIV << 8) | (uint64_t)buf[i];
|
||||||
|
|
||||||
|
rAssert(fileIV != 0); // 0 is never used..
|
||||||
|
} else {
|
||||||
|
rDebug("creating new file IV header");
|
||||||
|
|
||||||
|
unsigned char buf[8] = {0};
|
||||||
|
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];
|
||||||
|
|
||||||
|
if (fileIV == 0)
|
||||||
|
rWarning("Unexpected result: randomize returned 8 null bytes!");
|
||||||
|
} while (fileIV == 0); // don't accept 0 as an option..
|
||||||
|
|
||||||
|
if (base->isWritable()) {
|
||||||
|
cipher->streamEncode(buf, sizeof(buf), externalIV, key);
|
||||||
|
|
||||||
|
IORequest req;
|
||||||
|
req.offset = 0;
|
||||||
|
req.data = buf;
|
||||||
|
req.dataLen = 8;
|
||||||
|
|
||||||
|
base->write(req);
|
||||||
|
} else
|
||||||
|
rDebug("base not writable, IV not written..");
|
||||||
|
}
|
||||||
|
rDebug("initHeader finished, fileIV = %" PRIu64, fileIV);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t CipherFileIO::readOneBlock( const IORequest &req ) const
|
bool CipherFileIO::writeHeader() {
|
||||||
{
|
if (!base->isWritable()) {
|
||||||
// read raw data, then decipher it..
|
// open for write..
|
||||||
int bs = blockSize();
|
int newFlags = lastFlags | O_RDWR;
|
||||||
off_t blockNum = req.offset / bs;
|
if (base->open(newFlags) < 0) {
|
||||||
|
rDebug("writeHeader failed to re-open for write");
|
||||||
ssize_t readSize = 0;
|
return false;
|
||||||
IORequest tmpReq = req;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(haveHeader)
|
if (fileIV == 0) rError("Internal error: fileIV == 0 in writeHeader!!!");
|
||||||
tmpReq.offset += HEADER_SIZE;
|
rDebug("writing fileIV %" PRIu64, fileIV);
|
||||||
readSize = base->read( tmpReq );
|
|
||||||
|
|
||||||
bool ok;
|
unsigned char buf[8] = {0};
|
||||||
if(readSize > 0)
|
for (int i = 0; i < 8; ++i) {
|
||||||
{
|
buf[sizeof(buf) - 1 - i] = (unsigned char)(fileIV & 0xff);
|
||||||
if(haveHeader && fileIV == 0)
|
fileIV >>= 8;
|
||||||
const_cast<CipherFileIO*>(this)->initHeader();
|
}
|
||||||
|
|
||||||
if(readSize != bs)
|
cipher->streamEncode(buf, sizeof(buf), externalIV, key);
|
||||||
{
|
|
||||||
ok = streamRead( tmpReq.data, (int)readSize, blockNum ^ fileIV);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
ok = blockRead( tmpReq.data, (int)readSize, blockNum ^ fileIV);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ok)
|
IORequest req;
|
||||||
{
|
req.offset = 0;
|
||||||
rDebug("decodeBlock failed for block %" PRIi64 ", size %i",
|
req.data = buf;
|
||||||
blockNum, (int)readSize );
|
req.dataLen = 8;
|
||||||
readSize = -1;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
rDebug("readSize zero for offset %" PRIi64, req.offset);
|
|
||||||
|
|
||||||
return readSize;
|
base->write(req);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t CipherFileIO::readOneBlock(const IORequest &req) const {
|
||||||
|
// read raw data, then decipher it..
|
||||||
|
int bs = blockSize();
|
||||||
|
off_t blockNum = req.offset / bs;
|
||||||
|
|
||||||
bool CipherFileIO::writeOneBlock( const IORequest &req )
|
ssize_t readSize = 0;
|
||||||
{
|
IORequest tmpReq = req;
|
||||||
int bs = blockSize();
|
|
||||||
off_t blockNum = req.offset / bs;
|
|
||||||
|
|
||||||
if(haveHeader && fileIV == 0)
|
if (haveHeader) tmpReq.offset += HEADER_SIZE;
|
||||||
initHeader();
|
readSize = base->read(tmpReq);
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
if( req.dataLen != bs )
|
if (readSize > 0) {
|
||||||
{
|
if (haveHeader && fileIV == 0)
|
||||||
ok = streamWrite( req.data, (int)req.dataLen,
|
const_cast<CipherFileIO *>(this)->initHeader();
|
||||||
blockNum ^ fileIV );
|
|
||||||
} else
|
if (readSize != bs) {
|
||||||
{
|
ok = streamRead(tmpReq.data, (int)readSize, blockNum ^ fileIV);
|
||||||
ok = blockWrite( req.data, (int)req.dataLen,
|
} else {
|
||||||
blockNum ^ fileIV );
|
ok = blockRead(tmpReq.data, (int)readSize, blockNum ^ fileIV);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ok )
|
if (!ok) {
|
||||||
{
|
rDebug("decodeBlock failed for block %" PRIi64 ", size %i", blockNum,
|
||||||
if(haveHeader)
|
(int)readSize);
|
||||||
{
|
readSize = -1;
|
||||||
IORequest tmpReq = req;
|
}
|
||||||
tmpReq.offset += HEADER_SIZE;
|
} else
|
||||||
ok = base->write( tmpReq );
|
rDebug("readSize zero for offset %" PRIi64, req.offset);
|
||||||
} else
|
|
||||||
ok = base->write( req );
|
return readSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CipherFileIO::writeOneBlock(const IORequest &req) {
|
||||||
|
int bs = blockSize();
|
||||||
|
off_t blockNum = req.offset / bs;
|
||||||
|
|
||||||
|
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 (ok) {
|
||||||
|
if (haveHeader) {
|
||||||
|
IORequest tmpReq = req;
|
||||||
|
tmpReq.offset += HEADER_SIZE;
|
||||||
|
ok = base->write(tmpReq);
|
||||||
} else
|
} else
|
||||||
{
|
ok = base->write(req);
|
||||||
rDebug("encodeBlock failed for block %" PRIi64 ", size %i",
|
} else {
|
||||||
blockNum, req.dataLen);
|
rDebug("encodeBlock failed for block %" PRIi64 ", size %i", blockNum,
|
||||||
ok = false;
|
req.dataLen);
|
||||||
}
|
ok = false;
|
||||||
return ok;
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CipherFileIO::blockWrite( unsigned char *buf, int size,
|
bool CipherFileIO::blockWrite(unsigned char *buf, int size,
|
||||||
uint64_t _iv64 ) const
|
uint64_t _iv64) const {
|
||||||
{
|
if (!fsConfig->reverseEncryption)
|
||||||
if (!fsConfig->reverseEncryption)
|
return cipher->blockEncode(buf, size, _iv64, key);
|
||||||
return cipher->blockEncode( buf, size, _iv64, key );
|
else
|
||||||
else
|
return cipher->blockDecode(buf, size, _iv64, key);
|
||||||
return cipher->blockDecode( buf, size, _iv64, key );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool CipherFileIO::streamWrite( unsigned char *buf, int size,
|
bool CipherFileIO::streamWrite(unsigned char *buf, int size,
|
||||||
uint64_t _iv64 ) const
|
uint64_t _iv64) const {
|
||||||
{
|
if (!fsConfig->reverseEncryption)
|
||||||
if (!fsConfig->reverseEncryption)
|
return cipher->streamEncode(buf, size, _iv64, key);
|
||||||
return cipher->streamEncode( buf, size, _iv64, key );
|
else
|
||||||
else
|
return cipher->streamDecode(buf, size, _iv64, key);
|
||||||
return cipher->streamDecode( buf, size, _iv64, key );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
bool CipherFileIO::blockRead(unsigned char *buf, int size,
|
||||||
|
uint64_t _iv64) const {
|
||||||
|
if (fsConfig->reverseEncryption)
|
||||||
|
return cipher->blockEncode(buf, size, _iv64, key);
|
||||||
|
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);
|
||||||
|
|
||||||
bool CipherFileIO::blockRead( unsigned char *buf, int size,
|
return true;
|
||||||
uint64_t _iv64 ) const
|
|
||||||
{
|
|
||||||
if (fsConfig->reverseEncryption)
|
|
||||||
return cipher->blockEncode( buf, size, _iv64, key );
|
|
||||||
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 );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
return cipher->blockDecode( buf, size, _iv64, key );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CipherFileIO::streamRead( unsigned char *buf, int size,
|
|
||||||
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 res = 0;
|
|
||||||
if(!haveHeader)
|
|
||||||
{
|
|
||||||
res = BlockFileIO::truncateBase( size, base.get() );
|
|
||||||
} else
|
} else
|
||||||
{
|
return cipher->blockDecode(buf, size, _iv64, key);
|
||||||
if(0 == fileIV)
|
}
|
||||||
{
|
}
|
||||||
// empty file.. create the header..
|
|
||||||
if( !base->isWritable() )
|
|
||||||
{
|
|
||||||
// open for write..
|
|
||||||
int newFlags = lastFlags | O_RDWR;
|
|
||||||
if( base->open( newFlags ) < 0 )
|
|
||||||
rDebug("writeHeader failed to re-open for write");
|
|
||||||
}
|
|
||||||
initHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't let BlockFileIO call base->truncate(), since it would be using
|
bool CipherFileIO::streamRead(unsigned char *buf, int size,
|
||||||
// the wrong size..
|
uint64_t _iv64) const {
|
||||||
res = BlockFileIO::truncateBase( size, 0 );
|
if (fsConfig->reverseEncryption)
|
||||||
|
return cipher->streamEncode(buf, size, _iv64, key);
|
||||||
|
else
|
||||||
|
return cipher->streamDecode(buf, size, _iv64, key);
|
||||||
|
}
|
||||||
|
|
||||||
if(res == 0)
|
int CipherFileIO::truncate(off_t size) {
|
||||||
base->truncate( size + HEADER_SIZE );
|
int res = 0;
|
||||||
|
if (!haveHeader) {
|
||||||
|
res = BlockFileIO::truncateBase(size, base.get());
|
||||||
|
} else {
|
||||||
|
if (0 == fileIV) {
|
||||||
|
// empty file.. create the header..
|
||||||
|
if (!base->isWritable()) {
|
||||||
|
// open for write..
|
||||||
|
int newFlags = lastFlags | O_RDWR;
|
||||||
|
if (base->open(newFlags) < 0)
|
||||||
|
rDebug("writeHeader failed to re-open for write");
|
||||||
|
}
|
||||||
|
initHeader();
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
// can't let BlockFileIO call base->truncate(), since it would be using
|
||||||
|
// the wrong size..
|
||||||
bool CipherFileIO::isWritable() const
|
res = BlockFileIO::truncateBase(size, 0);
|
||||||
{
|
|
||||||
return base->isWritable();
|
if (res == 0) base->truncate(size + HEADER_SIZE);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CipherFileIO::isWritable() const { return base->isWritable(); }
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -30,60 +30,54 @@
|
|||||||
class Cipher;
|
class Cipher;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Implement the FileIO interface encrypting data in blocks.
|
Implement the FileIO interface encrypting data in blocks.
|
||||||
|
|
||||||
Uses BlockFileIO to handle the block scatter / gather issues.
|
Uses BlockFileIO to handle the block scatter / gather issues.
|
||||||
*/
|
*/
|
||||||
class CipherFileIO : public BlockFileIO
|
class CipherFileIO : public BlockFileIO {
|
||||||
{
|
public:
|
||||||
public:
|
CipherFileIO(const shared_ptr<FileIO> &base, const FSConfigPtr &cfg);
|
||||||
CipherFileIO( const shared_ptr<FileIO> &base,
|
virtual ~CipherFileIO();
|
||||||
const FSConfigPtr &cfg);
|
|
||||||
virtual ~CipherFileIO();
|
|
||||||
|
|
||||||
virtual rel::Interface interface() const;
|
virtual rel::Interface interface() const;
|
||||||
|
|
||||||
virtual void setFileName( const char *fileName );
|
virtual void setFileName(const char *fileName);
|
||||||
virtual const char *getFileName() const;
|
virtual const char *getFileName() const;
|
||||||
virtual bool setIV( uint64_t iv );
|
virtual bool setIV(uint64_t iv);
|
||||||
|
|
||||||
virtual int open( int flags );
|
virtual int open(int flags);
|
||||||
|
|
||||||
virtual int getAttr( struct stat *stbuf ) const;
|
virtual int getAttr(struct stat *stbuf) const;
|
||||||
virtual off_t getSize() const;
|
virtual off_t getSize() const;
|
||||||
|
|
||||||
virtual int truncate( off_t size );
|
virtual int truncate(off_t size);
|
||||||
|
|
||||||
virtual bool isWritable() const;
|
virtual bool isWritable() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ssize_t readOneBlock( const IORequest &req ) const;
|
virtual ssize_t readOneBlock(const IORequest &req) const;
|
||||||
virtual bool writeOneBlock( const IORequest &req );
|
virtual bool writeOneBlock(const IORequest &req);
|
||||||
|
|
||||||
void initHeader();
|
void initHeader();
|
||||||
bool writeHeader();
|
bool writeHeader();
|
||||||
bool blockRead( unsigned char *buf, int size,
|
bool blockRead(unsigned char *buf, int size, uint64_t iv64) const;
|
||||||
uint64_t iv64 ) const;
|
bool streamRead(unsigned char *buf, int size, uint64_t iv64) const;
|
||||||
bool streamRead( unsigned char *buf, int size,
|
bool blockWrite(unsigned char *buf, int size, uint64_t iv64) const;
|
||||||
uint64_t iv64 ) const;
|
bool streamWrite(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;
|
shared_ptr<FileIO> base;
|
||||||
|
|
||||||
FSConfigPtr fsConfig;
|
FSConfigPtr fsConfig;
|
||||||
|
|
||||||
// if haveHeader is true, then we have a transparent file header which
|
// if haveHeader is true, then we have a transparent file header which
|
||||||
// contains a 64 bit initialization vector.
|
// contains a 64 bit initialization vector.
|
||||||
bool haveHeader;
|
bool haveHeader;
|
||||||
uint64_t externalIV;
|
uint64_t externalIV;
|
||||||
uint64_t fileIV;
|
uint64_t fileIV;
|
||||||
int lastFlags;
|
int lastFlags;
|
||||||
|
|
||||||
shared_ptr<Cipher> cipher;
|
shared_ptr<Cipher> cipher;
|
||||||
CipherKey key;
|
CipherKey key;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -20,11 +20,6 @@
|
|||||||
|
|
||||||
#include "CipherKey.h"
|
#include "CipherKey.h"
|
||||||
|
|
||||||
AbstractCipherKey::AbstractCipherKey()
|
AbstractCipherKey::AbstractCipherKey() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractCipherKey::~AbstractCipherKey()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
AbstractCipherKey::~AbstractCipherKey() {}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -23,14 +23,12 @@
|
|||||||
|
|
||||||
#include "shared_ptr.h"
|
#include "shared_ptr.h"
|
||||||
|
|
||||||
class AbstractCipherKey
|
class AbstractCipherKey {
|
||||||
{
|
public:
|
||||||
public:
|
AbstractCipherKey();
|
||||||
AbstractCipherKey();
|
virtual ~AbstractCipherKey();
|
||||||
virtual ~AbstractCipherKey();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef shared_ptr<AbstractCipherKey> CipherKey;
|
typedef shared_ptr<AbstractCipherKey> CipherKey;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -28,135 +28,109 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace rlog;
|
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
|
// read the entire file into a ConfigVar instance and then use that to decode
|
||||||
// into mapped variables.
|
// into mapped variables.
|
||||||
bool
|
bool ConfigReader::load(const char *fileName) {
|
||||||
ConfigReader::load(const char *fileName)
|
struct stat stbuf;
|
||||||
{
|
memset(&stbuf, 0, sizeof(struct stat));
|
||||||
struct stat stbuf;
|
if (lstat(fileName, &stbuf) != 0) return false;
|
||||||
memset( &stbuf, 0, sizeof(struct stat));
|
|
||||||
if( lstat( fileName, &stbuf ) != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int size = stbuf.st_size;
|
int size = stbuf.st_size;
|
||||||
|
|
||||||
int fd = open( fileName, O_RDONLY );
|
int fd = open(fileName, O_RDONLY);
|
||||||
if(fd < 0)
|
if (fd < 0) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
char *buf = new char[size];
|
char *buf = new char[size];
|
||||||
|
|
||||||
int res = ::read( fd, buf, size );
|
int res = ::read(fd, buf, size);
|
||||||
close( fd );
|
close(fd);
|
||||||
|
|
||||||
if( res != size )
|
if (res != size) {
|
||||||
{
|
rWarning("Partial read of config file, expecting %i bytes, got %i", size,
|
||||||
rWarning("Partial read of config file, expecting %i bytes, got %i",
|
res);
|
||||||
size, res);
|
|
||||||
delete[] buf;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigVar in;
|
|
||||||
in.write( (unsigned char *)buf, size );
|
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return loadFromVar( in );
|
ConfigVar in;
|
||||||
|
in.write((unsigned char *)buf, size);
|
||||||
|
delete[] buf;
|
||||||
|
|
||||||
|
return loadFromVar(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool ConfigReader::loadFromVar(ConfigVar &in) {
|
||||||
ConfigReader::loadFromVar(ConfigVar &in)
|
in.resetOffset();
|
||||||
{
|
|
||||||
in.resetOffset();
|
|
||||||
|
|
||||||
// parse.
|
// parse.
|
||||||
int numEntries = in.readInt();
|
int numEntries = in.readInt();
|
||||||
|
|
||||||
for(int i=0; i<numEntries; ++i)
|
for (int i = 0; i < numEntries; ++i) {
|
||||||
{
|
string key, value;
|
||||||
string key, value;
|
in >> key >> value;
|
||||||
in >> key >> value;
|
|
||||||
|
|
||||||
if(key.length() == 0)
|
if (key.length() == 0) {
|
||||||
{
|
rError("Invalid key encoding in buffer");
|
||||||
rError("Invalid key encoding in buffer");
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ConfigVar newVar( value );
|
|
||||||
vars.insert( make_pair( key, newVar ) );
|
|
||||||
}
|
}
|
||||||
|
ConfigVar newVar(value);
|
||||||
|
vars.insert(make_pair(key, newVar));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool ConfigReader::save(const char *fileName) const {
|
||||||
ConfigReader::save(const char *fileName) const
|
// write everything to a ConfigVar, then output to disk
|
||||||
{
|
ConfigVar out = toVar();
|
||||||
// write everything to a ConfigVar, then output to disk
|
|
||||||
ConfigVar out = toVar();
|
|
||||||
|
|
||||||
int fd = ::open( fileName, O_RDWR | O_CREAT, 0640 );
|
int fd = ::open(fileName, O_RDWR | O_CREAT, 0640);
|
||||||
if(fd >= 0)
|
if (fd >= 0) {
|
||||||
{
|
int retVal = ::write(fd, out.buffer(), out.size());
|
||||||
int retVal = ::write( fd, out.buffer(), out.size() );
|
close(fd);
|
||||||
close( fd );
|
if (retVal != out.size()) {
|
||||||
if(retVal != out.size())
|
rError("Error writing to config file %s", fileName);
|
||||||
{
|
return false;
|
||||||
rError("Error writing to config file %s", fileName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
rError("Unable to open or create file %s", fileName);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
rError("Unable to open or create file %s", fileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVar
|
ConfigVar ConfigReader::toVar() const {
|
||||||
ConfigReader::toVar() const
|
// write everything to a ConfigVar, then output to disk
|
||||||
{
|
ConfigVar out;
|
||||||
// write everything to a ConfigVar, then output to disk
|
out.writeInt(vars.size());
|
||||||
ConfigVar out;
|
map<string, ConfigVar>::const_iterator it;
|
||||||
out.writeInt( vars.size() );
|
for (it = vars.begin(); it != vars.end(); ++it) {
|
||||||
map<string, ConfigVar>::const_iterator it;
|
out.writeInt(it->first.size());
|
||||||
for(it = vars.begin(); it != vars.end(); ++it)
|
out.write((unsigned char *)it->first.data(), it->first.size());
|
||||||
{
|
out.writeInt(it->second.size());
|
||||||
out.writeInt( it->first.size() );
|
out.write((unsigned char *)it->second.buffer(), it->second.size());
|
||||||
out.write( (unsigned char*)it->first.data(), it->first.size() );
|
}
|
||||||
out.writeInt( it->second.size() );
|
|
||||||
out.write( (unsigned char*)it->second.buffer(), it->second.size() );
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVar ConfigReader::operator[] ( const std::string &varName ) const
|
ConfigVar ConfigReader::operator[](const std::string &varName) const {
|
||||||
{
|
// read only
|
||||||
// read only
|
map<string, ConfigVar>::const_iterator it = vars.find(varName);
|
||||||
map<string, ConfigVar>::const_iterator it = vars.find( varName );
|
if (it == vars.end())
|
||||||
if( it == vars.end() )
|
return ConfigVar();
|
||||||
return ConfigVar();
|
else
|
||||||
else
|
return it->second;
|
||||||
return it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVar &ConfigReader::operator[] ( const std::string &varName )
|
ConfigVar &ConfigReader::operator[](const std::string &varName) {
|
||||||
{
|
return vars[varName];
|
||||||
return vars[ varName ];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ConfigReader_incl_
|
#ifndef _ConfigReader_incl_
|
||||||
#define _ConfigReader_incl_
|
#define _ConfigReader_incl_
|
||||||
|
|
||||||
@ -43,24 +43,22 @@
|
|||||||
ConfigReader cfg;
|
ConfigReader cfg;
|
||||||
cfg["cipher"] << cipher->interface();
|
cfg["cipher"] << cipher->interface();
|
||||||
*/
|
*/
|
||||||
class ConfigReader
|
class ConfigReader {
|
||||||
{
|
public:
|
||||||
public:
|
ConfigReader();
|
||||||
ConfigReader();
|
~ConfigReader();
|
||||||
~ConfigReader();
|
|
||||||
|
|
||||||
bool load(const char *fileName);
|
bool load(const char *fileName);
|
||||||
bool save(const char *fileName) const;
|
bool save(const char *fileName) const;
|
||||||
|
|
||||||
ConfigVar toVar() const;
|
ConfigVar toVar() const;
|
||||||
bool loadFromVar( ConfigVar &var );
|
bool loadFromVar(ConfigVar &var);
|
||||||
|
|
||||||
ConfigVar operator[](const std::string &varName) const;
|
ConfigVar operator[](const std::string &varName) const;
|
||||||
ConfigVar &operator[](const std::string &varName);
|
ConfigVar &operator[](const std::string &varName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, ConfigVar> vars;
|
std::map<std::string, ConfigVar> vars;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -26,227 +26,175 @@
|
|||||||
using namespace rlog;
|
using namespace rlog;
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
inline int MIN(int a, int b)
|
inline int MIN(int a, int b) { return (a < b) ? a : b; }
|
||||||
{
|
|
||||||
return (a < b) ? a : b;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ConfigVar::ConfigVar() : pd(new ConfigVarData) { pd->offset = 0; }
|
||||||
|
|
||||||
ConfigVar::ConfigVar()
|
ConfigVar::ConfigVar(const std::string &buf) : pd(new ConfigVarData) {
|
||||||
: pd( new ConfigVarData )
|
pd->buffer = buf;
|
||||||
{
|
pd->offset = 0;
|
||||||
pd->offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVar::ConfigVar(const std::string &buf)
|
ConfigVar::ConfigVar(const ConfigVar &src) { pd = src.pd; }
|
||||||
: pd( new ConfigVarData )
|
|
||||||
{
|
|
||||||
pd->buffer = buf;
|
|
||||||
pd->offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigVar::ConfigVar(const ConfigVar &src)
|
ConfigVar::~ConfigVar() { pd.reset(); }
|
||||||
{
|
|
||||||
pd = src.pd;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigVar::~ConfigVar()
|
|
||||||
{
|
|
||||||
pd.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigVar & ConfigVar::operator = (const ConfigVar &src)
|
|
||||||
{
|
|
||||||
if(src.pd == pd)
|
|
||||||
return *this;
|
|
||||||
else
|
|
||||||
pd = src.pd;
|
|
||||||
|
|
||||||
|
ConfigVar &ConfigVar::operator=(const ConfigVar &src) {
|
||||||
|
if (src.pd == pd)
|
||||||
return *this;
|
return *this;
|
||||||
|
else
|
||||||
|
pd = src.pd;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigVar::resetOffset()
|
void ConfigVar::resetOffset() { pd->offset = 0; }
|
||||||
{
|
|
||||||
pd->offset = 0;
|
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);
|
||||||
|
|
||||||
|
pd->offset += toCopy;
|
||||||
|
|
||||||
|
return toCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigVar::read(unsigned char *buffer_, int bytes) const
|
int ConfigVar::write(const unsigned char *data, int bytes) {
|
||||||
{
|
if (pd->buffer.size() == (unsigned int)pd->offset) {
|
||||||
int toCopy = MIN( bytes, pd->buffer.size() - pd->offset );
|
pd->buffer.append((const char *)data, bytes);
|
||||||
|
} else {
|
||||||
|
pd->buffer.insert(pd->offset, (const char *)data, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
if(toCopy > 0)
|
pd->offset += bytes;
|
||||||
memcpy( buffer_, pd->buffer.data() + pd->offset, toCopy );
|
|
||||||
|
|
||||||
pd->offset += toCopy;
|
return bytes;
|
||||||
|
|
||||||
return toCopy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigVar::write(const unsigned char *data, int bytes)
|
int ConfigVar::size() const { return pd->buffer.size(); }
|
||||||
{
|
|
||||||
if(pd->buffer.size() == (unsigned int)pd->offset)
|
|
||||||
{
|
|
||||||
pd->buffer.append( (const char *)data, bytes );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
pd->buffer.insert( pd->offset, (const char *)data, bytes );
|
|
||||||
}
|
|
||||||
|
|
||||||
pd->offset += bytes;
|
const char *ConfigVar::buffer() const { return pd->buffer.data(); }
|
||||||
|
|
||||||
return bytes;
|
int ConfigVar::at() const { return pd->offset; }
|
||||||
|
|
||||||
|
void ConfigVar::writeString(const char *data, int bytes) {
|
||||||
|
writeInt(bytes);
|
||||||
|
write((const unsigned char *)data, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigVar::size() const
|
|
||||||
{
|
|
||||||
return pd->buffer.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *ConfigVar::buffer() const
|
|
||||||
{
|
|
||||||
return pd->buffer.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ConfigVar::at() const
|
|
||||||
{
|
|
||||||
return pd->offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigVar::writeString(const char *data, int bytes)
|
|
||||||
{
|
|
||||||
writeInt( bytes );
|
|
||||||
write( (const unsigned char *)data, bytes );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// convert integer to BER encoded integer
|
// 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
|
||||||
// we can represent 7 bits per char output, so a 32bit number may take up
|
// to 5 bytes.
|
||||||
// to 5 bytes.
|
// first byte: 0x0000007f 0111,1111
|
||||||
// first byte: 0x0000007f 0111,1111
|
// second byte: 0x00003f80 0011,1111 1000,0000
|
||||||
// second byte: 0x00003f80 0011,1111 1000,0000
|
// third byte: 0x001fb000 0000,0000 0001,1111 1100,0000 0000,0000
|
||||||
// third byte: 0x001fb000 0000,0000 0001,1111 1100,0000 0000,0000
|
// fourth byte: 0x0fe00000 0000,1111 1110,0000
|
||||||
// fourth byte: 0x0fe00000 0000,1111 1110,0000
|
// fifth byte: 0xf0000000 1111,0000
|
||||||
// fifth byte: 0xf0000000 1111,0000
|
unsigned char digit[5];
|
||||||
unsigned char digit[5];
|
|
||||||
|
|
||||||
digit[4] = (unsigned char)((val & 0x0000007f));
|
digit[4] = (unsigned char)((val & 0x0000007f));
|
||||||
digit[3] = 0x80 | (unsigned char)((val & 0x00003f80) >> 7);
|
digit[3] = 0x80 | (unsigned char)((val & 0x00003f80) >> 7);
|
||||||
digit[2] = 0x80 | (unsigned char)((val & 0x001fc000) >> 14);
|
digit[2] = 0x80 | (unsigned char)((val & 0x001fc000) >> 14);
|
||||||
digit[1] = 0x80 | (unsigned char)((val & 0x0fe00000) >> 21);
|
digit[1] = 0x80 | (unsigned char)((val & 0x0fe00000) >> 21);
|
||||||
digit[0] = 0x80 | (unsigned char)((val & 0xf0000000) >> 28);
|
digit[0] = 0x80 | (unsigned char)((val & 0xf0000000) >> 28);
|
||||||
|
|
||||||
// find the starting point - we only need to output starting at the most
|
// find the starting point - we only need to output starting at the most
|
||||||
// significant non-zero digit..
|
// significant non-zero digit..
|
||||||
int start = 0;
|
int start = 0;
|
||||||
while(digit[start] == 0x80)
|
while (digit[start] == 0x80) ++start;
|
||||||
++start;
|
|
||||||
|
|
||||||
write( digit + start, 5-start );
|
write(digit + start, 5 - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigVar::readInt() const
|
int ConfigVar::readInt() const {
|
||||||
{
|
const unsigned char *buf = (const unsigned char *)buffer();
|
||||||
const unsigned char * buf = (const unsigned char *)buffer();
|
int bytes = this->size();
|
||||||
int bytes = this->size();
|
int offset = at();
|
||||||
int offset = at();
|
int value = 0;
|
||||||
int value = 0;
|
bool highBitSet;
|
||||||
bool highBitSet;
|
|
||||||
|
|
||||||
rAssert( offset < bytes );
|
rAssert(offset < bytes);
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
unsigned char tmp = buf[offset++];
|
||||||
unsigned char tmp = buf[offset++];
|
highBitSet = tmp & 0x80;
|
||||||
highBitSet = tmp & 0x80;
|
|
||||||
|
|
||||||
value = (value << 7) | (int)(tmp & 0x7f);
|
value = (value << 7) | (int)(tmp & 0x7f);
|
||||||
} while(highBitSet && offset < bytes);
|
} while (highBitSet && offset < bytes);
|
||||||
|
|
||||||
pd->offset = offset;
|
pd->offset = offset;
|
||||||
|
|
||||||
// should never end up with a negative number..
|
// should never end up with a negative number..
|
||||||
rAssert( value >= 0 );
|
rAssert(value >= 0);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigVar::readInt( int defaultValue ) const
|
int ConfigVar::readInt(int defaultValue) const {
|
||||||
{
|
int bytes = this->size();
|
||||||
int bytes = this->size();
|
int offset = at();
|
||||||
int offset = at();
|
|
||||||
|
|
||||||
if(offset >= bytes)
|
if (offset >= bytes)
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
else
|
else
|
||||||
return readInt();
|
return readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigVar::readBool( bool defaultValue ) const
|
bool ConfigVar::readBool(bool defaultValue) const {
|
||||||
{
|
int tmp = readInt(defaultValue ? 1 : 0);
|
||||||
int tmp = readInt( defaultValue ? 1 : 0 );
|
return (tmp != 0);
|
||||||
return (tmp != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVar & operator << (ConfigVar &src, bool value)
|
ConfigVar &operator<<(ConfigVar &src, bool value) {
|
||||||
{
|
src.writeInt(value ? 1 : 0);
|
||||||
src.writeInt( value ? 1 : 0 );
|
return src;
|
||||||
return src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVar & operator << (ConfigVar &src, int var)
|
ConfigVar &operator<<(ConfigVar &src, int var) {
|
||||||
{
|
src.writeInt(var);
|
||||||
src.writeInt( var );
|
return src;
|
||||||
return src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVar & operator << (ConfigVar &src, const std::string &str)
|
ConfigVar &operator<<(ConfigVar &src, const std::string &str) {
|
||||||
{
|
src.writeString(str.data(), str.length());
|
||||||
src.writeString( str.data(), str.length() );
|
return src;
|
||||||
return src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConfigVar & operator >> (const ConfigVar &src, bool &result)
|
const ConfigVar &operator>>(const ConfigVar &src, bool &result) {
|
||||||
{
|
int tmp = src.readInt();
|
||||||
int tmp = src.readInt();
|
result = (tmp != 0);
|
||||||
result = (tmp != 0);
|
return src;
|
||||||
return src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConfigVar & operator >> (const ConfigVar &src, int &result)
|
const ConfigVar &operator>>(const ConfigVar &src, int &result) {
|
||||||
{
|
result = src.readInt();
|
||||||
result = src.readInt();
|
return src;
|
||||||
return src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConfigVar & operator >> (const ConfigVar &src, std::string &result)
|
const ConfigVar &operator>>(const ConfigVar &src, std::string &result) {
|
||||||
{
|
int length = src.readInt();
|
||||||
int length = src.readInt();
|
// rAssert(length > 0);
|
||||||
//rAssert(length > 0);
|
|
||||||
|
|
||||||
int readLen;
|
int readLen;
|
||||||
|
|
||||||
unsigned char tmpBuf[32];
|
unsigned char tmpBuf[32];
|
||||||
if(length > (int)sizeof(tmpBuf))
|
if (length > (int)sizeof(tmpBuf)) {
|
||||||
{
|
unsigned char *ptr = new unsigned char[length];
|
||||||
unsigned char *ptr = new unsigned char[length];
|
readLen = src.read(ptr, length);
|
||||||
readLen = src.read( ptr, length );
|
result.assign((char *)ptr, length);
|
||||||
result.assign( (char*)ptr, length );
|
delete[] ptr;
|
||||||
delete[] ptr;
|
} else {
|
||||||
} else
|
readLen = src.read(tmpBuf, length);
|
||||||
{
|
result.assign((char *)tmpBuf, length);
|
||||||
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);
|
||||||
rDebug("string encoded as size %i bytes, read %i", length, readLen );
|
}
|
||||||
}
|
rAssert(readLen == length);
|
||||||
rAssert(readLen == length);
|
|
||||||
|
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -24,58 +24,55 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "shared_ptr.h"
|
#include "shared_ptr.h"
|
||||||
|
|
||||||
class ConfigVar
|
class ConfigVar {
|
||||||
{
|
struct ConfigVarData {
|
||||||
struct ConfigVarData
|
std::string buffer;
|
||||||
{
|
int offset;
|
||||||
std::string buffer;
|
};
|
||||||
int offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
shared_ptr<ConfigVarData> pd;
|
shared_ptr<ConfigVarData> pd;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConfigVar();
|
ConfigVar();
|
||||||
ConfigVar(const std::string &buffer);
|
ConfigVar(const std::string &buffer);
|
||||||
ConfigVar(const ConfigVar &src);
|
ConfigVar(const ConfigVar &src);
|
||||||
~ConfigVar();
|
~ConfigVar();
|
||||||
|
|
||||||
ConfigVar & operator = (const ConfigVar &src);
|
ConfigVar &operator=(const ConfigVar &src);
|
||||||
|
|
||||||
// reset read/write offset..
|
// reset read/write offset..
|
||||||
void resetOffset();
|
void resetOffset();
|
||||||
|
|
||||||
// read bytes
|
// read bytes
|
||||||
int read(unsigned char *buffer, int size) const;
|
int read(unsigned char *buffer, int size) const;
|
||||||
|
|
||||||
// write bytes..
|
// write bytes..
|
||||||
int write(const unsigned char *data, int size);
|
int write(const unsigned char *data, int size);
|
||||||
|
|
||||||
int readInt() const;
|
int readInt() const;
|
||||||
int readInt( int defaultValue ) const;
|
int readInt(int defaultValue) const;
|
||||||
void writeInt(int value);
|
void writeInt(int value);
|
||||||
|
|
||||||
bool readBool( bool defaultValue ) const;
|
bool readBool(bool defaultValue) const;
|
||||||
|
|
||||||
void writeString(const char *data, int size);
|
void writeString(const char *data, int size);
|
||||||
|
|
||||||
// return amount of data in var
|
// return amount of data in var
|
||||||
int size() const;
|
int size() const;
|
||||||
// return data pointer - returns front of data pointer, not the current
|
// return data pointer - returns front of data pointer, not the current
|
||||||
// position.
|
// position.
|
||||||
const char *buffer() const;
|
const char *buffer() const;
|
||||||
|
|
||||||
// return current position in data() buffer.
|
// return current position in data() buffer.
|
||||||
int at() const;
|
int at() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConfigVar & operator << (ConfigVar &, bool);
|
ConfigVar &operator<<(ConfigVar &, bool);
|
||||||
ConfigVar & operator << (ConfigVar &, int);
|
ConfigVar &operator<<(ConfigVar &, int);
|
||||||
ConfigVar & operator << (ConfigVar &, const std::string &str);
|
ConfigVar &operator<<(ConfigVar &, const std::string &str);
|
||||||
|
|
||||||
const ConfigVar & operator >> (const ConfigVar &, bool &);
|
const ConfigVar &operator>>(const ConfigVar &, bool &);
|
||||||
const ConfigVar & operator >> (const ConfigVar &, int &);
|
const ConfigVar &operator>>(const ConfigVar &, int &);
|
||||||
const ConfigVar & operator >> (const ConfigVar &, std::string &str);
|
const ConfigVar &operator>>(const ConfigVar &, std::string &str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -29,149 +29,126 @@
|
|||||||
using namespace rel;
|
using namespace rel;
|
||||||
using namespace rlog;
|
using namespace rlog;
|
||||||
|
|
||||||
EncFS_Context::EncFS_Context()
|
EncFS_Context::EncFS_Context() {
|
||||||
{
|
pthread_cond_init(&wakeupCond, 0);
|
||||||
pthread_cond_init( &wakeupCond, 0 );
|
pthread_mutex_init(&wakeupMutex, 0);
|
||||||
pthread_mutex_init( &wakeupMutex, 0 );
|
pthread_mutex_init(&contextMutex, 0);
|
||||||
pthread_mutex_init( &contextMutex, 0 );
|
|
||||||
|
|
||||||
usageCount = 0;
|
usageCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EncFS_Context::~EncFS_Context()
|
EncFS_Context::~EncFS_Context() {
|
||||||
{
|
pthread_mutex_destroy(&contextMutex);
|
||||||
pthread_mutex_destroy( &contextMutex );
|
pthread_mutex_destroy(&wakeupMutex);
|
||||||
pthread_mutex_destroy( &wakeupMutex );
|
pthread_cond_destroy(&wakeupCond);
|
||||||
pthread_cond_destroy( &wakeupCond );
|
|
||||||
|
|
||||||
// release all entries from map
|
// release all entries from map
|
||||||
openFiles.clear();
|
openFiles.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode)
|
shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode) {
|
||||||
{
|
shared_ptr<DirNode> ret;
|
||||||
shared_ptr<DirNode> ret;
|
do {
|
||||||
do
|
|
||||||
{
|
{
|
||||||
{
|
Lock lock(contextMutex);
|
||||||
Lock lock( contextMutex );
|
ret = root;
|
||||||
ret = root;
|
++usageCount;
|
||||||
++usageCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ret)
|
|
||||||
{
|
|
||||||
int res = remountFS( this );
|
|
||||||
if(res != 0)
|
|
||||||
{
|
|
||||||
*errCode = res;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while(!ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncFS_Context::setRoot(const shared_ptr<DirNode> &r)
|
|
||||||
{
|
|
||||||
Lock lock( contextMutex );
|
|
||||||
|
|
||||||
root = r;
|
|
||||||
if(r)
|
|
||||||
rootCipherDir = r->rootDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EncFS_Context::isMounted()
|
|
||||||
{
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EncFS_Context::getAndResetUsageCounter()
|
|
||||||
{
|
|
||||||
Lock lock( contextMutex );
|
|
||||||
|
|
||||||
int count = usageCount;
|
|
||||||
usageCount = 0;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EncFS_Context::openFileCount() const
|
|
||||||
{
|
|
||||||
Lock lock( contextMutex );
|
|
||||||
|
|
||||||
return openFiles.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path)
|
|
||||||
{
|
|
||||||
Lock lock( contextMutex );
|
|
||||||
|
|
||||||
FileMap::iterator it = openFiles.find( std::string(path) );
|
|
||||||
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
|
|
||||||
{
|
|
||||||
return shared_ptr<FileNode>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
|
||||||
{
|
|
||||||
std::set<Placeholder *> val = it->second;
|
|
||||||
openFiles.erase(it);
|
|
||||||
openFiles[ std::string(to) ] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
Lock lock( contextMutex );
|
|
||||||
Placeholder *pl = new Placeholder( node );
|
|
||||||
openFiles[ std::string(path) ].insert(pl);
|
|
||||||
|
|
||||||
return (void *)pl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncFS_Context::eraseNode(const char *path, void *pl)
|
|
||||||
{
|
|
||||||
Lock lock( contextMutex );
|
|
||||||
|
|
||||||
Placeholder *ph = (Placeholder *)pl;
|
|
||||||
|
|
||||||
FileMap::iterator it = openFiles.find( std::string(path) );
|
|
||||||
rAssert(it != openFiles.end());
|
|
||||||
|
|
||||||
int rmCount = it->second.erase( ph );
|
|
||||||
|
|
||||||
rAssert(rmCount == 1);
|
|
||||||
|
|
||||||
// if no more references to this file, remove the record all together
|
|
||||||
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;
|
|
||||||
openFiles.erase( it );
|
|
||||||
storedName.assign( storedName.length(), '\0' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete ph;
|
if (!ret) {
|
||||||
|
int res = remountFS(this);
|
||||||
|
if (res != 0) {
|
||||||
|
*errCode = res;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EncFS_Context::setRoot(const shared_ptr<DirNode> &r) {
|
||||||
|
Lock lock(contextMutex);
|
||||||
|
|
||||||
|
root = r;
|
||||||
|
if (r) rootCipherDir = r->rootDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EncFS_Context::isMounted() { return root; }
|
||||||
|
|
||||||
|
int EncFS_Context::getAndResetUsageCounter() {
|
||||||
|
Lock lock(contextMutex);
|
||||||
|
|
||||||
|
int count = usageCount;
|
||||||
|
usageCount = 0;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EncFS_Context::openFileCount() const {
|
||||||
|
Lock lock(contextMutex);
|
||||||
|
|
||||||
|
return openFiles.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
|
||||||
|
Lock lock(contextMutex);
|
||||||
|
|
||||||
|
FileMap::iterator it = openFiles.find(std::string(path));
|
||||||
|
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 {
|
||||||
|
return shared_ptr<FileNode>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
std::set<Placeholder *> val = it->second;
|
||||||
|
openFiles.erase(it);
|
||||||
|
openFiles[std::string(to)] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
Lock lock(contextMutex);
|
||||||
|
Placeholder *pl = new Placeholder(node);
|
||||||
|
openFiles[std::string(path)].insert(pl);
|
||||||
|
|
||||||
|
return (void *)pl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EncFS_Context::eraseNode(const char *path, void *pl) {
|
||||||
|
Lock lock(contextMutex);
|
||||||
|
|
||||||
|
Placeholder *ph = (Placeholder *)pl;
|
||||||
|
|
||||||
|
FileMap::iterator it = openFiles.find(std::string(path));
|
||||||
|
rAssert(it != openFiles.end());
|
||||||
|
|
||||||
|
int rmCount = it->second.erase(ph);
|
||||||
|
|
||||||
|
rAssert(rmCount == 1);
|
||||||
|
|
||||||
|
// if no more references to this file, remove the record all together
|
||||||
|
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;
|
||||||
|
openFiles.erase(it);
|
||||||
|
storedName.assign(storedName.length(), '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
delete ph;
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -37,75 +37,70 @@ struct EncFS_Opts;
|
|||||||
class FileNode;
|
class FileNode;
|
||||||
class DirNode;
|
class DirNode;
|
||||||
|
|
||||||
class EncFS_Context
|
class EncFS_Context {
|
||||||
{
|
public:
|
||||||
public:
|
EncFS_Context();
|
||||||
EncFS_Context();
|
~EncFS_Context();
|
||||||
~EncFS_Context();
|
|
||||||
|
|
||||||
shared_ptr<FileNode> getNode(void *ptr);
|
shared_ptr<FileNode> getNode(void *ptr);
|
||||||
shared_ptr<FileNode> lookupNode(const char *path);
|
shared_ptr<FileNode> lookupNode(const char *path);
|
||||||
|
|
||||||
int getAndResetUsageCounter();
|
int getAndResetUsageCounter();
|
||||||
int openFileCount() const;
|
int openFileCount() const;
|
||||||
|
|
||||||
void *putNode(const char *path, const shared_ptr<FileNode> &node);
|
void *putNode(const char *path, const shared_ptr<FileNode> &node);
|
||||||
|
|
||||||
void eraseNode(const char *path, void *placeholder);
|
void eraseNode(const char *path, void *placeholder);
|
||||||
|
|
||||||
void renameNode(const char *oldName, const char *newName);
|
void renameNode(const char *oldName, const char *newName);
|
||||||
|
|
||||||
void setRoot(const shared_ptr<DirNode> &root);
|
void setRoot(const shared_ptr<DirNode> &root);
|
||||||
shared_ptr<DirNode> getRoot(int *err);
|
shared_ptr<DirNode> getRoot(int *err);
|
||||||
bool isMounted();
|
bool isMounted();
|
||||||
|
|
||||||
shared_ptr<EncFS_Args> args;
|
shared_ptr<EncFS_Args> args;
|
||||||
shared_ptr<EncFS_Opts> opts;
|
shared_ptr<EncFS_Opts> opts;
|
||||||
bool publicFilesystem;
|
bool publicFilesystem;
|
||||||
|
|
||||||
// root path to cipher dir
|
// root path to cipher dir
|
||||||
std::string rootCipherDir;
|
std::string rootCipherDir;
|
||||||
|
|
||||||
// for idle monitor
|
// for idle monitor
|
||||||
bool running;
|
bool running;
|
||||||
pthread_t monitorThread;
|
pthread_t monitorThread;
|
||||||
pthread_cond_t wakeupCond;
|
pthread_cond_t wakeupCond;
|
||||||
pthread_mutex_t wakeupMutex;
|
pthread_mutex_t wakeupMutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* This placeholder is what is referenced in FUSE context (passed to
|
/* This placeholder is what is referenced in FUSE context (passed to
|
||||||
* callbacks).
|
* callbacks).
|
||||||
*
|
*
|
||||||
* A FileNode may be opened many times, but only one FileNode instance per
|
* A FileNode may be opened many times, but only one FileNode instance per
|
||||||
* file is kept. Rather then doing reference counting in FileNode, we
|
* file is kept. Rather then doing reference counting in FileNode, we
|
||||||
* store a unique Placeholder for each open() until the corresponding
|
* store a unique Placeholder for each open() until the corresponding
|
||||||
* release() is called. shared_ptr then does our reference counting for
|
* release() is called. shared_ptr then does our reference counting for
|
||||||
* us.
|
* us.
|
||||||
*/
|
*/
|
||||||
struct Placeholder
|
struct Placeholder {
|
||||||
{
|
shared_ptr<FileNode> node;
|
||||||
shared_ptr<FileNode> node;
|
|
||||||
|
|
||||||
Placeholder( const shared_ptr<FileNode> &ptr ) : node(ptr) {}
|
Placeholder(const shared_ptr<FileNode> &ptr) : node(ptr) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// set of open files, indexed by path
|
|
||||||
#ifdef USE_HASHMAP
|
#ifdef USE_HASHMAP
|
||||||
typedef __gnu_cxx::hash_map<std::string,
|
// set of open files, indexed by path
|
||||||
std::set<Placeholder*> > FileMap;
|
typedef __gnu_cxx::hash_map<std::string, std::set<Placeholder *> > FileMap;
|
||||||
#else
|
#else
|
||||||
typedef std::map< std::string,
|
typedef std::map<std::string, std::set<Placeholder *> > FileMap;
|
||||||
std::set<Placeholder*> > FileMap;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mutable pthread_mutex_t contextMutex;
|
mutable pthread_mutex_t contextMutex;
|
||||||
FileMap openFiles;
|
FileMap openFiles;
|
||||||
|
|
||||||
int usageCount;
|
int usageCount;
|
||||||
shared_ptr<DirNode> root;
|
shared_ptr<DirNode> root;
|
||||||
};
|
};
|
||||||
|
|
||||||
int remountFS( EncFS_Context *ctx );
|
int remountFS(EncFS_Context *ctx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
1179
encfs/DirNode.cpp
1179
encfs/DirNode.cpp
File diff suppressed because it is too large
Load Diff
210
encfs/DirNode.h
210
encfs/DirNode.h
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -40,146 +40,140 @@ class RenameOp;
|
|||||||
struct RenameEl;
|
struct RenameEl;
|
||||||
class EncFS_Context;
|
class EncFS_Context;
|
||||||
|
|
||||||
class DirTraverse
|
class DirTraverse {
|
||||||
{
|
public:
|
||||||
public:
|
DirTraverse(const shared_ptr<DIR> &dirPtr, uint64_t iv,
|
||||||
DirTraverse(const shared_ptr<DIR> &dirPtr, uint64_t iv,
|
const shared_ptr<NameIO> &naming);
|
||||||
const shared_ptr<NameIO> &naming);
|
DirTraverse(const DirTraverse &src);
|
||||||
DirTraverse(const DirTraverse &src);
|
~DirTraverse();
|
||||||
~DirTraverse();
|
|
||||||
|
|
||||||
DirTraverse &operator = (const DirTraverse &src);
|
DirTraverse &operator=(const DirTraverse &src);
|
||||||
|
|
||||||
// returns FALSE to indicate an invalid DirTraverse (such as when
|
// returns FALSE to indicate an invalid DirTraverse (such as when
|
||||||
// an invalid directory is requested for traversal)
|
// an invalid directory is requested for traversal)
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
|
|
||||||
// return next plaintext filename
|
// return next plaintext filename
|
||||||
// If fileType is not 0, then it is used to return the filetype (or 0 if
|
// If fileType is not 0, then it is used to return the filetype (or 0 if
|
||||||
// unknown)
|
// unknown)
|
||||||
std::string nextPlaintextName(int *fileType=0, ino_t *inode=0);
|
std::string nextPlaintextName(int *fileType = 0, ino_t *inode = 0);
|
||||||
|
|
||||||
/* Return cipher name of next undecodable filename..
|
/* Return cipher name of next undecodable filename..
|
||||||
The opposite of nextPlaintextName(), as that skips undecodable names..
|
The opposite of nextPlaintextName(), as that skips undecodable names..
|
||||||
*/
|
*/
|
||||||
std::string nextInvalid();
|
std::string nextInvalid();
|
||||||
private:
|
|
||||||
|
|
||||||
shared_ptr<DIR> dir; // struct DIR
|
private:
|
||||||
// initialization vector to use. Not very general purpose, but makes it
|
shared_ptr<DIR> dir; // struct DIR
|
||||||
// more efficient to support filename IV chaining..
|
// initialization vector to use. Not very general purpose, but makes it
|
||||||
uint64_t iv;
|
// more efficient to support filename IV chaining..
|
||||||
shared_ptr<NameIO> naming;
|
uint64_t iv;
|
||||||
|
shared_ptr<NameIO> naming;
|
||||||
};
|
};
|
||||||
inline bool DirTraverse::valid() const { return dir.get() != 0; }
|
inline bool DirTraverse::valid() const { return dir.get() != 0; }
|
||||||
|
|
||||||
#ifdef USE_HASHMAP
|
#ifdef USE_HASHMAP
|
||||||
namespace __gnu_cxx
|
namespace __gnu_cxx {
|
||||||
{
|
template <>
|
||||||
template<> struct hash<std::string>
|
struct hash<std::string> {
|
||||||
{
|
size_t operator()(const std::string &__s) const {
|
||||||
size_t operator() (const std::string &__s) const
|
return __stl_hash_string(__s.c_str());
|
||||||
{
|
}
|
||||||
return __stl_hash_string( __s.c_str() );
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class DirNode
|
class DirNode {
|
||||||
{
|
public:
|
||||||
public:
|
// sourceDir points to where raw files are stored
|
||||||
// sourceDir points to where raw files are stored
|
DirNode(EncFS_Context *ctx, const std::string &sourceDir,
|
||||||
DirNode(EncFS_Context *ctx,
|
const FSConfigPtr &config);
|
||||||
const std::string &sourceDir,
|
~DirNode();
|
||||||
const FSConfigPtr &config );
|
|
||||||
~DirNode();
|
|
||||||
|
|
||||||
// return the path to the root directory
|
// return the path to the root directory
|
||||||
std::string rootDirectory();
|
std::string rootDirectory();
|
||||||
|
|
||||||
// find files
|
// find files
|
||||||
shared_ptr<FileNode> lookupNode( const char *plaintextName,
|
shared_ptr<FileNode> lookupNode(const char *plaintextName,
|
||||||
const char *requestor );
|
const char *requestor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Combined lookupNode + node->open() call. If the open fails, then the
|
Combined lookupNode + node->open() call. If the open fails, then the
|
||||||
node is not retained. If the open succeeds, then the node is returned.
|
node is not retained. If the open succeeds, then the node is returned.
|
||||||
*/
|
*/
|
||||||
shared_ptr<FileNode> openNode( const char *plaintextName,
|
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 cipherPath(const char *plaintextPath);
|
||||||
std::string cipherPathWithoutRoot( const char *plaintextPath );
|
std::string cipherPathWithoutRoot(const char *plaintextPath);
|
||||||
std::string plainPath( const char *cipherPath );
|
std::string plainPath(const char *cipherPath);
|
||||||
|
|
||||||
// relative cipherPath is the same as cipherPath except that it doesn't
|
// relative cipherPath is the same as cipherPath except that it doesn't
|
||||||
// prepent the mount point. That it, it doesn't return a fully qualified
|
// prepent the mount point. That it, it doesn't return a fully qualified
|
||||||
// name, just a relative path within the encrypted filesystem.
|
// name, just a relative path within the encrypted filesystem.
|
||||||
std::string relativeCipherPath( const char *plaintextPath );
|
std::string relativeCipherPath(const char *plaintextPath);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns true if file names are dependent on the parent directory name.
|
Returns true if file names are dependent on the parent directory name.
|
||||||
If a directory name is changed, then all the filenames must also be
|
If a directory name is changed, then all the filenames must also be
|
||||||
changed.
|
changed.
|
||||||
*/
|
*/
|
||||||
bool hasDirectoryNameDependency() const;
|
bool hasDirectoryNameDependency() const;
|
||||||
|
|
||||||
// unlink the specified file
|
// unlink the specified file
|
||||||
int unlink( const char *plaintextName );
|
int unlink(const char *plaintextName);
|
||||||
|
|
||||||
// traverse directory
|
// traverse directory
|
||||||
DirTraverse openDir( const char *plainDirName );
|
DirTraverse openDir(const char *plainDirName);
|
||||||
|
|
||||||
// uid and gid are used as the directory owner, only if not zero
|
// uid and gid are used as the directory owner, only if not zero
|
||||||
int mkdir( const char *plaintextPath, mode_t mode,
|
int mkdir(const char *plaintextPath, mode_t mode, uid_t uid = 0,
|
||||||
uid_t uid = 0, gid_t gid = 0);
|
gid_t gid = 0);
|
||||||
|
|
||||||
int rename( const char *fromPlaintext, const char *toPlaintext );
|
int rename(const char *fromPlaintext, const char *toPlaintext);
|
||||||
|
|
||||||
int link( const char *from, const char *to );
|
int link(const char *from, const char *to);
|
||||||
|
|
||||||
// returns idle time of filesystem in seconds
|
|
||||||
int idleSeconds();
|
|
||||||
|
|
||||||
protected:
|
// returns idle time of filesystem in seconds
|
||||||
|
int idleSeconds();
|
||||||
|
|
||||||
/*
|
protected:
|
||||||
notify that a file is being renamed.
|
/*
|
||||||
This renames the internal node, if any. If the file is not open, then
|
notify that a file is being renamed.
|
||||||
this call has no effect.
|
This renames the internal node, if any. If the file is not open, then
|
||||||
Returns the FileNode if it was found.
|
this call has no effect.
|
||||||
*/
|
Returns the FileNode if it was found.
|
||||||
shared_ptr<FileNode> renameNode( const char *from, const char *to );
|
*/
|
||||||
shared_ptr<FileNode> renameNode( const char *from, const char *to,
|
shared_ptr<FileNode> renameNode(const char *from, const char *to);
|
||||||
bool forwardMode );
|
shared_ptr<FileNode> renameNode(const char *from, const char *to,
|
||||||
|
bool forwardMode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
when directory IV chaining is enabled, a directory can't be renamed
|
when directory IV chaining is enabled, a directory can't be renamed
|
||||||
without renaming all its contents as well. recursiveRename should be
|
without renaming all its contents as well. recursiveRename should be
|
||||||
called after renaming the directory, passing in the plaintext from and
|
called after renaming the directory, passing in the plaintext from and
|
||||||
to paths.
|
to paths.
|
||||||
*/
|
*/
|
||||||
shared_ptr<RenameOp> newRenameOp( const char *from, const char *to );
|
shared_ptr<RenameOp> newRenameOp(const char *from, const char *to);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class RenameOp;
|
||||||
|
|
||||||
friend class RenameOp;
|
bool genRenameList(std::list<RenameEl> &list, const char *fromP,
|
||||||
|
const char *toP);
|
||||||
|
|
||||||
bool genRenameList( std::list<RenameEl> &list, const char *fromP,
|
shared_ptr<FileNode> findOrCreate(const char *plainName);
|
||||||
const char *toP );
|
|
||||||
|
|
||||||
shared_ptr<FileNode> findOrCreate( const char *plainName);
|
|
||||||
|
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
EncFS_Context *ctx;
|
EncFS_Context *ctx;
|
||||||
|
|
||||||
// passed in as configuration
|
// passed in as configuration
|
||||||
std::string rootDir;
|
std::string rootDir;
|
||||||
FSConfigPtr fsConfig;
|
FSConfigPtr fsConfig;
|
||||||
|
|
||||||
shared_ptr<NameIO> naming;
|
shared_ptr<NameIO> naming;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
139
encfs/FSConfig.h
139
encfs/FSConfig.h
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -28,105 +28,98 @@
|
|||||||
#include "CipherKey.h"
|
#include "CipherKey.h"
|
||||||
#include "shared_ptr.h"
|
#include "shared_ptr.h"
|
||||||
|
|
||||||
enum ConfigType
|
enum ConfigType {
|
||||||
{
|
Config_None = 0,
|
||||||
Config_None = 0,
|
Config_Prehistoric,
|
||||||
Config_Prehistoric,
|
Config_V3,
|
||||||
Config_V3,
|
Config_V4,
|
||||||
Config_V4,
|
Config_V5,
|
||||||
Config_V5,
|
Config_V6
|
||||||
Config_V6
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EncFS_Opts;
|
struct EncFS_Opts;
|
||||||
class Cipher;
|
class Cipher;
|
||||||
class NameIO;
|
class NameIO;
|
||||||
|
|
||||||
struct EncFSConfig
|
struct EncFSConfig {
|
||||||
{
|
ConfigType cfgType;
|
||||||
ConfigType cfgType;
|
|
||||||
|
|
||||||
std::string creator;
|
std::string creator;
|
||||||
int subVersion;
|
int subVersion;
|
||||||
|
|
||||||
// interface of cipher
|
// interface of cipher
|
||||||
rel::Interface cipherIface;
|
rel::Interface cipherIface;
|
||||||
// interface used for file name coding
|
// interface used for file name coding
|
||||||
rel::Interface nameIface;
|
rel::Interface nameIface;
|
||||||
int keySize; // reported in bits
|
int keySize; // reported in bits
|
||||||
int blockSize; // reported in bytes
|
int blockSize; // reported in bytes
|
||||||
|
|
||||||
std::vector<unsigned char> keyData;
|
std::vector<unsigned char> keyData;
|
||||||
|
|
||||||
std::vector<unsigned char> salt;
|
std::vector<unsigned char> salt;
|
||||||
int kdfIterations;
|
int kdfIterations;
|
||||||
long desiredKDFDuration;
|
long desiredKDFDuration;
|
||||||
|
|
||||||
int blockMACBytes; // MAC headers on blocks..
|
int blockMACBytes; // MAC headers on blocks..
|
||||||
int blockMACRandBytes; // number of random bytes in the block header
|
int blockMACRandBytes; // number of random bytes in the block header
|
||||||
|
|
||||||
bool uniqueIV; // per-file Initialization Vector
|
bool uniqueIV; // per-file Initialization Vector
|
||||||
bool externalIVChaining; // IV seeding by filename IV chaining
|
bool externalIVChaining; // IV seeding by filename IV chaining
|
||||||
|
|
||||||
bool chainedNameIV; // filename IV chaining
|
bool chainedNameIV; // filename IV chaining
|
||||||
bool allowHoles; // allow holes in files (implicit zero blocks)
|
bool allowHoles; // allow holes in files (implicit zero blocks)
|
||||||
|
|
||||||
EncFSConfig()
|
EncFSConfig() : keyData(), salt() {
|
||||||
: keyData()
|
cfgType = Config_None;
|
||||||
, salt()
|
subVersion = 0;
|
||||||
{
|
blockMACBytes = 0;
|
||||||
cfgType = Config_None;
|
blockMACRandBytes = 0;
|
||||||
subVersion = 0;
|
uniqueIV = false;
|
||||||
blockMACBytes = 0;
|
externalIVChaining = false;
|
||||||
blockMACRandBytes = 0;
|
chainedNameIV = false;
|
||||||
uniqueIV = false;
|
allowHoles = false;
|
||||||
externalIVChaining = false;
|
|
||||||
chainedNameIV = false;
|
|
||||||
allowHoles = false;
|
|
||||||
|
|
||||||
kdfIterations = 0;
|
kdfIterations = 0;
|
||||||
desiredKDFDuration = 500;
|
desiredKDFDuration = 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherKey getUserKey(bool useStdin);
|
CipherKey getUserKey(bool useStdin);
|
||||||
CipherKey getUserKey(const std::string &passwordProgram,
|
CipherKey getUserKey(const std::string &passwordProgram,
|
||||||
const std::string &rootDir);
|
const std::string &rootDir);
|
||||||
CipherKey getNewUserKey();
|
CipherKey getNewUserKey();
|
||||||
|
|
||||||
shared_ptr<Cipher> getCipher() const;
|
|
||||||
|
|
||||||
// deprecated
|
shared_ptr<Cipher> getCipher() const;
|
||||||
void assignKeyData(const std::string &in);
|
|
||||||
void assignKeyData(unsigned char *data, int length);
|
|
||||||
void assignSaltData(unsigned char *data, int length);
|
|
||||||
|
|
||||||
unsigned char *getKeyData() const;
|
// deprecated
|
||||||
unsigned char *getSaltData() const;
|
void assignKeyData(const std::string &in);
|
||||||
|
void assignKeyData(unsigned char *data, int length);
|
||||||
|
void assignSaltData(unsigned char *data, int length);
|
||||||
|
|
||||||
private:
|
unsigned char *getKeyData() const;
|
||||||
CipherKey makeKey(const char *password, int passwdLen);
|
unsigned char *getSaltData() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CipherKey makeKey(const char *password, int passwdLen);
|
||||||
};
|
};
|
||||||
|
|
||||||
// helpers for serializing to/from a stream
|
// helpers for serializing to/from a stream
|
||||||
std::ostream &operator << (std::ostream &os, const EncFSConfig &cfg);
|
std::ostream &operator<<(std::ostream &os, const EncFSConfig &cfg);
|
||||||
std::istream &operator >> (std::istream &os, EncFSConfig &cfg);
|
std::istream &operator>>(std::istream &os, EncFSConfig &cfg);
|
||||||
|
|
||||||
struct FSConfig
|
struct FSConfig {
|
||||||
{
|
shared_ptr<EncFSConfig> config;
|
||||||
shared_ptr<EncFSConfig> config;
|
shared_ptr<EncFS_Opts> opts;
|
||||||
shared_ptr<EncFS_Opts> opts;
|
|
||||||
|
|
||||||
shared_ptr<Cipher> cipher;
|
shared_ptr<Cipher> cipher;
|
||||||
CipherKey key;
|
CipherKey key;
|
||||||
shared_ptr<NameIO> nameCoding;
|
shared_ptr<NameIO> nameCoding;
|
||||||
|
|
||||||
bool forceDecode; // force decode on MAC block failures
|
bool forceDecode; // force decode on MAC block failures
|
||||||
bool reverseEncryption; // reverse encryption operation
|
bool reverseEncryption; // reverse encryption operation
|
||||||
|
|
||||||
bool idleTracking; // turn on idle monitoring of filesystem
|
bool idleTracking; // turn on idle monitoring of filesystem
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef shared_ptr<FSConfig> FSConfigPtr;
|
typedef shared_ptr<FSConfig> FSConfigPtr;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -20,22 +20,13 @@
|
|||||||
|
|
||||||
#include "FileIO.h"
|
#include "FileIO.h"
|
||||||
|
|
||||||
FileIO::FileIO()
|
FileIO::FileIO() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FileIO::~FileIO()
|
FileIO::~FileIO() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileIO::blockSize() const
|
int FileIO::blockSize() const { return 1; }
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileIO::setIV( uint64_t iv )
|
bool FileIO::setIV(uint64_t iv) {
|
||||||
{
|
(void)iv;
|
||||||
(void)iv;
|
return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -27,61 +27,54 @@
|
|||||||
|
|
||||||
#include "Interface.h"
|
#include "Interface.h"
|
||||||
|
|
||||||
struct IORequest
|
struct IORequest {
|
||||||
{
|
off_t offset;
|
||||||
off_t offset;
|
|
||||||
|
|
||||||
// amount of bytes to read/write.
|
// amount of bytes to read/write.
|
||||||
int dataLen;
|
int dataLen;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
|
||||||
IORequest();
|
IORequest();
|
||||||
};
|
};
|
||||||
|
|
||||||
inline IORequest::IORequest()
|
inline IORequest::IORequest() : offset(0), dataLen(0), data(0) {}
|
||||||
: offset(0)
|
|
||||||
, dataLen(0)
|
|
||||||
, data(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
class FileIO
|
class FileIO {
|
||||||
{
|
public:
|
||||||
public:
|
FileIO();
|
||||||
FileIO();
|
virtual ~FileIO();
|
||||||
virtual ~FileIO();
|
|
||||||
|
|
||||||
virtual rel::Interface interface() const =0;
|
virtual rel::Interface interface() const = 0;
|
||||||
|
|
||||||
// default implementation returns 1, meaning this is not block oriented.
|
// default implementation returns 1, meaning this is not block oriented.
|
||||||
virtual int blockSize() const;
|
virtual int blockSize() const;
|
||||||
|
|
||||||
virtual void setFileName(const char *fileName) =0;
|
virtual void setFileName(const char *fileName) = 0;
|
||||||
virtual const char *getFileName() const =0;
|
virtual const char *getFileName() const = 0;
|
||||||
|
|
||||||
// Not sure about this -- it is specific to CipherFileIO, but the
|
// Not sure about this -- it is specific to CipherFileIO, but the
|
||||||
// alternative methods of exposing this interface aren't much nicer..
|
// alternative methods of exposing this interface aren't much nicer..
|
||||||
virtual bool setIV( uint64_t iv );
|
virtual bool setIV(uint64_t iv);
|
||||||
|
|
||||||
// open file for specified mode. There is no corresponding close, so a
|
// open file for specified mode. There is no corresponding close, so a
|
||||||
// file is open until the FileIO interface is destroyed.
|
// file is open until the FileIO interface is destroyed.
|
||||||
virtual int open( int flags ) =0;
|
virtual int open(int flags) = 0;
|
||||||
|
|
||||||
// get filesystem attributes for a file
|
|
||||||
virtual int getAttr( struct stat *stbuf ) const =0;
|
|
||||||
virtual off_t getSize( ) const =0;
|
|
||||||
|
|
||||||
virtual ssize_t read( const IORequest &req ) const =0;
|
// get filesystem attributes for a file
|
||||||
virtual bool write( const IORequest &req ) =0;
|
virtual int getAttr(struct stat *stbuf) const = 0;
|
||||||
|
virtual off_t getSize() const = 0;
|
||||||
|
|
||||||
virtual int truncate( off_t size ) =0;
|
virtual ssize_t read(const IORequest &req) const = 0;
|
||||||
|
virtual bool write(const IORequest &req) = 0;
|
||||||
|
|
||||||
virtual bool isWritable() const =0;
|
virtual int truncate(off_t size) = 0;
|
||||||
private:
|
|
||||||
// not implemented..
|
virtual bool isWritable() const = 0;
|
||||||
FileIO( const FileIO & );
|
|
||||||
FileIO &operator = ( const FileIO & );
|
private:
|
||||||
|
// not implemented..
|
||||||
|
FileIO(const FileIO &);
|
||||||
|
FileIO &operator=(const FileIO &);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -66,242 +66,202 @@ using namespace rlog;
|
|||||||
static RLogChannel *Info = DEF_CHANNEL("info/FileNode", Log_Info);
|
static RLogChannel *Info = DEF_CHANNEL("info/FileNode", Log_Info);
|
||||||
|
|
||||||
FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
|
FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
|
||||||
const char *plaintextName_, const char *cipherName_)
|
const char *plaintextName_, const char *cipherName_) {
|
||||||
{
|
pthread_mutex_init(&mutex, 0);
|
||||||
pthread_mutex_init( &mutex, 0 );
|
|
||||||
|
|
||||||
Lock _lock( mutex );
|
|
||||||
|
|
||||||
this->_pname = plaintextName_;
|
Lock _lock(mutex);
|
||||||
this->_cname = cipherName_;
|
|
||||||
this->parent = parent_;
|
|
||||||
|
|
||||||
this->fsConfig = cfg;
|
this->_pname = plaintextName_;
|
||||||
|
this->_cname = cipherName_;
|
||||||
|
this->parent = parent_;
|
||||||
|
|
||||||
// chain RawFileIO & CipherFileIO
|
this->fsConfig = cfg;
|
||||||
shared_ptr<FileIO> rawIO( new RawFileIO( _cname ) );
|
|
||||||
io = shared_ptr<FileIO>( new CipherFileIO( rawIO, fsConfig ));
|
|
||||||
|
|
||||||
if(cfg->config->blockMACBytes || cfg->config->blockMACRandBytes)
|
// chain RawFileIO & CipherFileIO
|
||||||
io = shared_ptr<FileIO>(new MACFileIO(io, fsConfig));
|
shared_ptr<FileIO> rawIO(new RawFileIO(_cname));
|
||||||
|
io = shared_ptr<FileIO>(new CipherFileIO(rawIO, fsConfig));
|
||||||
|
|
||||||
|
if (cfg->config->blockMACBytes || cfg->config->blockMACRandBytes)
|
||||||
|
io = shared_ptr<FileIO>(new MACFileIO(io, fsConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
FileNode::~FileNode()
|
FileNode::~FileNode() {
|
||||||
{
|
// FileNode mutex should be locked before the destructor is called
|
||||||
// FileNode mutex should be locked before the destructor is called
|
// pthread_mutex_lock( &mutex );
|
||||||
//pthread_mutex_lock( &mutex );
|
|
||||||
|
|
||||||
_pname.assign( _pname.length(), '\0' );
|
_pname.assign(_pname.length(), '\0');
|
||||||
_cname.assign( _cname.length(), '\0' );
|
_cname.assign(_cname.length(), '\0');
|
||||||
io.reset();
|
io.reset();
|
||||||
|
|
||||||
pthread_mutex_destroy( &mutex );
|
pthread_mutex_destroy(&mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *FileNode::cipherName() const
|
const char *FileNode::cipherName() const { return _cname.c_str(); }
|
||||||
{
|
|
||||||
return _cname.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *FileNode::plaintextName() const
|
const char *FileNode::plaintextName() const { return _pname.c_str(); }
|
||||||
{
|
|
||||||
return _pname.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
string FileNode::plaintextParent() const
|
string FileNode::plaintextParent() const { return parentDirectory(_pname); }
|
||||||
{
|
|
||||||
return parentDirectory( _pname );
|
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileNode::setName( const char *plaintextName_, const char *cipherName_,
|
|
||||||
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;
|
|
||||||
|
|
||||||
// now change the name..
|
|
||||||
if(plaintextName_)
|
|
||||||
this->_pname = plaintextName_;
|
|
||||||
if(cipherName_)
|
|
||||||
{
|
|
||||||
this->_cname = cipherName_;
|
|
||||||
io->setFileName( cipherName_ );
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
std::string oldPName = _pname;
|
|
||||||
std::string oldCName = _cname;
|
|
||||||
|
|
||||||
if(plaintextName_)
|
|
||||||
this->_pname = plaintextName_;
|
|
||||||
if(cipherName_)
|
|
||||||
{
|
|
||||||
this->_cname = cipherName_;
|
|
||||||
io->setFileName( cipherName_ );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fsConfig->config->externalIVChaining && !setIV(io, iv))
|
|
||||||
{
|
|
||||||
_pname = oldPName;
|
|
||||||
_cname = oldCName;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid)
|
bool FileNode::setName(const char *plaintextName_, const char *cipherName_,
|
||||||
{
|
uint64_t iv, bool setIVFirst) {
|
||||||
Lock _lock( mutex );
|
// Lock _lock( mutex );
|
||||||
|
rDebug("calling setIV on %s", cipherName_);
|
||||||
|
if (setIVFirst) {
|
||||||
|
if (fsConfig->config->externalIVChaining && !setIV(io, iv)) return false;
|
||||||
|
|
||||||
int res;
|
// now change the name..
|
||||||
int olduid = -1;
|
if (plaintextName_) this->_pname = plaintextName_;
|
||||||
int oldgid = -1;
|
if (cipherName_) {
|
||||||
if(uid != 0)
|
this->_cname = cipherName_;
|
||||||
{
|
io->setFileName(cipherName_);
|
||||||
olduid = setfsuid( uid );
|
|
||||||
if(olduid == -1)
|
|
||||||
{
|
|
||||||
rInfo("setfsuid error: %s", strerror(errno));
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(gid != 0)
|
} else {
|
||||||
{
|
std::string oldPName = _pname;
|
||||||
oldgid = setfsgid( gid );
|
std::string oldCName = _cname;
|
||||||
if(oldgid == -1)
|
|
||||||
{
|
if (plaintextName_) this->_pname = plaintextName_;
|
||||||
rInfo("setfsgid error: %s", strerror(errno));
|
if (cipherName_) {
|
||||||
return -EPERM;
|
this->_cname = cipherName_;
|
||||||
}
|
io->setFileName(cipherName_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (fsConfig->config->externalIVChaining && !setIV(io, iv)) {
|
||||||
* cf. xmp_mknod() in fusexmp.c
|
_pname = oldPName;
|
||||||
* The regular file stuff could be stripped off if there
|
_cname = oldCName;
|
||||||
* were a create method (advised to have)
|
return false;
|
||||||
*/
|
|
||||||
if (S_ISREG( mode )) {
|
|
||||||
res = ::open( _cname.c_str(), O_CREAT | O_EXCL | O_WRONLY, mode );
|
|
||||||
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(res == -1)
|
|
||||||
{
|
|
||||||
int eno = errno;
|
|
||||||
rDebug("mknod error: %s", strerror(eno));
|
|
||||||
res = -eno;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileNode::open(int flags) const
|
int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid) {
|
||||||
{
|
Lock _lock(mutex);
|
||||||
Lock _lock( mutex );
|
|
||||||
|
|
||||||
int res = io->open( flags );
|
int res;
|
||||||
return res;
|
int olduid = -1;
|
||||||
|
int oldgid = -1;
|
||||||
|
if (uid != 0) {
|
||||||
|
olduid = setfsuid(uid);
|
||||||
|
if (olduid == -1) {
|
||||||
|
rInfo("setfsuid error: %s", strerror(errno));
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gid != 0) {
|
||||||
|
oldgid = setfsgid(gid);
|
||||||
|
if (oldgid == -1) {
|
||||||
|
rInfo("setfsgid error: %s", strerror(errno));
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cf. xmp_mknod() in fusexmp.c
|
||||||
|
* The regular file stuff could be stripped off if there
|
||||||
|
* were a create method (advised to have)
|
||||||
|
*/
|
||||||
|
if (S_ISREG(mode)) {
|
||||||
|
res = ::open(_cname.c_str(), O_CREAT | O_EXCL | O_WRONLY, mode);
|
||||||
|
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 (res == -1) {
|
||||||
|
int eno = errno;
|
||||||
|
rDebug("mknod error: %s", strerror(eno));
|
||||||
|
res = -eno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileNode::getAttr(struct stat *stbuf) const
|
int FileNode::open(int flags) const {
|
||||||
{
|
Lock _lock(mutex);
|
||||||
Lock _lock( mutex );
|
|
||||||
|
|
||||||
int res = io->getAttr( stbuf );
|
int res = io->open(flags);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t FileNode::getSize() const
|
int FileNode::getAttr(struct stat *stbuf) const {
|
||||||
{
|
Lock _lock(mutex);
|
||||||
Lock _lock( mutex );
|
|
||||||
|
|
||||||
int res = io->getSize();
|
int res = io->getAttr(stbuf);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t FileNode::read( off_t offset, unsigned char *data, ssize_t size ) const
|
off_t FileNode::getSize() const {
|
||||||
{
|
Lock _lock(mutex);
|
||||||
IORequest req;
|
|
||||||
req.offset = offset;
|
|
||||||
req.dataLen = size;
|
|
||||||
req.data = data;
|
|
||||||
|
|
||||||
Lock _lock( mutex );
|
int res = io->getSize();
|
||||||
|
return res;
|
||||||
return io->read( req );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileNode::write(off_t offset, unsigned char *data, ssize_t size)
|
ssize_t FileNode::read(off_t offset, unsigned char *data, ssize_t size) const {
|
||||||
{
|
IORequest req;
|
||||||
rLog(Info, "FileNode::write offset %" PRIi64 ", data size %i",
|
req.offset = offset;
|
||||||
offset, (int)size);
|
req.dataLen = size;
|
||||||
|
req.data = data;
|
||||||
|
|
||||||
IORequest req;
|
Lock _lock(mutex);
|
||||||
req.offset = offset;
|
|
||||||
req.dataLen = size;
|
|
||||||
req.data = data;
|
|
||||||
|
|
||||||
Lock _lock( mutex );
|
|
||||||
|
|
||||||
return io->write( req );
|
return io->read(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileNode::truncate( off_t size )
|
bool FileNode::write(off_t offset, unsigned char *data, ssize_t size) {
|
||||||
{
|
rLog(Info, "FileNode::write offset %" PRIi64 ", data size %i", offset,
|
||||||
Lock _lock( mutex );
|
(int)size);
|
||||||
|
|
||||||
return io->truncate( size );
|
IORequest req;
|
||||||
|
req.offset = offset;
|
||||||
|
req.dataLen = size;
|
||||||
|
req.data = data;
|
||||||
|
|
||||||
|
Lock _lock(mutex);
|
||||||
|
|
||||||
|
return io->write(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileNode::sync(bool datasync)
|
int FileNode::truncate(off_t size) {
|
||||||
{
|
Lock _lock(mutex);
|
||||||
Lock _lock( mutex );
|
|
||||||
|
|
||||||
int fh = io->open( O_RDONLY );
|
return io->truncate(size);
|
||||||
if(fh >= 0)
|
}
|
||||||
{
|
|
||||||
int res = -EIO;
|
int FileNode::sync(bool datasync) {
|
||||||
|
Lock _lock(mutex);
|
||||||
|
|
||||||
|
int fh = io->open(O_RDONLY);
|
||||||
|
if (fh >= 0) {
|
||||||
|
int res = -EIO;
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
if(datasync)
|
if (datasync)
|
||||||
res = fdatasync( fh );
|
res = fdatasync(fh);
|
||||||
else
|
else
|
||||||
res = fsync( fh );
|
res = fsync(fh);
|
||||||
#else
|
#else
|
||||||
(void)datasync;
|
(void)datasync;
|
||||||
// no fdatasync support
|
// no fdatasync support
|
||||||
// TODO: use autoconfig to check for it..
|
// TODO: use autoconfig to check for it..
|
||||||
res = fsync(fh);
|
res = fsync(fh);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(res == -1)
|
|
||||||
res = -errno;
|
|
||||||
|
|
||||||
return res;
|
if (res == -1) res = -errno;
|
||||||
} else
|
|
||||||
return fh;
|
return res;
|
||||||
|
} else
|
||||||
|
return fh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _FileNode_incl_
|
#ifndef _FileNode_incl_
|
||||||
#define _FileNode_incl_
|
#define _FileNode_incl_
|
||||||
|
|
||||||
@ -33,68 +33,62 @@ class Cipher;
|
|||||||
class FileIO;
|
class FileIO;
|
||||||
class DirNode;
|
class DirNode;
|
||||||
|
|
||||||
class FileNode
|
class FileNode {
|
||||||
{
|
public:
|
||||||
public:
|
FileNode(DirNode *parent, const FSConfigPtr &cfg, const char *plaintextName,
|
||||||
FileNode(DirNode *parent,
|
const char *cipherName);
|
||||||
const FSConfigPtr &cfg,
|
~FileNode();
|
||||||
const char *plaintextName,
|
|
||||||
const char *cipherName);
|
|
||||||
~FileNode();
|
|
||||||
|
|
||||||
const char *plaintextName() const;
|
const char *plaintextName() const;
|
||||||
const char *cipherName() const;
|
const char *cipherName() const;
|
||||||
|
|
||||||
// directory portion of plaintextName
|
// directory portion of plaintextName
|
||||||
std::string plaintextParent() const;
|
std::string plaintextParent() const;
|
||||||
|
|
||||||
// if setIVFirst is true, then the IV is changed before the name is changed
|
// if setIVFirst is true, then the IV is changed before the name is changed
|
||||||
// (default). The reverse is also supported for special cases..
|
// (default). The reverse is also supported for special cases..
|
||||||
bool setName( const char *plaintextName, const char *cipherName,
|
bool setName(const char *plaintextName, const char *cipherName, uint64_t iv,
|
||||||
uint64_t iv, bool setIVFirst = true);
|
bool setIVFirst = true);
|
||||||
|
|
||||||
// create node
|
// create node
|
||||||
// If uid/gid are not 0, then chown is used change ownership as specified
|
// If uid/gid are not 0, then chown is used change ownership as specified
|
||||||
int mknod(mode_t mode, dev_t rdev, uid_t uid = 0, gid_t gid = 0);
|
int mknod(mode_t mode, dev_t rdev, uid_t uid = 0, gid_t gid = 0);
|
||||||
|
|
||||||
// Returns < 0 on error (-errno), file descriptor on success.
|
// Returns < 0 on error (-errno), file descriptor on success.
|
||||||
int open(int flags) const;
|
int open(int flags) const;
|
||||||
|
|
||||||
// getAttr returns 0 on success, -errno on failure
|
// getAttr returns 0 on success, -errno on failure
|
||||||
int getAttr(struct stat *stbuf) const;
|
int getAttr(struct stat *stbuf) const;
|
||||||
off_t getSize() const;
|
off_t getSize() const;
|
||||||
|
|
||||||
ssize_t read(off_t offset, unsigned char *data, ssize_t size) const;
|
ssize_t read(off_t offset, unsigned char *data, ssize_t size) const;
|
||||||
bool write(off_t offset, unsigned char *data, ssize_t size);
|
bool write(off_t offset, unsigned char *data, ssize_t size);
|
||||||
|
|
||||||
// truncate the file to a particular size
|
// truncate the file to a particular size
|
||||||
int truncate( off_t size );
|
int truncate(off_t size);
|
||||||
|
|
||||||
// datasync or full sync
|
// datasync or full sync
|
||||||
int sync(bool dataSync);
|
int sync(bool dataSync);
|
||||||
private:
|
|
||||||
|
|
||||||
// doing locking at the FileNode level isn't as efficient as at the
|
private:
|
||||||
// lowest level of RawFileIO, since that means locks are held longer
|
// doing locking at the FileNode level isn't as efficient as at the
|
||||||
// (held during CPU intensive crypto operations!). However it makes it
|
// lowest level of RawFileIO, since that means locks are held longer
|
||||||
// easier to avoid any race conditions with operations such as
|
// (held during CPU intensive crypto operations!). However it makes it
|
||||||
// truncate() which may result in multiple calls down to the FileIO
|
// easier to avoid any race conditions with operations such as
|
||||||
// level.
|
// truncate() which may result in multiple calls down to the FileIO
|
||||||
mutable pthread_mutex_t mutex;
|
// level.
|
||||||
|
mutable pthread_mutex_t mutex;
|
||||||
|
|
||||||
FSConfigPtr fsConfig;
|
FSConfigPtr fsConfig;
|
||||||
|
|
||||||
shared_ptr<FileIO> io;
|
shared_ptr<FileIO> io;
|
||||||
std::string _pname; // plaintext name
|
std::string _pname; // plaintext name
|
||||||
std::string _cname; // encrypted name
|
std::string _cname; // encrypted name
|
||||||
DirNode *parent;
|
DirNode *parent;
|
||||||
|
|
||||||
private:
|
|
||||||
FileNode(const FileNode &src);
|
|
||||||
FileNode &operator = (const FileNode &src);
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileNode(const FileNode &src);
|
||||||
|
FileNode &operator=(const FileNode &src);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
2900
encfs/FileUtils.cpp
2900
encfs/FileUtils.cpp
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _FileUtils_incl_
|
#ifndef _FileUtils_incl_
|
||||||
#define _FileUtils_incl_
|
#define _FileUtils_incl_
|
||||||
|
|
||||||
@ -27,118 +27,106 @@
|
|||||||
#include "FSConfig.h"
|
#include "FSConfig.h"
|
||||||
|
|
||||||
// true if the path points to an existing node (of any type)
|
// true if the path points to an existing node (of any type)
|
||||||
bool fileExists( const char *fileName );
|
bool fileExists(const char *fileName);
|
||||||
// true if path is a directory
|
// true if path is a directory
|
||||||
bool isDirectory( const char *fileName );
|
bool isDirectory(const char *fileName);
|
||||||
// true if starts with '/'
|
// true if starts with '/'
|
||||||
bool isAbsolutePath( const char *fileName );
|
bool isAbsolutePath(const char *fileName);
|
||||||
// pointer to just after the last '/'
|
// pointer to just after the last '/'
|
||||||
const char *lastPathElement( const char *name );
|
const char *lastPathElement(const char *name);
|
||||||
|
|
||||||
std::string parentDirectory( const std::string &path );
|
std::string parentDirectory(const std::string &path);
|
||||||
|
|
||||||
// ask the user for permission to create the directory. If they say ok, then
|
// ask the user for permission to create the directory. If they say ok, then
|
||||||
// do it and return true.
|
// do it and return true.
|
||||||
bool userAllowMkdir(const char *dirPath, mode_t mode );
|
bool userAllowMkdir(const char *dirPath, mode_t mode);
|
||||||
bool userAllowMkdir(int promptno, const char *dirPath, mode_t mode );
|
bool userAllowMkdir(int promptno, const char *dirPath, mode_t mode);
|
||||||
|
|
||||||
class Cipher;
|
class Cipher;
|
||||||
class DirNode;
|
class DirNode;
|
||||||
|
|
||||||
struct EncFS_Root
|
struct EncFS_Root {
|
||||||
{
|
shared_ptr<Cipher> cipher;
|
||||||
shared_ptr<Cipher> cipher;
|
CipherKey volumeKey;
|
||||||
CipherKey volumeKey;
|
shared_ptr<DirNode> root;
|
||||||
shared_ptr<DirNode> root;
|
|
||||||
|
|
||||||
EncFS_Root();
|
EncFS_Root();
|
||||||
~EncFS_Root();
|
~EncFS_Root();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef shared_ptr<EncFS_Root> RootPtr;
|
typedef shared_ptr<EncFS_Root> RootPtr;
|
||||||
|
|
||||||
enum ConfigMode
|
enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia };
|
||||||
{
|
|
||||||
Config_Prompt,
|
|
||||||
Config_Standard,
|
|
||||||
Config_Paranoia
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EncFS_Opts
|
struct EncFS_Opts {
|
||||||
{
|
std::string rootDir;
|
||||||
std::string rootDir;
|
bool createIfNotFound; // create filesystem if not found
|
||||||
bool createIfNotFound; // create filesystem if not found
|
bool idleTracking; // turn on idle monitoring of filesystem
|
||||||
bool idleTracking; // turn on idle monitoring of filesystem
|
bool mountOnDemand; // mounting on-demand
|
||||||
bool mountOnDemand; // mounting on-demand
|
bool delayMount; // delay initial mount
|
||||||
bool delayMount; // delay initial mount
|
|
||||||
|
|
||||||
bool checkKey; // check crypto key decoding
|
bool checkKey; // check crypto key decoding
|
||||||
bool forceDecode; // force decode on MAC block failures
|
bool forceDecode; // force decode on MAC block failures
|
||||||
|
|
||||||
std::string passwordProgram; // path to password program (or empty)
|
std::string passwordProgram; // path to password program (or empty)
|
||||||
bool useStdin; // read password from stdin rather then prompting
|
bool useStdin; // read password from stdin rather then prompting
|
||||||
bool annotate; // print annotation line prompt to stderr.
|
bool annotate; // print annotation line prompt to stderr.
|
||||||
|
|
||||||
bool ownerCreate; // set owner of new files to caller
|
bool ownerCreate; // set owner of new files to caller
|
||||||
|
|
||||||
bool reverseEncryption; // Reverse encryption
|
bool reverseEncryption; // Reverse encryption
|
||||||
|
|
||||||
ConfigMode configMode;
|
ConfigMode configMode;
|
||||||
|
|
||||||
EncFS_Opts()
|
EncFS_Opts() {
|
||||||
{
|
createIfNotFound = true;
|
||||||
createIfNotFound = true;
|
idleTracking = false;
|
||||||
idleTracking = false;
|
mountOnDemand = false;
|
||||||
mountOnDemand = false;
|
delayMount = false;
|
||||||
delayMount = false;
|
checkKey = true;
|
||||||
checkKey = true;
|
forceDecode = false;
|
||||||
forceDecode = false;
|
useStdin = false;
|
||||||
useStdin = false;
|
annotate = false;
|
||||||
annotate = false;
|
ownerCreate = false;
|
||||||
ownerCreate = false;
|
reverseEncryption = false;
|
||||||
reverseEncryption = false;
|
configMode = Config_Prompt;
|
||||||
configMode = Config_Prompt;
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read existing config file. Looks for any supported configuration version.
|
Read existing config file. Looks for any supported configuration version.
|
||||||
*/
|
*/
|
||||||
ConfigType readConfig( const std::string &rootDir,
|
ConfigType readConfig(const std::string &rootDir,
|
||||||
const shared_ptr<EncFSConfig> &config );
|
const shared_ptr<EncFSConfig> &config);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Save the configuration. Saves back as the same configuration type as was
|
Save the configuration. Saves back as the same configuration type as was
|
||||||
read from.
|
read from.
|
||||||
*/
|
*/
|
||||||
bool saveConfig( ConfigType type, const std::string &rootdir,
|
bool saveConfig(ConfigType type, const std::string &rootdir,
|
||||||
const shared_ptr<EncFSConfig> &config );
|
const shared_ptr<EncFSConfig> &config);
|
||||||
|
|
||||||
class EncFS_Context;
|
class EncFS_Context;
|
||||||
|
|
||||||
RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts );
|
RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts);
|
||||||
|
|
||||||
RootPtr createV6Config( EncFS_Context *ctx,
|
RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts);
|
||||||
const shared_ptr<EncFS_Opts> &opts );
|
|
||||||
|
|
||||||
void showFSInfo( const shared_ptr<EncFSConfig> &config );
|
void showFSInfo(const shared_ptr<EncFSConfig> &config);
|
||||||
|
|
||||||
bool readV4Config( const char *configFile,
|
bool readV4Config(const char *configFile, const shared_ptr<EncFSConfig> &config,
|
||||||
const shared_ptr<EncFSConfig> &config,
|
struct ConfigInfo *);
|
||||||
struct ConfigInfo *);
|
bool writeV4Config(const char *configFile,
|
||||||
bool writeV4Config( const char *configFile,
|
const shared_ptr<EncFSConfig> &config);
|
||||||
const shared_ptr<EncFSConfig> &config);
|
|
||||||
|
|
||||||
bool readV5Config( const char *configFile,
|
bool readV5Config(const char *configFile, const shared_ptr<EncFSConfig> &config,
|
||||||
const shared_ptr<EncFSConfig> &config,
|
struct ConfigInfo *);
|
||||||
struct ConfigInfo *);
|
bool writeV5Config(const char *configFile,
|
||||||
bool writeV5Config( const char *configFile,
|
const shared_ptr<EncFSConfig> &config);
|
||||||
const shared_ptr<EncFSConfig> &config);
|
|
||||||
|
|
||||||
bool readV6Config( const char *configFile,
|
bool readV6Config(const char *configFile, const shared_ptr<EncFSConfig> &config,
|
||||||
const shared_ptr<EncFSConfig> &config,
|
struct ConfigInfo *);
|
||||||
struct ConfigInfo *);
|
bool writeV6Config(const char *configFile,
|
||||||
bool writeV6Config( const char *configFile,
|
const shared_ptr<EncFSConfig> &config);
|
||||||
const shared_ptr<EncFSConfig> &config);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -17,7 +17,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Interface.h"
|
#include "Interface.h"
|
||||||
|
|
||||||
#include "ConfigVar.h"
|
#include "ConfigVar.h"
|
||||||
@ -28,106 +28,58 @@
|
|||||||
using namespace rel;
|
using namespace rel;
|
||||||
using namespace rlog;
|
using namespace rlog;
|
||||||
|
|
||||||
static RLogChannel * Info = DEF_CHANNEL( "info/iface", Log_Info );
|
static RLogChannel *Info = DEF_CHANNEL("info/iface", Log_Info);
|
||||||
|
|
||||||
Interface::Interface(const char *name_, int Current, int Revision, int Age)
|
Interface::Interface(const char *name_, int Current, int Revision, int Age)
|
||||||
: _name( name_ )
|
: _name(name_), _current(Current), _revision(Revision), _age(Age) {}
|
||||||
, _current( Current )
|
|
||||||
, _revision( Revision )
|
|
||||||
, _age( Age )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Interface::Interface(const std::string &name_, int Current,
|
Interface::Interface(const std::string &name_, int Current, int Revision,
|
||||||
int Revision, int Age)
|
int Age)
|
||||||
: _name( name_ )
|
: _name(name_), _current(Current), _revision(Revision), _age(Age) {}
|
||||||
, _current( Current )
|
|
||||||
, _revision( Revision )
|
|
||||||
, _age( Age )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Interface::Interface(const Interface &src)
|
Interface::Interface(const Interface &src)
|
||||||
: _name( src._name )
|
: _name(src._name),
|
||||||
, _current( src._current )
|
_current(src._current),
|
||||||
, _revision( src._revision )
|
_revision(src._revision),
|
||||||
, _age( src._age )
|
_age(src._age) {}
|
||||||
{
|
|
||||||
|
Interface::Interface() : _current(0), _revision(0), _age(0) {}
|
||||||
|
|
||||||
|
Interface &Interface::operator=(const Interface &src) {
|
||||||
|
_name = src._name;
|
||||||
|
_current = src._current;
|
||||||
|
_revision = src._revision;
|
||||||
|
_age = src._age;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface::Interface()
|
const std::string &Interface::name() const { return _name; }
|
||||||
: _current( 0 )
|
|
||||||
, _revision( 0 )
|
std::string &Interface::name() { return _name; }
|
||||||
, _age( 0 )
|
|
||||||
{
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface &Interface::operator = (const Interface &src)
|
bool operator!=(const Interface &A, const Interface &B) {
|
||||||
{
|
return (A.name() != B.name() || A.current() != B.current() ||
|
||||||
_name = src._name;
|
A.revision() != B.revision() || A.age() != B.age());
|
||||||
_current = src._current;
|
|
||||||
_revision = src._revision;
|
|
||||||
_age = src._age;
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string & Interface::name() const
|
// zero branch method of getting comparison sign..
|
||||||
{
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string & Interface::name()
|
|
||||||
{
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Interface::current() const
|
|
||||||
{
|
|
||||||
return _current;
|
|
||||||
}
|
|
||||||
|
|
||||||
int &Interface::current()
|
|
||||||
{
|
|
||||||
return _current;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Interface::revision() const
|
|
||||||
{
|
|
||||||
return _revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
int &Interface::revision()
|
|
||||||
{
|
|
||||||
return _revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Interface::age() const
|
|
||||||
{
|
|
||||||
return _age;
|
|
||||||
}
|
|
||||||
|
|
||||||
int &Interface::age()
|
|
||||||
{
|
|
||||||
return _age;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator == (const Interface &A, const Interface &B)
|
|
||||||
{
|
|
||||||
return ( A.name() == B.name()
|
|
||||||
&& A.current() == B.current()
|
|
||||||
&& A.revision() == B.revision()
|
|
||||||
&& A.age() == B.age() );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator != (const Interface &A, const Interface &B)
|
|
||||||
{
|
|
||||||
return ( A.name() != B.name()
|
|
||||||
|| A.current() != B.current()
|
|
||||||
|| A.revision() != B.revision()
|
|
||||||
|| A.age() != B.age() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// zero branch method of getting comparison sign..
|
|
||||||
// tricky.. makes assumptions
|
// tricky.. makes assumptions
|
||||||
#if 0
|
#if 0
|
||||||
static int sign( int a, int b )
|
static int sign( int a, int b )
|
||||||
@ -139,91 +91,74 @@ static int sign( int a, int b )
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// simple, easy to check, unlikely to break due to unforseen events..
|
// 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)
|
||||||
if(a < b)
|
return 0;
|
||||||
return 0;
|
else if (a == b)
|
||||||
else if(a == b)
|
return 1;
|
||||||
return 1;
|
else
|
||||||
else
|
return 2;
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
#endif
|
#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 cS = sign( A.current() , B.current() );
|
int aS = sign(A.age(), B.age());
|
||||||
int aS = sign( A.age(), B.age() );
|
int rS = sign(A.revision(), B.revision());
|
||||||
int rS = sign( A.revision(), B.revision() );
|
|
||||||
|
|
||||||
return (cS * 3 + aS) * 3 + rS;
|
return (cS * 3 + aS) * 3 + rS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int EqualVersion = (1 * 3 + 1) * 3 + 1;
|
const int EqualVersion = (1 * 3 + 1) * 3 + 1;
|
||||||
|
|
||||||
bool Interface::implements(const Interface &B) const
|
bool Interface::implements(const Interface &B) const {
|
||||||
{
|
rLog(Info, "checking if %s(%i:%i:%i) implements %s(%i:%i:%i)", name().c_str(),
|
||||||
rLog(Info, "checking if %s(%i:%i:%i) implements %s(%i:%i:%i)",
|
current(), revision(), age(), B.name().c_str(), B.current(),
|
||||||
name().c_str(), current(), revision(), age(),
|
B.revision(), B.age());
|
||||||
B.name().c_str(), B.current(), B.revision(), B.age());
|
|
||||||
|
|
||||||
if( name() != B.name() )
|
if (name() != B.name()) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
int currentDiff = current() - B.current();
|
int currentDiff = current() - B.current();
|
||||||
return ( currentDiff >= 0 && currentDiff <= age() );
|
return (currentDiff >= 0 && currentDiff <= age());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator<(const Interface &A, const Interface &B) {
|
||||||
bool operator < (const Interface &A, const Interface &B)
|
if (A.name() == B.name()) {
|
||||||
{
|
return (diffSum(A, B) < EqualVersion);
|
||||||
if( A.name() == B.name() )
|
} else
|
||||||
{
|
return A.name() < B.name();
|
||||||
return ( diffSum(A,B) < EqualVersion );
|
|
||||||
} else
|
|
||||||
return A.name() < B.name();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator > (const Interface &A, const Interface &B)
|
bool operator>(const Interface &A, const Interface &B) {
|
||||||
{
|
if (A.name() == B.name()) {
|
||||||
if( A.name() == B.name() )
|
return (diffSum(A, B) > EqualVersion);
|
||||||
{
|
} else
|
||||||
return ( diffSum(A,B) > EqualVersion );
|
return A.name() < B.name();
|
||||||
} else
|
|
||||||
return A.name() < B.name();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator <= (const Interface &A, const Interface &B)
|
bool operator<=(const Interface &A, const Interface &B) {
|
||||||
{
|
if (A.name() == B.name()) {
|
||||||
if( A.name() == B.name() )
|
return (diffSum(A, B) <= EqualVersion);
|
||||||
{
|
} else
|
||||||
return ( diffSum(A,B) <= EqualVersion );
|
return A.name() < B.name();
|
||||||
} else
|
|
||||||
return A.name() < B.name();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator >= (const Interface &A, const Interface &B)
|
bool operator>=(const Interface &A, const Interface &B) {
|
||||||
{
|
if (A.name() == B.name()) {
|
||||||
if( A.name() == B.name() )
|
return (diffSum(A, B) >= EqualVersion);
|
||||||
{
|
} else
|
||||||
return ( diffSum(A,B) >= EqualVersion );
|
return A.name() < B.name();
|
||||||
} 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;
|
||||||
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.name();
|
src >> iface.current();
|
||||||
src >> iface.current();
|
src >> iface.revision();
|
||||||
src >> iface.revision();
|
src >> iface.age();
|
||||||
src >> iface.age();
|
return src;
|
||||||
return src;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -26,62 +26,57 @@
|
|||||||
class ConfigVar;
|
class ConfigVar;
|
||||||
|
|
||||||
// part of REL library..
|
// part of REL library..
|
||||||
namespace rel
|
namespace rel {
|
||||||
{
|
|
||||||
|
|
||||||
class Interface
|
class Interface {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
|
Version numbers as described by libtool: info://libtool/versioning
|
||||||
|
Current - the most recent interface api that is implemented.
|
||||||
|
Revision - the implementation number of the current interface.
|
||||||
|
Age - the difference between the newest and oldest interfaces that
|
||||||
|
are implemented.
|
||||||
|
*/
|
||||||
|
Interface(const char *name, int Current, int Revision, int Age);
|
||||||
|
Interface(const std::string &name, int Current, int Revision, int Age);
|
||||||
|
Interface(const Interface &src);
|
||||||
|
Interface();
|
||||||
|
|
||||||
/*!
|
// check if we implement the interface described by B.
|
||||||
Version numbers as described by libtool: info://libtool/versioning
|
// Note that A.implements(B) is not the same as B.implements(A)
|
||||||
Current - the most recent interface api that is implemented.
|
// This checks the current() version and age() against B.current() for
|
||||||
Revision - the implementation number of the current interface.
|
// compatibility. Even if A.implements(B) is true, B > A may also be
|
||||||
Age - the difference between the newest and oldest interfaces that
|
// true, meaning B is a newer revision of the interface then A.
|
||||||
are implemented.
|
bool implements(const Interface &dst) const;
|
||||||
*/
|
|
||||||
Interface( const char *name, int Current, int Revision, int Age );
|
|
||||||
Interface( const std::string &name, int Current, int Revision, int Age);
|
|
||||||
Interface(const Interface &src);
|
|
||||||
Interface();
|
|
||||||
|
|
||||||
// check if we implement the interface described by B.
|
const std::string &name() const;
|
||||||
// Note that A.implements(B) is not the same as B.implements(A)
|
int current() const;
|
||||||
// This checks the current() version and age() against B.current() for
|
int revision() const;
|
||||||
// compatibility. Even if A.implements(B) is true, B > A may also be
|
int age() const;
|
||||||
// true, meaning B is a newer revision of the interface then A.
|
|
||||||
bool implements( const Interface &dst ) const;
|
|
||||||
|
|
||||||
const std::string &name() const;
|
std::string &name();
|
||||||
int current() const;
|
int ¤t();
|
||||||
int revision() const;
|
int &revision();
|
||||||
int age() const;
|
int &age();
|
||||||
|
|
||||||
std::string &name();
|
|
||||||
int ¤t();
|
|
||||||
int &revision();
|
|
||||||
int &age();
|
|
||||||
|
|
||||||
Interface &operator = ( const Interface &src );
|
Interface &operator=(const Interface &src);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _name;
|
std::string _name;
|
||||||
int _current;
|
int _current;
|
||||||
int _revision;
|
int _revision;
|
||||||
int _age;
|
int _age;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVar & operator << (ConfigVar &, const rel::Interface &);
|
ConfigVar &operator<<(ConfigVar &, const rel::Interface &);
|
||||||
const ConfigVar & operator >> (const ConfigVar &, rel::Interface &);
|
const ConfigVar &operator>>(const ConfigVar &, rel::Interface &);
|
||||||
|
|
||||||
bool operator < (const rel::Interface &A, const rel::Interface &B);
|
bool operator<(const rel::Interface &A, const rel::Interface &B);
|
||||||
bool operator > (const rel::Interface &A, const rel::Interface &B);
|
bool operator>(const rel::Interface &A, const rel::Interface &B);
|
||||||
bool operator <= (const rel::Interface &A, const rel::Interface &B);
|
bool operator<=(const rel::Interface &A, const rel::Interface &B);
|
||||||
bool operator >= (const rel::Interface &A, const rel::Interface &B);
|
bool operator>=(const rel::Interface &A, const rel::Interface &B);
|
||||||
bool operator == (const rel::Interface &A, const rel::Interface &B);
|
bool operator==(const rel::Interface &A, const rel::Interface &B);
|
||||||
bool operator != (const rel::Interface &A, const rel::Interface &B);
|
bool operator!=(const rel::Interface &A, const rel::Interface &B);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -51,66 +51,45 @@ static RLogChannel *Info = DEF_CHANNEL("info/MACFileIO", Log_Info);
|
|||||||
//
|
//
|
||||||
static rel::Interface MACFileIO_iface("FileIO/MAC", 2, 1, 0);
|
static rel::Interface MACFileIO_iface("FileIO/MAC", 2, 1, 0);
|
||||||
|
|
||||||
int dataBlockSize(const FSConfigPtr &cfg)
|
int dataBlockSize(const FSConfigPtr &cfg) {
|
||||||
{
|
return cfg->config->blockSize - cfg->config->blockMACBytes -
|
||||||
return cfg->config->blockSize
|
cfg->config->blockMACRandBytes;
|
||||||
- cfg->config->blockMACBytes
|
|
||||||
- cfg->config->blockMACRandBytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MACFileIO::MACFileIO( const shared_ptr<FileIO> &_base,
|
MACFileIO::MACFileIO(const shared_ptr<FileIO> &_base, const FSConfigPtr &cfg)
|
||||||
const FSConfigPtr &cfg )
|
: BlockFileIO(dataBlockSize(cfg), cfg),
|
||||||
: BlockFileIO( dataBlockSize( cfg ), cfg )
|
base(_base),
|
||||||
, base( _base )
|
cipher(cfg->cipher),
|
||||||
, cipher( cfg->cipher )
|
key(cfg->key),
|
||||||
, key( cfg->key )
|
macBytes(cfg->config->blockMACBytes),
|
||||||
, macBytes( cfg->config->blockMACBytes )
|
randBytes(cfg->config->blockMACRandBytes),
|
||||||
, randBytes( cfg->config->blockMACRandBytes )
|
warnOnly(cfg->opts->forceDecode) {
|
||||||
, warnOnly( cfg->opts->forceDecode )
|
rAssert(macBytes >= 0 && macBytes <= 8);
|
||||||
{
|
rAssert(randBytes >= 0);
|
||||||
rAssert( macBytes >= 0 && macBytes <= 8 );
|
rLog(Info, "fs block size = %i, macBytes = %i, randBytes = %i",
|
||||||
rAssert( randBytes >= 0 );
|
cfg->config->blockSize, cfg->config->blockMACBytes,
|
||||||
rLog(Info, "fs block size = %i, macBytes = %i, randBytes = %i",
|
cfg->config->blockMACRandBytes);
|
||||||
cfg->config->blockSize,
|
|
||||||
cfg->config->blockMACBytes,
|
|
||||||
cfg->config->blockMACRandBytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MACFileIO::~MACFileIO()
|
MACFileIO::~MACFileIO() {}
|
||||||
{
|
|
||||||
|
rel::Interface MACFileIO::interface() const { return MACFileIO_iface; }
|
||||||
|
|
||||||
|
int MACFileIO::open(int flags) { return base->open(flags); }
|
||||||
|
|
||||||
|
void MACFileIO::setFileName(const char *fileName) {
|
||||||
|
base->setFileName(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
rel::Interface MACFileIO::interface() const
|
const char *MACFileIO::getFileName() const { return base->getFileName(); }
|
||||||
{
|
|
||||||
return MACFileIO_iface;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MACFileIO::open( int flags )
|
bool MACFileIO::setIV(uint64_t iv) { return base->setIV(iv); }
|
||||||
{
|
|
||||||
return base->open( flags );
|
|
||||||
}
|
|
||||||
|
|
||||||
void MACFileIO::setFileName( const char *fileName )
|
inline static off_t roundUpDivide(off_t numerator, int denominator) {
|
||||||
{
|
// integer arithmetic always rounds down, so we can round up by adding
|
||||||
base->setFileName( fileName );
|
// enough so that any value other then a multiple of denominator gets
|
||||||
}
|
// rouned to the next highest value.
|
||||||
|
return (numerator + denominator - 1) / denominator;
|
||||||
const char *MACFileIO::getFileName() const
|
|
||||||
{
|
|
||||||
return base->getFileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MACFileIO::setIV( uint64_t iv )
|
|
||||||
{
|
|
||||||
return base->setIV( iv );
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
return ( numerator + denominator - 1 ) / denominator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert from a location in the raw file to a location when MAC headers are
|
// Convert from a location in the raw file to a location when MAC headers are
|
||||||
@ -123,10 +102,9 @@ inline static off_t roundUpDivide( off_t numerator, int denominator )
|
|||||||
// ... blockNum = 1
|
// ... blockNum = 1
|
||||||
// ... partialBlock = 0
|
// ... partialBlock = 0
|
||||||
// ... adjLoc = 1 * blockSize
|
// ... 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);
|
||||||
off_t blockNum = roundUpDivide( offset , blockSize - headerSize );
|
return offset + blockNum * headerSize;
|
||||||
return offset + blockNum * headerSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert from a given location in the stream containing headers, and return a
|
// convert from a given location in the stream containing headers, and return a
|
||||||
@ -134,175 +112,149 @@ static off_t locWithHeader( off_t offset, int blockSize, int headerSize )
|
|||||||
// The output value will always be less then the input value, because the
|
// 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
|
// headers are stored at the beginning of the block, so even the first data is
|
||||||
// offset by the size of the header.
|
// 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);
|
||||||
off_t blockNum = roundUpDivide( offset , blockSize );
|
return offset - blockNum * headerSize;
|
||||||
return offset - blockNum * headerSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MACFileIO::getAttr( struct stat *stbuf ) const
|
int MACFileIO::getAttr(struct stat *stbuf) const {
|
||||||
{
|
int res = base->getAttr(stbuf);
|
||||||
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..
|
||||||
// have to adjust size field..
|
|
||||||
int headerSize = macBytes + randBytes;
|
|
||||||
int bs = blockSize() + headerSize;
|
|
||||||
stbuf->st_size = locWithoutHeader( stbuf->st_size, bs, headerSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
off_t MACFileIO::getSize() const
|
|
||||||
{
|
|
||||||
// adjust the size to hide the header overhead we tack on..
|
|
||||||
int headerSize = macBytes + randBytes;
|
int headerSize = macBytes + randBytes;
|
||||||
int bs = blockSize() + headerSize;
|
int bs = blockSize() + headerSize;
|
||||||
|
stbuf->st_size = locWithoutHeader(stbuf->st_size, bs, headerSize);
|
||||||
|
}
|
||||||
|
|
||||||
off_t size = base->getSize();
|
return res;
|
||||||
if(size > 0)
|
|
||||||
size = locWithoutHeader( size, bs, headerSize );
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t MACFileIO::readOneBlock( const IORequest &req ) const
|
off_t MACFileIO::getSize() const {
|
||||||
{
|
// adjust the size to hide the header overhead we tack on..
|
||||||
int headerSize = macBytes + randBytes;
|
int headerSize = macBytes + randBytes;
|
||||||
|
int bs = blockSize() + headerSize;
|
||||||
|
|
||||||
int bs = blockSize() + headerSize;
|
off_t size = base->getSize();
|
||||||
|
if (size > 0) size = locWithoutHeader(size, bs, headerSize);
|
||||||
|
|
||||||
MemBlock mb = MemoryPool::allocate( bs );
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
IORequest tmp;
|
ssize_t MACFileIO::readOneBlock(const IORequest &req) const {
|
||||||
tmp.offset = locWithHeader( req.offset, bs, headerSize );
|
int headerSize = macBytes + randBytes;
|
||||||
tmp.data = mb.data;
|
|
||||||
tmp.dataLen = headerSize + req.dataLen;
|
|
||||||
|
|
||||||
// get the data from the base FileIO layer
|
int bs = blockSize() + headerSize;
|
||||||
ssize_t readSize = base->read( tmp );
|
|
||||||
|
|
||||||
// don't store zeros if configured for zero-block pass-through
|
MemBlock mb = MemoryPool::allocate(bs);
|
||||||
bool skipBlock = true;
|
|
||||||
if( _allowHoles )
|
|
||||||
{
|
|
||||||
for(int i=0; i<readSize; ++i)
|
|
||||||
if(tmp.data[i] != 0)
|
|
||||||
{
|
|
||||||
skipBlock = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if(macBytes > 0)
|
|
||||||
skipBlock = false;
|
|
||||||
|
|
||||||
if(readSize > headerSize)
|
IORequest tmp;
|
||||||
{
|
tmp.offset = locWithHeader(req.offset, bs, headerSize);
|
||||||
if(!skipBlock)
|
tmp.data = mb.data;
|
||||||
{
|
tmp.dataLen = headerSize + req.dataLen;
|
||||||
// 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 );
|
|
||||||
|
|
||||||
// Constant time comparision to prevent timing attacks
|
// get the data from the base FileIO layer
|
||||||
unsigned char fail = 0;
|
ssize_t readSize = base->read(tmp);
|
||||||
for(int i=0; i<macBytes; ++i, mac >>= 8)
|
|
||||||
{
|
|
||||||
int test = mac & 0xff;
|
|
||||||
int stored = tmp.data[i];
|
|
||||||
|
|
||||||
fail |= (test ^ stored);
|
// don't store zeros if configured for zero-block pass-through
|
||||||
}
|
bool skipBlock = true;
|
||||||
|
if (_allowHoles) {
|
||||||
|
for (int i = 0; i < readSize; ++i)
|
||||||
|
if (tmp.data[i] != 0) {
|
||||||
|
skipBlock = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (macBytes > 0)
|
||||||
|
skipBlock = false;
|
||||||
|
|
||||||
if( fail > 0 )
|
if (readSize > headerSize) {
|
||||||
{
|
if (!skipBlock) {
|
||||||
// uh oh..
|
// At this point the data has been decoded. So, compute the MAC of
|
||||||
long blockNum = req.offset / bs;
|
// the block and check against the checksum stored in the header..
|
||||||
rWarning(_("MAC comparison failure in block %li"),
|
uint64_t mac =
|
||||||
blockNum);
|
cipher->MAC_64(tmp.data + macBytes, readSize - macBytes, key);
|
||||||
if( !warnOnly )
|
|
||||||
{
|
// Constant time comparision to prevent timing attacks
|
||||||
MemoryPool::release( mb );
|
unsigned char fail = 0;
|
||||||
throw ERROR(
|
for (int i = 0; i < macBytes; ++i, mac >>= 8) {
|
||||||
_("MAC comparison failure, refusing to read"));
|
int test = mac & 0xff;
|
||||||
}
|
int stored = tmp.data[i];
|
||||||
}
|
|
||||||
|
fail |= (test ^ stored);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail > 0) {
|
||||||
|
// uh oh..
|
||||||
|
long blockNum = req.offset / bs;
|
||||||
|
rWarning(_("MAC comparison failure in block %li"), blockNum);
|
||||||
|
if (!warnOnly) {
|
||||||
|
MemoryPool::release(mb);
|
||||||
|
throw ERROR(_("MAC comparison failure, refusing to read"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// now copy the data to the output buffer
|
|
||||||
readSize -= headerSize;
|
|
||||||
memcpy( req.data, tmp.data + headerSize, readSize );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
rDebug("readSize %i at offset %" PRIi64, (int)readSize, req.offset);
|
|
||||||
if(readSize > 0)
|
|
||||||
readSize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryPool::release( mb );
|
// now copy the data to the output buffer
|
||||||
|
readSize -= headerSize;
|
||||||
|
memcpy(req.data, tmp.data + headerSize, readSize);
|
||||||
|
} else {
|
||||||
|
rDebug("readSize %i at offset %" PRIi64, (int)readSize, req.offset);
|
||||||
|
if (readSize > 0) readSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return readSize;
|
MemoryPool::release(mb);
|
||||||
|
|
||||||
|
return readSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MACFileIO::writeOneBlock( const IORequest &req )
|
bool MACFileIO::writeOneBlock(const IORequest &req) {
|
||||||
{
|
int headerSize = macBytes + randBytes;
|
||||||
int headerSize = macBytes + randBytes;
|
|
||||||
|
|
||||||
int bs = blockSize() + headerSize;
|
int bs = blockSize() + headerSize;
|
||||||
|
|
||||||
// we have the unencrypted data, so we need to attach a header to it.
|
// we have the unencrypted data, so we need to attach a header to it.
|
||||||
MemBlock mb = MemoryPool::allocate( bs );
|
MemBlock mb = MemoryPool::allocate(bs);
|
||||||
|
|
||||||
IORequest newReq;
|
IORequest newReq;
|
||||||
newReq.offset = locWithHeader( req.offset, bs, headerSize );
|
newReq.offset = locWithHeader(req.offset, bs, headerSize);
|
||||||
newReq.data = mb.data;
|
newReq.data = mb.data;
|
||||||
newReq.dataLen = headerSize + req.dataLen;
|
newReq.dataLen = headerSize + req.dataLen;
|
||||||
|
|
||||||
memset( newReq.data, 0, headerSize );
|
memset(newReq.data, 0, headerSize);
|
||||||
memcpy( newReq.data + headerSize, req.data, req.dataLen );
|
memcpy(newReq.data + headerSize, req.data, req.dataLen);
|
||||||
if(randBytes > 0)
|
if (randBytes > 0) {
|
||||||
{
|
if (!cipher->randomize(newReq.data + macBytes, randBytes, false))
|
||||||
if(!cipher->randomize( newReq.data+macBytes, randBytes, false ))
|
return false;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
for (int i = 0; i < macBytes; ++i) {
|
||||||
|
newReq.data[i] = mac & 0xff;
|
||||||
|
mac >>= 8;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(macBytes > 0)
|
// now, we can let the next level have it..
|
||||||
{
|
bool ok = base->write(newReq);
|
||||||
// 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 );
|
|
||||||
|
|
||||||
for(int i=0; i<macBytes; ++i)
|
MemoryPool::release(mb);
|
||||||
{
|
|
||||||
newReq.data[i] = mac & 0xff;
|
|
||||||
mac >>= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now, we can let the next level have it..
|
return ok;
|
||||||
bool ok = base->write( newReq );
|
|
||||||
|
|
||||||
MemoryPool::release( mb );
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MACFileIO::truncate( off_t size )
|
int MACFileIO::truncate(off_t size) {
|
||||||
{
|
int headerSize = macBytes + randBytes;
|
||||||
int headerSize = macBytes + randBytes;
|
int bs = blockSize() + headerSize;
|
||||||
int bs = blockSize() + headerSize;
|
|
||||||
|
|
||||||
int res = BlockFileIO::truncateBase( size, 0 );
|
int res = BlockFileIO::truncateBase(size, 0);
|
||||||
|
|
||||||
if(res == 0)
|
if (res == 0) base->truncate(locWithHeader(size, bs, headerSize));
|
||||||
base->truncate( locWithHeader( size, bs, headerSize ) );
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MACFileIO::isWritable() const
|
bool MACFileIO::isWritable() const { return base->isWritable(); }
|
||||||
{
|
|
||||||
return base->isWritable();
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -24,44 +24,41 @@
|
|||||||
#include "BlockFileIO.h"
|
#include "BlockFileIO.h"
|
||||||
#include "Cipher.h"
|
#include "Cipher.h"
|
||||||
|
|
||||||
class MACFileIO : public BlockFileIO
|
class MACFileIO : public BlockFileIO {
|
||||||
{
|
public:
|
||||||
public:
|
/*
|
||||||
/*
|
If warnOnlyMode is enabled, then a MAC comparison failure will only
|
||||||
If warnOnlyMode is enabled, then a MAC comparison failure will only
|
result in a warning message from encfs -- the garbled data will still
|
||||||
result in a warning message from encfs -- the garbled data will still
|
be made available..
|
||||||
be made available..
|
*/
|
||||||
*/
|
MACFileIO(const shared_ptr<FileIO> &base, const FSConfigPtr &cfg);
|
||||||
MACFileIO( const shared_ptr<FileIO> &base,
|
MACFileIO();
|
||||||
const FSConfigPtr &cfg );
|
virtual ~MACFileIO();
|
||||||
MACFileIO();
|
|
||||||
virtual ~MACFileIO();
|
|
||||||
|
|
||||||
virtual rel::Interface interface() const;
|
virtual rel::Interface interface() const;
|
||||||
|
|
||||||
virtual void setFileName( const char *fileName );
|
virtual void setFileName(const char *fileName);
|
||||||
virtual const char *getFileName() const;
|
virtual const char *getFileName() const;
|
||||||
virtual bool setIV( uint64_t iv );
|
virtual bool setIV(uint64_t iv);
|
||||||
|
|
||||||
virtual int open( int flags );
|
virtual int open(int flags);
|
||||||
virtual int getAttr( struct stat *stbuf ) const;
|
virtual int getAttr(struct stat *stbuf) const;
|
||||||
virtual off_t getSize() const;
|
virtual off_t getSize() const;
|
||||||
|
|
||||||
virtual int truncate( off_t size );
|
virtual int truncate(off_t size);
|
||||||
|
|
||||||
virtual bool isWritable() const;
|
virtual bool isWritable() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ssize_t readOneBlock( const IORequest &req ) const;
|
virtual ssize_t readOneBlock(const IORequest &req) const;
|
||||||
virtual bool writeOneBlock( const IORequest &req );
|
virtual bool writeOneBlock(const IORequest &req);
|
||||||
|
|
||||||
shared_ptr<FileIO> base;
|
shared_ptr<FileIO> base;
|
||||||
shared_ptr<Cipher> cipher;
|
shared_ptr<Cipher> cipher;
|
||||||
CipherKey key;
|
CipherKey key;
|
||||||
int macBytes;
|
int macBytes;
|
||||||
int randBytes;
|
int randBytes;
|
||||||
bool warnOnly;
|
bool warnOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -30,116 +30,101 @@
|
|||||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
#include <valgrind/memcheck.h>
|
#include <valgrind/memcheck.h>
|
||||||
#else
|
#else
|
||||||
#define VALGRIND_MAKE_MEM_NOACCESS( a, b )
|
#define VALGRIND_MAKE_MEM_NOACCESS(a, b)
|
||||||
#define VALGRIND_MAKE_MEM_UNDEFINED( a, b )
|
#define VALGRIND_MAKE_MEM_UNDEFINED(a, b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace rlog;
|
using namespace rlog;
|
||||||
|
|
||||||
# include <openssl/buffer.h>
|
#include <openssl/buffer.h>
|
||||||
#define BLOCKDATA( BLOCK ) (unsigned char*)BLOCK->data->data
|
#define BLOCKDATA(BLOCK) (unsigned char *) BLOCK->data->data
|
||||||
|
|
||||||
|
struct BlockList {
|
||||||
struct BlockList
|
BlockList *next;
|
||||||
{
|
int size;
|
||||||
BlockList *next;
|
BUF_MEM *data;
|
||||||
int size;
|
|
||||||
BUF_MEM *data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static BlockList *allocBlock( int size )
|
static BlockList *allocBlock(int size) {
|
||||||
{
|
BlockList *block = new BlockList;
|
||||||
BlockList *block = new BlockList;
|
block->size = size;
|
||||||
block->size = size;
|
block->data = BUF_MEM_new();
|
||||||
block->data = BUF_MEM_new( );
|
BUF_MEM_grow(block->data, size);
|
||||||
BUF_MEM_grow( block->data, size );
|
VALGRIND_MAKE_MEM_NOACCESS(block->data->data, block->data->max);
|
||||||
VALGRIND_MAKE_MEM_NOACCESS( block->data->data, block->data->max );
|
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeBlock( BlockList *el )
|
static void freeBlock(BlockList *el) {
|
||||||
{
|
VALGRIND_MAKE_MEM_UNDEFINED(el->data->data, el->data->max);
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED( el->data->data, el->data->max );
|
BUF_MEM_free(el->data);
|
||||||
BUF_MEM_free( el->data );
|
|
||||||
|
delete el;
|
||||||
delete el;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static pthread_mutex_t gMPoolMutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t gMPoolMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static BlockList *gMemPool = NULL;
|
static BlockList *gMemPool = NULL;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
parent = block;
|
||||||
|
block = block->next;
|
||||||
|
}
|
||||||
|
|
||||||
MemBlock MemoryPool::allocate( int size )
|
// unlink block from list
|
||||||
{
|
if (block) {
|
||||||
pthread_mutex_lock( &gMPoolMutex );
|
if (!parent)
|
||||||
|
gMemPool = block->next;
|
||||||
|
else
|
||||||
|
parent->next = block->next;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&gMPoolMutex);
|
||||||
|
|
||||||
BlockList *parent = NULL;
|
if (!block) block = allocBlock(size);
|
||||||
BlockList *block = gMemPool;
|
block->next = NULL;
|
||||||
// check if we already have a large enough block available..
|
|
||||||
while(block != NULL && block->size < size)
|
|
||||||
{
|
|
||||||
parent = block;
|
|
||||||
block = block->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unlink block from list
|
MemBlock result;
|
||||||
if(block)
|
result.data = BLOCKDATA(block);
|
||||||
{
|
result.internalData = block;
|
||||||
if(!parent)
|
|
||||||
gMemPool = block->next;
|
|
||||||
else
|
|
||||||
parent->next = block->next;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock( &gMPoolMutex );
|
|
||||||
|
|
||||||
if(!block)
|
VALGRIND_MAKE_MEM_UNDEFINED(result.data, size);
|
||||||
block = allocBlock( size );
|
|
||||||
block->next = NULL;
|
|
||||||
|
|
||||||
MemBlock result;
|
return result;
|
||||||
result.data = BLOCKDATA(block);
|
|
||||||
result.internalData = block;
|
|
||||||
|
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED( result.data, size );
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryPool::release( const MemBlock &mb )
|
void MemoryPool::release(const MemBlock &mb) {
|
||||||
{
|
pthread_mutex_lock(&gMPoolMutex);
|
||||||
pthread_mutex_lock( &gMPoolMutex );
|
|
||||||
|
|
||||||
BlockList *block = (BlockList*)mb.internalData;
|
BlockList *block = (BlockList *)mb.internalData;
|
||||||
|
|
||||||
// just to be sure there's nothing important left in buffers..
|
// just to be sure there's nothing important left in buffers..
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED( block->data->data, block->size );
|
VALGRIND_MAKE_MEM_UNDEFINED(block->data->data, block->size);
|
||||||
memset( BLOCKDATA(block) , 0, block->size);
|
memset(BLOCKDATA(block), 0, block->size);
|
||||||
VALGRIND_MAKE_MEM_NOACCESS( block->data->data, block->data->max );
|
VALGRIND_MAKE_MEM_NOACCESS(block->data->data, block->data->max);
|
||||||
|
|
||||||
block->next = gMemPool;
|
block->next = gMemPool;
|
||||||
gMemPool = block;
|
gMemPool = block;
|
||||||
|
|
||||||
pthread_mutex_unlock( &gMPoolMutex );
|
pthread_mutex_unlock(&gMPoolMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryPool::destroyAll()
|
void MemoryPool::destroyAll() {
|
||||||
{
|
pthread_mutex_lock(&gMPoolMutex);
|
||||||
pthread_mutex_lock( &gMPoolMutex );
|
|
||||||
|
|
||||||
BlockList *block = gMemPool;
|
|
||||||
gMemPool = NULL;
|
|
||||||
|
|
||||||
pthread_mutex_unlock( &gMPoolMutex );
|
|
||||||
|
|
||||||
while(block != NULL)
|
BlockList *block = gMemPool;
|
||||||
{
|
gMemPool = NULL;
|
||||||
BlockList *next = block->next;
|
|
||||||
|
|
||||||
freeBlock( block );
|
pthread_mutex_unlock(&gMPoolMutex);
|
||||||
block = next;
|
|
||||||
}
|
while (block != NULL) {
|
||||||
|
BlockList *next = block->next;
|
||||||
|
|
||||||
|
freeBlock(block);
|
||||||
|
block = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -21,20 +21,15 @@
|
|||||||
#ifndef _MemoryPool_incl_
|
#ifndef _MemoryPool_incl_
|
||||||
#define _MemoryPool_incl_
|
#define _MemoryPool_incl_
|
||||||
|
|
||||||
|
struct MemBlock {
|
||||||
|
unsigned char *data;
|
||||||
|
|
||||||
struct MemBlock
|
void *internalData;
|
||||||
{
|
|
||||||
unsigned char *data;
|
|
||||||
|
|
||||||
void *internalData;
|
MemBlock();
|
||||||
|
|
||||||
MemBlock();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline MemBlock::MemBlock()
|
inline MemBlock::MemBlock() : data(0), internalData(0) {}
|
||||||
: data(0), internalData(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Memory Pool for fixed sized objects.
|
Memory Pool for fixed sized objects.
|
||||||
@ -45,12 +40,10 @@ inline MemBlock::MemBlock()
|
|||||||
unsigned char *buffer = mb.data;
|
unsigned char *buffer = mb.data;
|
||||||
MemoryPool::release( mb );
|
MemoryPool::release( mb );
|
||||||
*/
|
*/
|
||||||
namespace MemoryPool
|
namespace MemoryPool {
|
||||||
{
|
MemBlock allocate(int size);
|
||||||
MemBlock allocate( int size );
|
void release(const MemBlock &el);
|
||||||
void release( const MemBlock &el );
|
void destroyAll();
|
||||||
void destroyAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -23,43 +23,33 @@
|
|||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
namespace rel
|
namespace rel {
|
||||||
{
|
|
||||||
|
|
||||||
class Lock
|
class Lock {
|
||||||
{
|
public:
|
||||||
public:
|
Lock(pthread_mutex_t &mutex);
|
||||||
Lock( pthread_mutex_t &mutex );
|
~Lock();
|
||||||
~Lock();
|
|
||||||
|
|
||||||
// leave the lock as it is. When the Lock wrapper is destroyed, it
|
// leave the lock as it is. When the Lock wrapper is destroyed, it
|
||||||
// will do nothing with the pthread mutex.
|
// will do nothing with the pthread mutex.
|
||||||
void leave();
|
void leave();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Lock(const Lock &src); // not allowed
|
Lock(const Lock &src); // not allowed
|
||||||
Lock &operator = (const Lock &src); // not allowed
|
Lock &operator=(const Lock &src); // not allowed
|
||||||
|
|
||||||
pthread_mutex_t *_mutex;
|
pthread_mutex_t *_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Lock::Lock( pthread_mutex_t &mutex )
|
inline Lock::Lock(pthread_mutex_t &mutex) : _mutex(&mutex) {
|
||||||
: _mutex( &mutex )
|
pthread_mutex_lock(_mutex);
|
||||||
{
|
}
|
||||||
pthread_mutex_lock( _mutex );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Lock::~Lock( )
|
inline Lock::~Lock() {
|
||||||
{
|
if (_mutex) pthread_mutex_unlock(_mutex);
|
||||||
if(_mutex)
|
}
|
||||||
pthread_mutex_unlock( _mutex );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Lock::leave()
|
inline void Lock::leave() { _mutex = 0; }
|
||||||
{
|
|
||||||
_mutex = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
422
encfs/NameIO.cpp
422
encfs/NameIO.cpp
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -39,314 +39,250 @@ using namespace rel;
|
|||||||
using namespace rlog;
|
using namespace rlog;
|
||||||
|
|
||||||
#define REF_MODULE(TYPE) \
|
#define REF_MODULE(TYPE) \
|
||||||
if(!TYPE::Enabled() ) \
|
if (!TYPE::Enabled()) cerr << "referenceModule: should never happen\n";
|
||||||
cerr << "referenceModule: should never happen\n";
|
|
||||||
|
|
||||||
static
|
static void AddSymbolReferences() {
|
||||||
void AddSymbolReferences()
|
REF_MODULE(BlockNameIO)
|
||||||
{
|
REF_MODULE(StreamNameIO)
|
||||||
REF_MODULE(BlockNameIO)
|
REF_MODULE(NullNameIO)
|
||||||
REF_MODULE(StreamNameIO)
|
|
||||||
REF_MODULE(NullNameIO)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NameIOAlg {
|
||||||
struct NameIOAlg
|
bool hidden;
|
||||||
{
|
NameIO::Constructor constructor;
|
||||||
bool hidden;
|
string description;
|
||||||
NameIO::Constructor constructor;
|
Interface iface;
|
||||||
string description;
|
|
||||||
Interface iface;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef multimap< string, NameIOAlg > NameIOMap_t;
|
typedef multimap<string, NameIOAlg> NameIOMap_t;
|
||||||
static NameIOMap_t *gNameIOMap = 0;
|
static NameIOMap_t *gNameIOMap = 0;
|
||||||
|
|
||||||
|
list<NameIO::Algorithm> NameIO::GetAlgorithmList(bool includeHidden) {
|
||||||
|
AddSymbolReferences();
|
||||||
|
|
||||||
list< NameIO::Algorithm >
|
list<Algorithm> result;
|
||||||
NameIO::GetAlgorithmList( bool includeHidden )
|
if (gNameIOMap) {
|
||||||
{
|
NameIOMap_t::const_iterator it;
|
||||||
AddSymbolReferences();
|
NameIOMap_t::const_iterator end = gNameIOMap->end();
|
||||||
|
for (it = gNameIOMap->begin(); it != end; ++it) {
|
||||||
|
if (includeHidden || !it->second.hidden) {
|
||||||
|
Algorithm tmp;
|
||||||
|
tmp.name = it->first;
|
||||||
|
tmp.description = it->second.description;
|
||||||
|
tmp.iface = it->second.iface;
|
||||||
|
|
||||||
list< Algorithm > result;
|
result.push_back(tmp);
|
||||||
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)
|
|
||||||
{
|
|
||||||
Algorithm tmp;
|
|
||||||
tmp.name = it->first;
|
|
||||||
tmp.description = it->second.description;
|
|
||||||
tmp.iface = it->second.iface;
|
|
||||||
|
|
||||||
result.push_back( tmp );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NameIO::Register( const char *name, const char *description,
|
bool NameIO::Register(const char *name, const char *description,
|
||||||
const Interface &iface, Constructor constructor,
|
const Interface &iface, Constructor constructor,
|
||||||
bool hidden )
|
bool hidden) {
|
||||||
{
|
if (!gNameIOMap) gNameIOMap = new NameIOMap_t;
|
||||||
if( !gNameIOMap )
|
|
||||||
gNameIOMap = new NameIOMap_t;
|
|
||||||
|
|
||||||
NameIOAlg alg;
|
NameIOAlg alg;
|
||||||
alg.hidden = hidden;
|
alg.hidden = hidden;
|
||||||
alg.constructor = constructor;
|
alg.constructor = constructor;
|
||||||
alg.description = description;
|
alg.description = description;
|
||||||
alg.iface = iface;
|
alg.iface = iface;
|
||||||
|
|
||||||
gNameIOMap->insert( make_pair( string(name), alg ));
|
gNameIOMap->insert(make_pair(string(name), alg));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<NameIO> NameIO::New( const string &name,
|
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;
|
shared_ptr<NameIO> result;
|
||||||
if(gNameIOMap)
|
if (gNameIOMap) {
|
||||||
{
|
NameIOMap_t::const_iterator it = gNameIOMap->find(name);
|
||||||
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);
|
||||||
Constructor fn = it->second.constructor;
|
|
||||||
result = (*fn)( it->second.iface, cipher, key );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<NameIO> NameIO::New( const Interface &iface,
|
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;
|
shared_ptr<NameIO> result;
|
||||||
if(gNameIOMap)
|
if (gNameIOMap) {
|
||||||
{
|
NameIOMap_t::const_iterator it;
|
||||||
NameIOMap_t::const_iterator it;
|
NameIOMap_t::const_iterator end = gNameIOMap->end();
|
||||||
NameIOMap_t::const_iterator end = gNameIOMap->end();
|
for (it = gNameIOMap->begin(); it != end; ++it) {
|
||||||
for(it = gNameIOMap->begin(); it != end; ++it)
|
if (it->second.iface.implements(iface)) {
|
||||||
{
|
Constructor fn = it->second.constructor;
|
||||||
if( it->second.iface.implements( iface ))
|
result = (*fn)(iface, cipher, key);
|
||||||
{
|
break;
|
||||||
Constructor fn = it->second.constructor;
|
}
|
||||||
result = (*fn)( iface, cipher, key );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NameIO::NameIO() : chainedNameIV(false), reverseEncryption(false) {}
|
||||||
|
|
||||||
|
NameIO::~NameIO() {}
|
||||||
|
|
||||||
NameIO::NameIO()
|
void NameIO::setChainedNameIV(bool enable) { chainedNameIV = enable; }
|
||||||
: chainedNameIV( false ), reverseEncryption( false )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NameIO::~NameIO()
|
bool NameIO::getChainedNameIV() const { return chainedNameIV; }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void NameIO::setChainedNameIV( bool enable )
|
void NameIO::setReverseEncryption(bool enable) { reverseEncryption = enable; }
|
||||||
{
|
|
||||||
chainedNameIV = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NameIO::getChainedNameIV() const
|
bool NameIO::getReverseEncryption() const { return reverseEncryption; }
|
||||||
{
|
|
||||||
return chainedNameIV;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NameIO::setReverseEncryption( bool enable )
|
std::string NameIO::recodePath(const char *path,
|
||||||
{
|
int (NameIO::*_length)(int) const,
|
||||||
reverseEncryption = enable;
|
int (NameIO::*_code)(const char *, int,
|
||||||
}
|
uint64_t *, char *) const,
|
||||||
|
uint64_t *iv) const {
|
||||||
|
string output;
|
||||||
|
|
||||||
bool NameIO::getReverseEncryption() const
|
while (*path) {
|
||||||
{
|
if (*path == '/') {
|
||||||
return reverseEncryption;
|
if (!output.empty()) // don't start the string with '/'
|
||||||
}
|
output += '/';
|
||||||
|
++path;
|
||||||
|
} 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)) {
|
||||||
|
output.append(len, '.'); // append [len] copies of '.'
|
||||||
|
path += len;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
std::string NameIO::recodePath( const char *path,
|
// figure out buffer sizes
|
||||||
int (NameIO::*_length)(int) const,
|
int approxLen = (this->*_length)(len);
|
||||||
int (NameIO::*_code)(const char*, int, uint64_t *, char*) const,
|
if (approxLen <= 0) throw ERROR("Filename too small to decode");
|
||||||
uint64_t *iv ) const
|
|
||||||
{
|
|
||||||
string output;
|
|
||||||
|
|
||||||
while( *path )
|
BUFFER_INIT(codeBuf, 32, (unsigned int)approxLen + 1)
|
||||||
{
|
|
||||||
if( *path == '/' )
|
|
||||||
{
|
|
||||||
if( !output.empty() ) // don't start the string with '/'
|
|
||||||
output += '/';
|
|
||||||
++path;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
bool isDotFile = (*path == '.');
|
|
||||||
const char *next = strchr( path, '/' );
|
|
||||||
int len = next ? next - path : strlen( path );
|
|
||||||
|
|
||||||
// at this point we know that len > 0
|
// code the name
|
||||||
if( isDotFile && (path[len-1] == '.') && (len <= 2) )
|
int codedLen = (this->*_code)(path, len, iv, codeBuf);
|
||||||
{
|
rAssert(codedLen <= approxLen);
|
||||||
output.append(len, '.'); // append [len] copies of '.'
|
rAssert(codeBuf[codedLen] == '\0');
|
||||||
path += len;
|
path += len;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// figure out buffer sizes
|
// append result to string
|
||||||
int approxLen = (this->*_length)( len );
|
output += (char *)codeBuf;
|
||||||
if(approxLen <= 0)
|
|
||||||
throw ERROR("Filename too small to decode");
|
|
||||||
|
|
||||||
BUFFER_INIT( codeBuf, 32, (unsigned int)approxLen+1 )
|
BUFFER_RESET(codeBuf)
|
||||||
|
|
||||||
// code the name
|
|
||||||
int codedLen = (this->*_code)( path, len, iv, codeBuf );
|
|
||||||
rAssert( codedLen <= approxLen );
|
|
||||||
rAssert( codeBuf[codedLen] == '\0' );
|
|
||||||
path += len;
|
|
||||||
|
|
||||||
// append result to string
|
|
||||||
output += (char*)codeBuf;
|
|
||||||
|
|
||||||
BUFFER_RESET( codeBuf )
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NameIO::encodePath( const char *plaintextPath ) const
|
std::string NameIO::encodePath(const char *plaintextPath) const {
|
||||||
{
|
uint64_t iv = 0;
|
||||||
uint64_t iv = 0;
|
return encodePath(plaintextPath, &iv);
|
||||||
return encodePath( plaintextPath, &iv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NameIO::decodePath( const char *cipherPath ) const
|
std::string NameIO::decodePath(const char *cipherPath) const {
|
||||||
{
|
uint64_t iv = 0;
|
||||||
uint64_t iv = 0;
|
return decodePath(cipherPath, &iv);
|
||||||
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 chaining is not enabled, then the iv pointer is not used..
|
if (!chainedNameIV) iv = 0;
|
||||||
if(!chainedNameIV)
|
return recodePath(plaintextPath, &NameIO::maxEncodedNameLen,
|
||||||
iv = 0;
|
&NameIO::encodeName, iv);
|
||||||
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 chaining is not enabled, then the iv pointer is not used..
|
if (!chainedNameIV) iv = 0;
|
||||||
if(!chainedNameIV)
|
return recodePath(cipherPath, &NameIO::maxDecodedNameLen, &NameIO::decodeName,
|
||||||
iv = 0;
|
iv);
|
||||||
return recodePath( cipherPath,
|
|
||||||
&NameIO::maxDecodedNameLen, &NameIO::decodeName, iv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NameIO::encodePath( const char *path, uint64_t *iv ) const
|
std::string NameIO::encodePath(const char *path, uint64_t *iv) const {
|
||||||
{
|
return getReverseEncryption() ? _decodePath(path, iv) : _encodePath(path, iv);
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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
|
std::string NameIO::decodePath(const char *path, uint64_t *iv) const {
|
||||||
{
|
return getReverseEncryption() ? _encodePath(path, iv) : _decodePath(path, iv);
|
||||||
return decodeName( input, length, (uint64_t*)0, output );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NameIO::_encodeName( const char *plaintextName, int length ) const
|
int NameIO::encodeName(const char *input, int length, char *output) const {
|
||||||
{
|
return encodeName(input, length, (uint64_t *)0, output);
|
||||||
int approxLen = maxEncodedNameLen( length );
|
|
||||||
|
|
||||||
BUFFER_INIT( codeBuf, 32, (unsigned int)approxLen+1 )
|
|
||||||
|
|
||||||
// code the name
|
|
||||||
int codedLen = encodeName( plaintextName, length, 0, codeBuf );
|
|
||||||
rAssert( codedLen <= approxLen );
|
|
||||||
rAssert( codeBuf[codedLen] == '\0' );
|
|
||||||
|
|
||||||
// append result to string
|
|
||||||
std::string result = (char*)codeBuf;
|
|
||||||
|
|
||||||
BUFFER_RESET( codeBuf )
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NameIO::_decodeName( const char *encodedName, int length ) const
|
int NameIO::decodeName(const char *input, int length, char *output) const {
|
||||||
{
|
return decodeName(input, length, (uint64_t *)0, output);
|
||||||
int approxLen = maxDecodedNameLen( length );
|
|
||||||
|
|
||||||
BUFFER_INIT( codeBuf, 32, (unsigned int)approxLen+1 )
|
|
||||||
|
|
||||||
// code the name
|
|
||||||
int codedLen = decodeName( encodedName, length, 0, codeBuf );
|
|
||||||
rAssert( codedLen <= approxLen );
|
|
||||||
rAssert( codeBuf[codedLen] == '\0' );
|
|
||||||
|
|
||||||
// append result to string
|
|
||||||
std::string result = (char*)codeBuf;
|
|
||||||
|
|
||||||
BUFFER_RESET( codeBuf )
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NameIO::encodeName( const char *path, int length ) const
|
std::string NameIO::_encodeName(const char *plaintextName, int length) const {
|
||||||
{
|
int approxLen = maxEncodedNameLen(length);
|
||||||
return getReverseEncryption() ?
|
|
||||||
_decodeName( path, length ) :
|
BUFFER_INIT(codeBuf, 32, (unsigned int)approxLen + 1)
|
||||||
_encodeName( path, length );
|
|
||||||
|
// code the name
|
||||||
|
int codedLen = encodeName(plaintextName, length, 0, codeBuf);
|
||||||
|
rAssert(codedLen <= approxLen);
|
||||||
|
rAssert(codeBuf[codedLen] == '\0');
|
||||||
|
|
||||||
|
// append result to string
|
||||||
|
std::string result = (char *)codeBuf;
|
||||||
|
|
||||||
|
BUFFER_RESET(codeBuf)
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NameIO::decodeName( const char *path, int length ) const
|
std::string NameIO::_decodeName(const char *encodedName, int length) const {
|
||||||
{
|
int approxLen = maxDecodedNameLen(length);
|
||||||
return getReverseEncryption() ?
|
|
||||||
_encodeName( path, length ) :
|
BUFFER_INIT(codeBuf, 32, (unsigned int)approxLen + 1)
|
||||||
_decodeName( path, length );
|
|
||||||
|
// code the name
|
||||||
|
int codedLen = decodeName(encodedName, length, 0, codeBuf);
|
||||||
|
rAssert(codedLen <= approxLen);
|
||||||
|
rAssert(codeBuf[codedLen] == '\0');
|
||||||
|
|
||||||
|
// append result to string
|
||||||
|
std::string result = (char *)codeBuf;
|
||||||
|
|
||||||
|
BUFFER_RESET(codeBuf)
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
int NameIO::encodeName( const char *path, int length,
|
int NameIO::encodeName( const char *path, int length,
|
||||||
char *output ) const
|
char *output ) const
|
||||||
{
|
{
|
||||||
return getReverseEncryption() ?
|
return getReverseEncryption() ?
|
||||||
_decodeName( path, length, output ) :
|
_decodeName( path, length, output ) :
|
||||||
_encodeName( path, length, output );
|
_encodeName( path, length, output );
|
||||||
}
|
}
|
||||||
|
|
||||||
int NameIO::decodeName( const char *path, int length,
|
int NameIO::decodeName( const char *path, int length,
|
||||||
char *output ) const
|
char *output ) const
|
||||||
{
|
{
|
||||||
return getReverseEncryption() ?
|
return getReverseEncryption() ?
|
||||||
_encodeName( path, length, output ) :
|
_encodeName( path, length, output ) :
|
||||||
_decodeName( path, length, output );
|
_decodeName( path, length, output );
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
147
encfs/NameIO.h
147
encfs/NameIO.h
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -31,85 +31,80 @@
|
|||||||
|
|
||||||
class Cipher;
|
class Cipher;
|
||||||
|
|
||||||
class NameIO
|
class NameIO {
|
||||||
{
|
public:
|
||||||
public:
|
typedef shared_ptr<NameIO>(*Constructor)(const rel::Interface &iface,
|
||||||
typedef shared_ptr<NameIO> (*Constructor)( const rel::Interface &iface,
|
const shared_ptr<Cipher> &cipher,
|
||||||
const shared_ptr<Cipher> &cipher, const CipherKey &key);
|
const CipherKey &key);
|
||||||
|
|
||||||
struct Algorithm
|
struct Algorithm {
|
||||||
{
|
std::string name;
|
||||||
std::string name;
|
std::string description;
|
||||||
std::string description;
|
rel::Interface iface;
|
||||||
rel::Interface iface;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::list<Algorithm> AlgorithmList;
|
typedef std::list<Algorithm> AlgorithmList;
|
||||||
static AlgorithmList GetAlgorithmList( bool includeHidden = false );
|
static AlgorithmList GetAlgorithmList(bool includeHidden = false);
|
||||||
|
|
||||||
static shared_ptr<NameIO> New( const rel::Interface &iface,
|
static shared_ptr<NameIO> New(const rel::Interface &iface,
|
||||||
const shared_ptr<Cipher> &cipher, const CipherKey &key);
|
const shared_ptr<Cipher> &cipher,
|
||||||
static shared_ptr<NameIO> New( const std::string &name,
|
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);
|
||||||
|
|
||||||
static bool Register( const char *name, const char *description,
|
static bool Register(const char *name, const char *description,
|
||||||
const rel::Interface &iface, Constructor constructor,
|
const rel::Interface &iface, Constructor constructor,
|
||||||
bool hidden = false);
|
bool hidden = false);
|
||||||
|
|
||||||
|
NameIO();
|
||||||
|
virtual ~NameIO();
|
||||||
|
|
||||||
NameIO();
|
virtual rel::Interface interface() const = 0;
|
||||||
virtual ~NameIO();
|
|
||||||
|
|
||||||
virtual rel::Interface interface() const =0;
|
void setChainedNameIV(bool enable);
|
||||||
|
bool getChainedNameIV() const;
|
||||||
|
void setReverseEncryption(bool enable);
|
||||||
|
bool getReverseEncryption() const;
|
||||||
|
|
||||||
void setChainedNameIV( bool enable );
|
std::string encodePath(const char *plaintextPath) const;
|
||||||
bool getChainedNameIV() const;
|
std::string decodePath(const char *encodedPath) const;
|
||||||
void setReverseEncryption( bool enable );
|
|
||||||
bool getReverseEncryption() const;
|
|
||||||
|
|
||||||
std::string encodePath( const char *plaintextPath ) const;
|
std::string encodePath(const char *plaintextPath, uint64_t *iv) const;
|
||||||
std::string decodePath( const char *encodedPath ) const;
|
std::string decodePath(const char *encodedPath, uint64_t *iv) const;
|
||||||
|
|
||||||
std::string encodePath( const char *plaintextPath, uint64_t *iv ) const;
|
virtual int maxEncodedNameLen(int plaintextNameLen) const = 0;
|
||||||
std::string decodePath( const char *encodedPath, uint64_t *iv ) const;
|
virtual int maxDecodedNameLen(int encodedNameLen) const = 0;
|
||||||
|
|
||||||
virtual int maxEncodedNameLen( int plaintextNameLen ) const =0;
|
std::string encodeName(const char *plaintextName, int length) const;
|
||||||
virtual int maxDecodedNameLen( int encodedNameLen ) const =0;
|
std::string decodeName(const char *encodedName, int length) const;
|
||||||
|
|
||||||
std::string encodeName( const char *plaintextName, int length ) const;
|
protected:
|
||||||
std::string decodeName( const char *encodedName, int length ) const;
|
virtual int encodeName(const char *plaintextName, int length,
|
||||||
|
char *encodedName) const;
|
||||||
|
virtual int decodeName(const char *encodedName, int length,
|
||||||
|
char *plaintextName) const;
|
||||||
|
|
||||||
protected:
|
virtual int encodeName(const char *plaintextName, int length, uint64_t *iv,
|
||||||
virtual int encodeName( const char *plaintextName, int length,
|
char *encodedName) const = 0;
|
||||||
char *encodedName ) const;
|
virtual int decodeName(const char *encodedName, int length, uint64_t *iv,
|
||||||
virtual int decodeName( const char *encodedName, int length,
|
char *plaintextName) const = 0;
|
||||||
char *plaintextName ) const;
|
|
||||||
|
|
||||||
virtual int encodeName( const char *plaintextName, int length,
|
private:
|
||||||
uint64_t *iv, char *encodedName ) const =0;
|
std::string recodePath(const char *path, int (NameIO::*codingLen)(int) const,
|
||||||
virtual int decodeName( const char *encodedName, int length,
|
int (NameIO::*codingFunc)(const char *, int,
|
||||||
uint64_t *iv, char *plaintextName ) const =0;
|
uint64_t *, char *) const,
|
||||||
|
uint64_t *iv) const;
|
||||||
|
|
||||||
|
std::string _encodePath(const char *plaintextPath, uint64_t *iv) const;
|
||||||
|
std::string _decodePath(const char *encodedPath, uint64_t *iv) const;
|
||||||
|
std::string _encodeName(const char *plaintextName, int length) const;
|
||||||
|
std::string _decodeName(const char *encodedName, int length) const;
|
||||||
|
|
||||||
private:
|
bool chainedNameIV;
|
||||||
|
bool reverseEncryption;
|
||||||
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;
|
|
||||||
|
|
||||||
std::string _encodePath( const char *plaintextPath, uint64_t *iv ) const;
|
|
||||||
std::string _decodePath( const char *encodedPath, uint64_t *iv ) const;
|
|
||||||
std::string _encodeName( const char *plaintextName, int length ) const;
|
|
||||||
std::string _decodeName( const char *encodedName, int length ) const;
|
|
||||||
|
|
||||||
bool chainedNameIV;
|
|
||||||
bool reverseEncryption;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Helper macros for creating temporary buffers with an optimization that
|
Helper macros for creating temporary buffers with an optimization that
|
||||||
below a given size (OptimizedSize) is allocated on the stack, and when a
|
below a given size (OptimizedSize) is allocated on the stack, and when a
|
||||||
@ -117,22 +112,18 @@ private:
|
|||||||
|
|
||||||
BUFFER_RESET should be called for the same name as BUFFER_INIT
|
BUFFER_RESET should be called for the same name as BUFFER_INIT
|
||||||
*/
|
*/
|
||||||
#define BUFFER_INIT( Name, OptimizedSize, Size ) \
|
#define BUFFER_INIT(Name, OptimizedSize, Size) \
|
||||||
char Name ## _Raw [ OptimizedSize ]; \
|
char Name##_Raw[OptimizedSize]; \
|
||||||
char *Name = Name ## _Raw; \
|
char *Name = Name##_Raw; \
|
||||||
if( sizeof(Name ## _Raw) < Size ) \
|
if (sizeof(Name##_Raw) < Size) Name = new char[Size]; \
|
||||||
Name = new char[ Size ];\
|
memset(Name, 0, Size);
|
||||||
memset( Name, 0, Size );
|
|
||||||
|
|
||||||
#define BUFFER_RESET( Name ) \
|
|
||||||
do { \
|
|
||||||
if( Name != Name ## _Raw ) \
|
|
||||||
{ \
|
|
||||||
delete[] Name; \
|
|
||||||
Name = Name ## _Raw; \
|
|
||||||
} \
|
|
||||||
} while(0);
|
|
||||||
|
|
||||||
|
#define BUFFER_RESET(Name) \
|
||||||
|
do { \
|
||||||
|
if (Name != Name##_Raw) { \
|
||||||
|
delete[] Name; \
|
||||||
|
Name = Name##_Raw; \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -18,7 +18,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "NullCipher.h"
|
#include "NullCipher.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -32,153 +31,109 @@ using namespace std;
|
|||||||
using namespace rel;
|
using namespace rel;
|
||||||
using namespace rlog;
|
using namespace rlog;
|
||||||
|
|
||||||
static Interface NullInterface( "nullCipher", 1, 0, 0 );
|
static Interface NullInterface("nullCipher", 1, 0, 0);
|
||||||
static Range NullKeyRange(0);
|
static Range NullKeyRange(0);
|
||||||
static Range NullBlockRange(1,4096,1);
|
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;
|
||||||
(void)keyLen;
|
return shared_ptr<Cipher>(new NullCipher(iface));
|
||||||
return shared_ptr<Cipher>( new NullCipher( iface ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool HiddenCipher = true;
|
const bool HiddenCipher = true;
|
||||||
|
|
||||||
static bool NullCipher_registered = Cipher::Register("Null",
|
static bool NullCipher_registered = Cipher::Register(
|
||||||
"Non encrypting cipher. For testing only!",
|
"Null", "Non encrypting cipher. For testing only!", NullInterface,
|
||||||
NullInterface, NullKeyRange, NullBlockRange, NewNullCipher,
|
NullKeyRange, NullBlockRange, NewNullCipher, HiddenCipher);
|
||||||
HiddenCipher);
|
|
||||||
|
|
||||||
class NullKey : public AbstractCipherKey
|
class NullKey : public AbstractCipherKey {
|
||||||
{
|
public:
|
||||||
public:
|
NullKey() {}
|
||||||
NullKey() {}
|
virtual ~NullKey() {}
|
||||||
virtual ~NullKey() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NullDestructor
|
class NullDestructor {
|
||||||
{
|
public:
|
||||||
public:
|
NullDestructor() {}
|
||||||
NullDestructor() {}
|
NullDestructor(const NullDestructor &) {}
|
||||||
NullDestructor(const NullDestructor &) {}
|
~NullDestructor() {}
|
||||||
~NullDestructor() {}
|
|
||||||
|
|
||||||
NullDestructor &operator = (const NullDestructor &){ return *this; }
|
NullDestructor &operator=(const NullDestructor &) { return *this; }
|
||||||
void operator ()(NullKey *&) {}
|
void operator()(NullKey *&) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
shared_ptr<AbstractCipherKey> gNullKey( new NullKey(), NullDestructor() );
|
shared_ptr<AbstractCipherKey> gNullKey(new NullKey(), NullDestructor());
|
||||||
|
|
||||||
NullCipher::NullCipher(const Interface &iface_)
|
NullCipher::NullCipher(const Interface &iface_) { this->iface = iface_; }
|
||||||
{
|
|
||||||
this->iface = iface_;
|
NullCipher::~NullCipher() {}
|
||||||
|
|
||||||
|
Interface NullCipher::interface() const { return iface; }
|
||||||
|
|
||||||
|
CipherKey NullCipher::newKey(const char *, int, int &, long,
|
||||||
|
const unsigned char *, int) {
|
||||||
|
return gNullKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
NullCipher::~NullCipher()
|
CipherKey NullCipher::newKey(const char *, int) { return gNullKey; }
|
||||||
{
|
|
||||||
|
CipherKey NullCipher::newRandomKey() { return gNullKey; }
|
||||||
|
|
||||||
|
bool NullCipher::randomize(unsigned char *buf, int len, bool) const {
|
||||||
|
memset(buf, 0, len);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface NullCipher::interface() const
|
uint64_t NullCipher::MAC_64(const unsigned char *, int, const CipherKey &,
|
||||||
{
|
uint64_t *) const {
|
||||||
return iface;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherKey NullCipher::newKey(const char *, int,
|
CipherKey NullCipher::readKey(const unsigned char *, const CipherKey &, bool) {
|
||||||
int &, long, const unsigned char *, int )
|
return gNullKey;
|
||||||
{
|
|
||||||
return gNullKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherKey NullCipher::newKey(const char *, int)
|
void NullCipher::writeKey(const CipherKey &, unsigned char *,
|
||||||
{
|
const CipherKey &) {}
|
||||||
return gNullKey;
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherKey NullCipher::newRandomKey()
|
int NullCipher::encodedKeySize() const { return 0; }
|
||||||
{
|
|
||||||
return gNullKey;
|
int NullCipher::keySize() const { return 0; }
|
||||||
|
|
||||||
|
int NullCipher::cipherBlockSize() const { return 1; }
|
||||||
|
|
||||||
|
bool NullCipher::streamEncode(unsigned char *src, int len, uint64_t iv64,
|
||||||
|
const CipherKey &key) const {
|
||||||
|
(void)src;
|
||||||
|
(void)len;
|
||||||
|
(void)iv64;
|
||||||
|
(void)key;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NullCipher::randomize( unsigned char *buf, int len, bool ) const
|
bool NullCipher::streamDecode(unsigned char *src, int len, uint64_t iv64,
|
||||||
{
|
const CipherKey &key) const {
|
||||||
memset( buf, 0, len );
|
(void)src;
|
||||||
return true;
|
(void)len;
|
||||||
|
(void)iv64;
|
||||||
|
(void)key;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t NullCipher::MAC_64(const unsigned char *, int ,
|
bool NullCipher::blockEncode(unsigned char *, int, uint64_t,
|
||||||
const CipherKey &, uint64_t *) const
|
const CipherKey &) const {
|
||||||
{
|
return true;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherKey NullCipher::readKey( const unsigned char *,
|
bool NullCipher::blockDecode(unsigned char *, int, uint64_t,
|
||||||
const CipherKey &, bool)
|
const CipherKey &) const {
|
||||||
{
|
return true;
|
||||||
return gNullKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NullCipher::writeKey(const CipherKey &, unsigned char *,
|
|
||||||
const CipherKey &)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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::keySize() const
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NullCipher::cipherBlockSize() const
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullCipher::streamEncode( unsigned char *src, int len,
|
|
||||||
uint64_t iv64, const CipherKey &key) const
|
|
||||||
{
|
|
||||||
(void)src;
|
|
||||||
(void)len;
|
|
||||||
(void)iv64;
|
|
||||||
(void)key;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullCipher::streamDecode( unsigned char *src, int len,
|
|
||||||
uint64_t iv64, const CipherKey &key) const
|
|
||||||
{
|
|
||||||
(void)src;
|
|
||||||
(void)len;
|
|
||||||
(void)iv64;
|
|
||||||
(void)key;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullCipher::blockEncode( unsigned char *, int , uint64_t,
|
|
||||||
const CipherKey & ) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullCipher::blockDecode( unsigned char *, int, uint64_t,
|
|
||||||
const CipherKey & ) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullCipher::Enabled()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NullCipher::Enabled() { return true; }
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -28,59 +28,53 @@
|
|||||||
Implements Cipher interface for a pass-through mode. May be useful for
|
Implements Cipher interface for a pass-through mode. May be useful for
|
||||||
testing, but that's it.
|
testing, but that's it.
|
||||||
*/
|
*/
|
||||||
class NullCipher : public Cipher
|
class NullCipher : public Cipher {
|
||||||
{
|
rel::Interface iface;
|
||||||
rel::Interface iface;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NullCipher(const rel::Interface &iface);
|
NullCipher(const rel::Interface &iface);
|
||||||
virtual ~NullCipher();
|
virtual ~NullCipher();
|
||||||
|
|
||||||
virtual rel::Interface interface() const;
|
virtual rel::Interface interface() const;
|
||||||
|
|
||||||
// create a new key based on a password
|
// create a new key based on a password
|
||||||
virtual CipherKey newKey(const char *password, int passwdLength,
|
virtual CipherKey newKey(const char *password, int passwdLength,
|
||||||
int &iterationCount, long desiredDuration,
|
int &iterationCount, long desiredDuration,
|
||||||
const unsigned char *salt, int saltLen);
|
const unsigned char *salt, int saltLen);
|
||||||
virtual CipherKey newKey(const char *password, int passwdLength);
|
virtual CipherKey newKey(const char *password, int passwdLength);
|
||||||
// create a new random key
|
// create a new random key
|
||||||
virtual CipherKey newRandomKey();
|
virtual CipherKey newRandomKey();
|
||||||
|
|
||||||
// data must be len keySize()
|
// data must be len keySize()
|
||||||
virtual CipherKey readKey(const unsigned char *data,
|
virtual CipherKey readKey(const unsigned char *data,
|
||||||
const CipherKey &encodingKey,
|
const CipherKey &encodingKey, bool checkKey);
|
||||||
bool checkKey);
|
virtual void writeKey(const CipherKey &key, unsigned char *data,
|
||||||
virtual void writeKey(const CipherKey &key, unsigned char *data,
|
const CipherKey &encodingKey);
|
||||||
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
|
// meta-data about the cypher
|
||||||
virtual int keySize() const;
|
virtual int keySize() const;
|
||||||
virtual int encodedKeySize() const;
|
virtual int encodedKeySize() const;
|
||||||
virtual int cipherBlockSize() const;
|
virtual int cipherBlockSize() const;
|
||||||
|
|
||||||
virtual bool randomize( unsigned char *buf, int len,
|
virtual bool randomize(unsigned char *buf, int len, bool strongRandom) const;
|
||||||
bool strongRandom ) const;
|
|
||||||
|
|
||||||
virtual uint64_t MAC_64(const unsigned char *data, int len,
|
virtual uint64_t MAC_64(const unsigned char *data, int len,
|
||||||
const CipherKey &key, uint64_t *chainedIV) const;
|
const CipherKey &key, uint64_t *chainedIV) const;
|
||||||
|
|
||||||
// functional interfaces
|
// functional interfaces
|
||||||
virtual bool streamEncode(unsigned char *in, int len,
|
virtual bool streamEncode(unsigned char *in, int len, uint64_t iv64,
|
||||||
uint64_t iv64, const CipherKey &key) const;
|
const CipherKey &key) const;
|
||||||
virtual bool streamDecode(unsigned char *in, int len,
|
virtual bool streamDecode(unsigned char *in, int len, uint64_t iv64,
|
||||||
uint64_t iv64, const CipherKey &key) const;
|
const CipherKey &key) const;
|
||||||
|
|
||||||
virtual bool blockEncode(unsigned char *buf, int size,
|
virtual bool blockEncode(unsigned char *buf, int size, uint64_t iv64,
|
||||||
uint64_t iv64, const CipherKey &key) const;
|
const CipherKey &key) const;
|
||||||
virtual bool blockDecode(unsigned char *buf, int size,
|
virtual bool blockDecode(unsigned char *buf, int size, uint64_t iv64,
|
||||||
uint64_t iv64, const CipherKey &key) const;
|
const CipherKey &key) const;
|
||||||
|
|
||||||
// hack to help with static builds
|
// hack to help with static builds
|
||||||
static bool Enabled();
|
static bool Enabled();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -27,66 +27,45 @@
|
|||||||
|
|
||||||
using namespace rel;
|
using namespace rel;
|
||||||
|
|
||||||
static shared_ptr<NameIO> NewNNIO( const Interface &,
|
static shared_ptr<NameIO> NewNNIO(const Interface &, const shared_ptr<Cipher> &,
|
||||||
const shared_ptr<Cipher> &, const CipherKey & )
|
const CipherKey &) {
|
||||||
{
|
return shared_ptr<NameIO>(new NullNameIO());
|
||||||
return shared_ptr<NameIO>( new NullNameIO() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Interface NNIOIface("nameio/null", 1, 0, 0);
|
static Interface NNIOIface("nameio/null", 1, 0, 0);
|
||||||
static bool NullNameIO_registered = NameIO::Register("Null",
|
static bool NullNameIO_registered =
|
||||||
"No encryption of filenames", NNIOIface, NewNNIO);
|
NameIO::Register("Null", "No encryption of filenames", NNIOIface, NewNNIO);
|
||||||
|
|
||||||
NullNameIO::NullNameIO( )
|
NullNameIO::NullNameIO() {}
|
||||||
{
|
|
||||||
|
|
||||||
|
NullNameIO::~NullNameIO() {}
|
||||||
|
|
||||||
|
Interface NullNameIO::interface() const { return NNIOIface; }
|
||||||
|
|
||||||
|
Interface NullNameIO::CurrentInterface() { return NNIOIface; }
|
||||||
|
|
||||||
|
int NullNameIO::maxEncodedNameLen(int plaintextNameLen) const {
|
||||||
|
return plaintextNameLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
NullNameIO::~NullNameIO()
|
int NullNameIO::maxDecodedNameLen(int encodedNameLen) const {
|
||||||
{
|
return encodedNameLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface NullNameIO::interface() const
|
int NullNameIO::encodeName(const char *plaintextName, int length, uint64_t *iv,
|
||||||
{
|
char *encodedName) const {
|
||||||
return NNIOIface;
|
(void)iv;
|
||||||
|
memcpy(encodedName, plaintextName, length);
|
||||||
|
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface NullNameIO::CurrentInterface()
|
int NullNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
|
||||||
{
|
char *plaintextName) const {
|
||||||
return NNIOIface;
|
(void)iv;
|
||||||
}
|
memcpy(plaintextName, encodedName, length);
|
||||||
|
|
||||||
|
return length;
|
||||||
int NullNameIO::maxEncodedNameLen( int plaintextNameLen ) const
|
|
||||||
{
|
|
||||||
return plaintextNameLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NullNameIO::maxDecodedNameLen( int encodedNameLen ) const
|
|
||||||
{
|
|
||||||
return encodedNameLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
(void)iv;
|
|
||||||
memcpy( plaintextName, encodedName, length );
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NullNameIO::Enabled()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NullNameIO::Enabled() { return true; }
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -23,30 +23,29 @@
|
|||||||
|
|
||||||
#include "NameIO.h"
|
#include "NameIO.h"
|
||||||
|
|
||||||
class NullNameIO : public NameIO
|
class NullNameIO : public NameIO {
|
||||||
{
|
public:
|
||||||
public:
|
static rel::Interface CurrentInterface();
|
||||||
static rel::Interface CurrentInterface();
|
|
||||||
|
|
||||||
NullNameIO( );
|
NullNameIO();
|
||||||
|
|
||||||
virtual ~NullNameIO();
|
virtual ~NullNameIO();
|
||||||
|
|
||||||
virtual rel::Interface interface() const;
|
virtual rel::Interface interface() const;
|
||||||
|
|
||||||
virtual int maxEncodedNameLen( int plaintextNameLen ) const;
|
virtual int maxEncodedNameLen(int plaintextNameLen) const;
|
||||||
virtual int maxDecodedNameLen( int encodedNameLen ) const;
|
virtual int maxDecodedNameLen(int encodedNameLen) const;
|
||||||
|
|
||||||
// hack to help with static builds
|
// hack to help with static builds
|
||||||
static bool Enabled();
|
static bool Enabled();
|
||||||
protected:
|
|
||||||
virtual int encodeName( const char *plaintextName, int length,
|
protected:
|
||||||
uint64_t *iv, char *encodedName ) const;
|
virtual int encodeName(const char *plaintextName, int length, uint64_t *iv,
|
||||||
virtual int decodeName( const char *encodedName, int length,
|
char *encodedName) const;
|
||||||
uint64_t *iv, char *plaintextName ) const;
|
virtual int decodeName(const char *encodedName, int length, uint64_t *iv,
|
||||||
private:
|
char *plaintextName) const;
|
||||||
|
|
||||||
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
122
encfs/Range.h
122
encfs/Range.h
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -17,97 +17,73 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _Range_incl_
|
#ifndef _Range_incl_
|
||||||
#define _Range_incl_
|
#define _Range_incl_
|
||||||
|
|
||||||
|
class Range {
|
||||||
|
int minVal;
|
||||||
|
int maxVal;
|
||||||
|
int increment;
|
||||||
|
|
||||||
class Range
|
public:
|
||||||
{
|
Range();
|
||||||
int minVal;
|
Range(int minMax);
|
||||||
int maxVal;
|
Range(int min, int max, int increment);
|
||||||
int increment;
|
|
||||||
public:
|
|
||||||
Range();
|
|
||||||
Range(int minMax);
|
|
||||||
Range(int min, int max, int increment);
|
|
||||||
|
|
||||||
bool allowed(int value) const;
|
bool allowed(int value) const;
|
||||||
|
|
||||||
int closest(int value) const;
|
int closest(int value) const;
|
||||||
|
|
||||||
int min() const;
|
int min() const;
|
||||||
int max() const;
|
int max() const;
|
||||||
int inc() const;
|
int inc() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Range::Range(int minMax)
|
inline Range::Range(int minMax) {
|
||||||
{
|
this->minVal = minMax;
|
||||||
this->minVal = minMax;
|
this->maxVal = minMax;
|
||||||
this->maxVal = minMax;
|
this->increment = 1;
|
||||||
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->minVal = min_;
|
this->maxVal = max_;
|
||||||
this->maxVal = max_;
|
this->increment = increment_;
|
||||||
this->increment = increment_;
|
if (increment == 0) this->increment = 1;
|
||||||
if(increment == 0)
|
|
||||||
this->increment = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Range::Range()
|
inline Range::Range() : minVal(-1), maxVal(-1), increment(1) {}
|
||||||
: minVal(-1)
|
|
||||||
, maxVal(-1)
|
|
||||||
, increment(1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Range::allowed(int value) const
|
inline bool Range::allowed(int value) const {
|
||||||
{
|
if (value >= minVal && value <= maxVal) {
|
||||||
if(value >= minVal && value <= maxVal)
|
|
||||||
{
|
|
||||||
int tmp = value - minVal;
|
|
||||||
if((tmp % increment) == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int Range::closest(int value) const
|
|
||||||
{
|
|
||||||
if(allowed(value))
|
|
||||||
return value;
|
|
||||||
else
|
|
||||||
if(value < minVal)
|
|
||||||
return minVal;
|
|
||||||
else
|
|
||||||
if(value > maxVal)
|
|
||||||
return maxVal;
|
|
||||||
|
|
||||||
// must be inbetween but not matched with increment
|
|
||||||
int tmp = value - minVal;
|
int tmp = value - minVal;
|
||||||
// try rounding to the nearest increment..
|
if ((tmp % increment) == 0) return true;
|
||||||
tmp += (increment >> 1);
|
}
|
||||||
tmp -= (tmp % increment);
|
return false;
|
||||||
|
|
||||||
return closest( value + tmp );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Range::min() const
|
inline int Range::closest(int value) const {
|
||||||
{
|
if (allowed(value))
|
||||||
|
return value;
|
||||||
|
else if (value < minVal)
|
||||||
return minVal;
|
return minVal;
|
||||||
}
|
else if (value > maxVal)
|
||||||
|
|
||||||
inline int Range::max() const
|
|
||||||
{
|
|
||||||
return maxVal;
|
return maxVal;
|
||||||
|
|
||||||
|
// must be inbetween but not matched with increment
|
||||||
|
int tmp = value - minVal;
|
||||||
|
// try rounding to the nearest increment..
|
||||||
|
tmp += (increment >> 1);
|
||||||
|
tmp -= (tmp % increment);
|
||||||
|
|
||||||
|
return closest(value + tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Range::inc() const
|
inline int Range::min() const { return minVal; }
|
||||||
{
|
|
||||||
return increment;
|
inline int Range::max() const { return maxVal; }
|
||||||
}
|
|
||||||
|
inline int Range::inc() const { return increment; }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
#define _XOPEN_SOURCE 500 // pick up pread , pwrite
|
#define _XOPEN_SOURCE 500 // pick up pread , pwrite
|
||||||
#endif
|
#endif
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -38,57 +38,41 @@ using namespace std;
|
|||||||
|
|
||||||
static rel::Interface RawFileIO_iface("FileIO/Raw", 1, 0, 0);
|
static rel::Interface RawFileIO_iface("FileIO/Raw", 1, 0, 0);
|
||||||
|
|
||||||
FileIO *NewRawFileIO( const rel::Interface &iface )
|
FileIO *NewRawFileIO(const rel::Interface &iface) {
|
||||||
{
|
(void)iface;
|
||||||
(void)iface;
|
return new RawFileIO();
|
||||||
return new RawFileIO();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void swap( int &x, int &y )
|
inline void swap(int &x, int &y) {
|
||||||
{
|
int tmp = x;
|
||||||
int tmp = x;
|
x = y;
|
||||||
x = y;
|
y = tmp;
|
||||||
y = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RawFileIO::RawFileIO( )
|
RawFileIO::RawFileIO()
|
||||||
: knownSize( false )
|
: knownSize(false), fileSize(0), fd(-1), oldfd(-1), canWrite(false) {}
|
||||||
, fileSize(0)
|
|
||||||
, fd( -1 )
|
RawFileIO::RawFileIO(const std::string &fileName)
|
||||||
, oldfd( -1 )
|
: name(fileName),
|
||||||
, canWrite( false )
|
knownSize(false),
|
||||||
{
|
fileSize(0),
|
||||||
|
fd(-1),
|
||||||
|
oldfd(-1),
|
||||||
|
canWrite(false) {}
|
||||||
|
|
||||||
|
RawFileIO::~RawFileIO() {
|
||||||
|
int _fd = -1;
|
||||||
|
int _oldfd = -1;
|
||||||
|
|
||||||
|
swap(_fd, fd);
|
||||||
|
swap(_oldfd, oldfd);
|
||||||
|
|
||||||
|
if (_oldfd != -1) close(_oldfd);
|
||||||
|
|
||||||
|
if (_fd != -1) close(_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
RawFileIO::RawFileIO( const std::string &fileName )
|
rel::Interface RawFileIO::interface() const { return RawFileIO_iface; }
|
||||||
: name( fileName )
|
|
||||||
, knownSize( false )
|
|
||||||
, fileSize( 0 )
|
|
||||||
, fd( -1 )
|
|
||||||
, oldfd( -1 )
|
|
||||||
, canWrite( false )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RawFileIO::~RawFileIO()
|
|
||||||
{
|
|
||||||
int _fd = -1;
|
|
||||||
int _oldfd = -1;
|
|
||||||
|
|
||||||
swap( _fd, fd );
|
|
||||||
swap( _oldfd, oldfd );
|
|
||||||
|
|
||||||
if( _oldfd != -1 )
|
|
||||||
close( _oldfd );
|
|
||||||
|
|
||||||
if( _fd != -1 )
|
|
||||||
close( _fd );
|
|
||||||
}
|
|
||||||
|
|
||||||
rel::Interface RawFileIO::interface() const
|
|
||||||
{
|
|
||||||
return RawFileIO_iface;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Workaround for opening a file for write when permissions don't allow.
|
Workaround for opening a file for write when permissions don't allow.
|
||||||
@ -97,23 +81,20 @@ rel::Interface RawFileIO::interface() const
|
|||||||
be called with a lock around it so that there won't be a race condition
|
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.
|
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;
|
||||||
int fd = -1;
|
struct stat stbuf;
|
||||||
struct stat stbuf;
|
memset(&stbuf, 0, sizeof(struct stat));
|
||||||
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);
|
||||||
// make sure user has read/write permission..
|
fd = ::open(path, flags);
|
||||||
chmod( path , stbuf.st_mode | 0600 );
|
chmod(path, stbuf.st_mode);
|
||||||
fd = ::open( path , flags );
|
} else {
|
||||||
chmod( path , stbuf.st_mode );
|
rInfo("can't stat file %s", path);
|
||||||
} else
|
}
|
||||||
{
|
|
||||||
rInfo("can't stat file %s", path );
|
|
||||||
}
|
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -125,201 +106,164 @@ static int open_readonly_workaround(const char *path, int flags)
|
|||||||
- Also keep the O_LARGEFILE flag, in case the underlying filesystem needs
|
- Also keep the O_LARGEFILE flag, in case the underlying filesystem needs
|
||||||
it..
|
it..
|
||||||
*/
|
*/
|
||||||
int RawFileIO::open(int flags)
|
int RawFileIO::open(int flags) {
|
||||||
{
|
bool requestWrite = ((flags & O_RDWR) || (flags & O_WRONLY));
|
||||||
bool requestWrite = ((flags & O_RDWR) || (flags & O_WRONLY));
|
|
||||||
|
|
||||||
rDebug("open call for %s file", requestWrite ? "writable" : "read only");
|
rDebug("open call for %s file", requestWrite ? "writable" : "read only");
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
// if we have a descriptor and it is writable, or we don't need writable..
|
// 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");
|
||||||
rDebug("using existing file descriptor");
|
result = fd; // success
|
||||||
result = fd; // success
|
} else {
|
||||||
} else
|
int finalFlags = requestWrite ? O_RDWR : O_RDONLY;
|
||||||
{
|
|
||||||
int finalFlags = requestWrite ? O_RDWR : O_RDONLY;
|
|
||||||
|
|
||||||
#if defined(O_LARGEFILE)
|
#if defined(O_LARGEFILE)
|
||||||
if( flags & O_LARGEFILE )
|
if (flags & O_LARGEFILE) finalFlags |= O_LARGEFILE;
|
||||||
finalFlags |= O_LARGEFILE;
|
|
||||||
#else
|
#else
|
||||||
#warning O_LARGEFILE not supported
|
#warning O_LARGEFILE not supported
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int newFd = ::open( name.c_str(), finalFlags );
|
int newFd = ::open(name.c_str(), finalFlags);
|
||||||
|
|
||||||
rDebug("open file with flags %i, result = %i", finalFlags, newFd);
|
|
||||||
|
|
||||||
if((newFd == -1) && (errno == EACCES))
|
rDebug("open file with flags %i, result = %i", finalFlags, newFd);
|
||||||
{
|
|
||||||
rDebug("using readonly workaround for open");
|
|
||||||
newFd = open_readonly_workaround( name.c_str(), finalFlags );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(newFd >= 0)
|
if ((newFd == -1) && (errno == EACCES)) {
|
||||||
{
|
rDebug("using readonly workaround for open");
|
||||||
if(oldfd >= 0)
|
newFd = open_readonly_workaround(name.c_str(), finalFlags);
|
||||||
{
|
|
||||||
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
|
|
||||||
// now.
|
|
||||||
canWrite = requestWrite;
|
|
||||||
oldfd = fd;
|
|
||||||
result = fd = newFd;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
result = -errno;
|
|
||||||
rInfo("::open error: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result < 0)
|
if (newFd >= 0) {
|
||||||
rInfo("file %s open failure: %i", name.c_str(), -result);
|
if (oldfd >= 0) {
|
||||||
|
rError("leaking FD?: oldfd = %i, fd = %i, newfd = %i", oldfd, fd,
|
||||||
|
newFd);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
// the old fd might still be in use, so just keep it around for
|
||||||
|
// now.
|
||||||
|
canWrite = requestWrite;
|
||||||
|
oldfd = fd;
|
||||||
|
result = fd = newFd;
|
||||||
|
} else {
|
||||||
|
result = -errno;
|
||||||
|
rInfo("::open error: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 res = lstat( name.c_str(), stbuf );
|
int eno = errno;
|
||||||
int eno = errno;
|
|
||||||
|
|
||||||
if(res < 0)
|
if (res < 0) rInfo("getAttr error on %s: %s", name.c_str(), strerror(eno));
|
||||||
rInfo("getAttr error on %s: %s", name.c_str(), strerror( eno ));
|
|
||||||
|
|
||||||
return ( res < 0 ) ? -eno : 0;
|
return (res < 0) ? -eno : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RawFileIO::setFileName( const char *fileName )
|
void RawFileIO::setFileName(const char *fileName) { name = fileName; }
|
||||||
{
|
|
||||||
name = fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *RawFileIO::getFileName() const
|
const char *RawFileIO::getFileName() const { return name.c_str(); }
|
||||||
{
|
|
||||||
return name.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
off_t RawFileIO::getSize() const
|
off_t RawFileIO::getSize() const {
|
||||||
{
|
if (!knownSize) {
|
||||||
if(!knownSize)
|
struct stat stbuf;
|
||||||
{
|
memset(&stbuf, 0, sizeof(struct stat));
|
||||||
struct stat stbuf;
|
int res = lstat(name.c_str(), &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)->fileSize = stbuf.st_size;
|
const_cast<RawFileIO *>(this)->knownSize = true;
|
||||||
const_cast<RawFileIO*>(this)->knownSize = true;
|
return fileSize;
|
||||||
return fileSize;
|
|
||||||
} else
|
|
||||||
return -1;
|
|
||||||
} else
|
} else
|
||||||
{
|
return -1;
|
||||||
return fileSize;
|
} else {
|
||||||
}
|
return fileSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t RawFileIO::read( const IORequest &req ) const
|
ssize_t RawFileIO::read(const IORequest &req) const {
|
||||||
{
|
rAssert(fd >= 0);
|
||||||
rAssert( fd >= 0 );
|
|
||||||
|
|
||||||
ssize_t readSize = pread( fd, req.data, req.dataLen, req.offset );
|
ssize_t readSize = pread(fd, req.data, req.dataLen, req.offset);
|
||||||
|
|
||||||
if(readSize < 0)
|
if (readSize < 0) {
|
||||||
{
|
rInfo("read failed at offset %" PRIi64 " for %i bytes: %s", req.offset,
|
||||||
rInfo("read failed at offset %" PRIi64 " for %i bytes: %s",
|
req.dataLen, strerror(errno));
|
||||||
req.offset, req.dataLen, strerror( errno ));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return readSize;
|
return readSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RawFileIO::write( const IORequest &req )
|
bool RawFileIO::write(const IORequest &req) {
|
||||||
{
|
rAssert(fd >= 0);
|
||||||
rAssert( fd >= 0 );
|
rAssert(true == canWrite);
|
||||||
rAssert( true == canWrite );
|
|
||||||
|
|
||||||
int retrys = 10;
|
int retrys = 10;
|
||||||
void *buf = req.data;
|
void *buf = req.data;
|
||||||
ssize_t bytes = req.dataLen;
|
ssize_t bytes = req.dataLen;
|
||||||
off_t offset = req.offset;
|
off_t offset = req.offset;
|
||||||
|
|
||||||
while( bytes && retrys > 0 )
|
while (bytes && retrys > 0) {
|
||||||
{
|
ssize_t writeSize = ::pwrite(fd, buf, bytes, offset);
|
||||||
ssize_t writeSize = ::pwrite( fd, buf, bytes, offset );
|
|
||||||
|
|
||||||
if( writeSize < 0 )
|
if (writeSize < 0) {
|
||||||
{
|
knownSize = false;
|
||||||
knownSize = false;
|
rInfo("write failed at offset %" PRIi64 " for %i bytes: %s", offset,
|
||||||
rInfo("write failed at offset %" PRIi64 " for %i bytes: %s",
|
(int)bytes, strerror(errno));
|
||||||
offset, (int)bytes, strerror( errno ));
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes -= writeSize;
|
|
||||||
offset += writeSize;
|
|
||||||
buf = (void*)((char*)buf + writeSize);
|
|
||||||
--retrys;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bytes != 0)
|
bytes -= writeSize;
|
||||||
{
|
offset += writeSize;
|
||||||
rError("Write error: wrote %i bytes of %i, max retries reached\n",
|
buf = (void *)((char *)buf + writeSize);
|
||||||
(int)(req.dataLen - bytes), req.dataLen );
|
--retrys;
|
||||||
knownSize = false;
|
}
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
if(knownSize)
|
|
||||||
{
|
|
||||||
off_t last = req.offset + req.dataLen;
|
|
||||||
if(last > fileSize)
|
|
||||||
fileSize = last;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
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) {
|
||||||
|
off_t last = req.offset + req.dataLen;
|
||||||
|
if (last > fileSize) fileSize = last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int RawFileIO::truncate( off_t size )
|
int RawFileIO::truncate(off_t size) {
|
||||||
{
|
int res;
|
||||||
int res;
|
|
||||||
|
|
||||||
if(fd >= 0 && canWrite)
|
if (fd >= 0 && canWrite) {
|
||||||
{
|
res = ::ftruncate(fd, size);
|
||||||
res = ::ftruncate( fd, size );
|
|
||||||
#if !defined(__FreeBSD__) && !defined(__APPLE__)
|
#if !defined(__FreeBSD__) && !defined(__APPLE__)
|
||||||
::fdatasync( fd );
|
::fdatasync(fd);
|
||||||
#endif
|
#endif
|
||||||
} else
|
} else
|
||||||
res = ::truncate( name.c_str(), size );
|
res = ::truncate(name.c_str(), size);
|
||||||
|
|
||||||
if(res < 0)
|
if (res < 0) {
|
||||||
{
|
int eno = errno;
|
||||||
int eno = errno;
|
rInfo("truncate failed for %s (%i) size %" PRIi64 ", error %s",
|
||||||
rInfo("truncate failed for %s (%i) size %" PRIi64 ", error %s",
|
name.c_str(), fd, size, strerror(eno));
|
||||||
name.c_str(), fd, size, strerror(eno));
|
res = -eno;
|
||||||
res = -eno;
|
knownSize = false;
|
||||||
knownSize = false;
|
} else {
|
||||||
} else
|
res = 0;
|
||||||
{
|
fileSize = size;
|
||||||
res = 0;
|
knownSize = true;
|
||||||
fileSize = size;
|
}
|
||||||
knownSize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RawFileIO::isWritable() const
|
bool RawFileIO::isWritable() const { return canWrite; }
|
||||||
{
|
|
||||||
return canWrite;
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -25,40 +25,38 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class RawFileIO : public FileIO
|
class RawFileIO : public FileIO {
|
||||||
{
|
public:
|
||||||
public:
|
RawFileIO();
|
||||||
RawFileIO();
|
RawFileIO(const std::string &fileName);
|
||||||
RawFileIO( const std::string &fileName );
|
virtual ~RawFileIO();
|
||||||
virtual ~RawFileIO();
|
|
||||||
|
|
||||||
virtual rel::Interface interface() const;
|
virtual rel::Interface interface() const;
|
||||||
|
|
||||||
virtual void setFileName( const char *fileName );
|
virtual void setFileName(const char *fileName);
|
||||||
virtual const char *getFileName() const;
|
virtual const char *getFileName() const;
|
||||||
|
|
||||||
virtual int open( int flags );
|
virtual int open(int flags);
|
||||||
|
|
||||||
virtual int getAttr( struct stat *stbuf ) const;
|
|
||||||
virtual off_t getSize() const;
|
|
||||||
|
|
||||||
virtual ssize_t read( const IORequest & req ) const;
|
virtual int getAttr(struct stat *stbuf) const;
|
||||||
virtual bool write( const IORequest &req );
|
virtual off_t getSize() const;
|
||||||
|
|
||||||
virtual int truncate( off_t size );
|
virtual ssize_t read(const IORequest &req) const;
|
||||||
|
virtual bool write(const IORequest &req);
|
||||||
|
|
||||||
virtual bool isWritable() const;
|
virtual int truncate(off_t size);
|
||||||
protected:
|
|
||||||
|
|
||||||
std::string name;
|
virtual bool isWritable() const;
|
||||||
|
|
||||||
bool knownSize;
|
protected:
|
||||||
off_t fileSize;
|
std::string name;
|
||||||
|
|
||||||
int fd;
|
bool knownSize;
|
||||||
int oldfd;
|
off_t fileSize;
|
||||||
bool canWrite;
|
|
||||||
|
int fd;
|
||||||
|
int oldfd;
|
||||||
|
bool canWrite;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
1299
encfs/SSL_Cipher.cpp
1299
encfs/SSL_Cipher.cpp
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -55,9 +55,9 @@ typedef struct evp_cipher_st EVP_CIPHER;
|
|||||||
as:
|
as:
|
||||||
1. shuffle
|
1. shuffle
|
||||||
2. encrypt
|
2. encrypt
|
||||||
3. reverse
|
3. reverse
|
||||||
4. shuffle
|
4. shuffle
|
||||||
5. encrypt
|
5. encrypt
|
||||||
The reason for the shuffle and reverse steps (and the second encrypt pass)
|
The reason for the shuffle and reverse steps (and the second encrypt pass)
|
||||||
is to try and propogate any changed bits to a larger set. If only a single
|
is to try and propogate any changed bits to a larger set. If only a single
|
||||||
pass was made with the stream cipher in CFB mode, then a change to one byte
|
pass was made with the stream cipher in CFB mode, then a change to one byte
|
||||||
@ -68,83 +68,78 @@ typedef struct evp_cipher_st EVP_CIPHER;
|
|||||||
initial value vector to randomize the output. But it makes the code
|
initial value vector to randomize the output. But it makes the code
|
||||||
simpler to reuse the encryption algorithm as is.
|
simpler to reuse the encryption algorithm as is.
|
||||||
*/
|
*/
|
||||||
class SSL_Cipher : public Cipher
|
class SSL_Cipher : public Cipher {
|
||||||
{
|
rel::Interface iface;
|
||||||
rel::Interface iface;
|
rel::Interface realIface;
|
||||||
rel::Interface realIface;
|
const EVP_CIPHER *_blockCipher;
|
||||||
const EVP_CIPHER *_blockCipher;
|
const EVP_CIPHER *_streamCipher;
|
||||||
const EVP_CIPHER *_streamCipher;
|
unsigned int _keySize; // in bytes
|
||||||
unsigned int _keySize; // in bytes
|
unsigned int _ivLength;
|
||||||
unsigned int _ivLength;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SSL_Cipher(const rel::Interface &iface, const rel::Interface &realIface,
|
SSL_Cipher(const rel::Interface &iface, const rel::Interface &realIface,
|
||||||
const EVP_CIPHER *blockCipher, const EVP_CIPHER *streamCipher,
|
const EVP_CIPHER *blockCipher, const EVP_CIPHER *streamCipher,
|
||||||
int keyLength);
|
int keyLength);
|
||||||
virtual ~SSL_Cipher();
|
virtual ~SSL_Cipher();
|
||||||
|
|
||||||
// returns the real interface, not the one we're emulating (if any)..
|
// returns the real interface, not the one we're emulating (if any)..
|
||||||
virtual rel::Interface interface() const;
|
virtual rel::Interface interface() const;
|
||||||
|
|
||||||
// create a new key based on a password
|
// create a new key based on a password
|
||||||
virtual CipherKey newKey(const char *password, int passwdLength,
|
virtual CipherKey newKey(const char *password, int passwdLength,
|
||||||
int &iterationCount, long desiredDuration,
|
int &iterationCount, long desiredDuration,
|
||||||
const unsigned char *salt, int saltLen);
|
const unsigned char *salt, int saltLen);
|
||||||
// deprecated - for backward compatibility
|
// deprecated - for backward compatibility
|
||||||
virtual CipherKey newKey(const char *password, int passwdLength);
|
virtual CipherKey newKey(const char *password, int passwdLength);
|
||||||
// create a new random key
|
// create a new random key
|
||||||
virtual CipherKey newRandomKey();
|
virtual CipherKey newRandomKey();
|
||||||
|
|
||||||
// data must be len keySize()
|
// data must be len keySize()
|
||||||
virtual CipherKey readKey(const unsigned char *data,
|
virtual CipherKey readKey(const unsigned char *data,
|
||||||
const CipherKey &encodingKey,
|
const CipherKey &encodingKey, bool checkKey);
|
||||||
bool checkKey);
|
virtual void writeKey(const CipherKey &key, unsigned char *data,
|
||||||
virtual void writeKey(const CipherKey &key, unsigned char *data,
|
const CipherKey &encodingKey);
|
||||||
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
|
// meta-data about the cypher
|
||||||
virtual int keySize() const;
|
virtual int keySize() const;
|
||||||
virtual int encodedKeySize() const;
|
virtual int encodedKeySize() const;
|
||||||
virtual int cipherBlockSize() const;
|
virtual int cipherBlockSize() const;
|
||||||
|
|
||||||
virtual bool randomize( unsigned char *buf, int len,
|
virtual bool randomize(unsigned char *buf, int len, bool strongRandom) const;
|
||||||
bool strongRandom ) const;
|
|
||||||
|
|
||||||
virtual uint64_t MAC_64( const unsigned char *src, int len,
|
virtual uint64_t MAC_64(const unsigned char *src, int len,
|
||||||
const CipherKey &key, uint64_t *augment ) const;
|
const CipherKey &key, uint64_t *augment) const;
|
||||||
|
|
||||||
// functional interfaces
|
// functional interfaces
|
||||||
/*
|
/*
|
||||||
Stream encoding in-place.
|
Stream encoding in-place.
|
||||||
*/
|
*/
|
||||||
virtual bool streamEncode(unsigned char *in, int len,
|
virtual bool streamEncode(unsigned char *in, int len, uint64_t iv64,
|
||||||
uint64_t iv64, const CipherKey &key) const;
|
const CipherKey &key) const;
|
||||||
virtual bool streamDecode(unsigned char *in, int len,
|
virtual bool streamDecode(unsigned char *in, int len, uint64_t iv64,
|
||||||
uint64_t iv64, const CipherKey &key) const;
|
const CipherKey &key) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Block encoding is done in-place. Partial blocks are supported, but
|
Block encoding is done in-place. Partial blocks are supported, but
|
||||||
blocks are always expected to begin on a block boundary. See
|
blocks are always expected to begin on a block boundary. See
|
||||||
blockSize().
|
blockSize().
|
||||||
*/
|
*/
|
||||||
virtual bool blockEncode(unsigned char *buf, int size,
|
virtual bool blockEncode(unsigned char *buf, int size, uint64_t iv64,
|
||||||
uint64_t iv64, const CipherKey &key) const;
|
const CipherKey &key) const;
|
||||||
virtual bool blockDecode(unsigned char *buf, int size,
|
virtual bool blockDecode(unsigned char *buf, int size, uint64_t iv64,
|
||||||
uint64_t iv64, const CipherKey &key) const;
|
const CipherKey &key) const;
|
||||||
|
|
||||||
// hack to help with static builds
|
// hack to help with static builds
|
||||||
static bool Enabled();
|
static bool Enabled();
|
||||||
private:
|
|
||||||
void setIVec( unsigned char *ivec, uint64_t seed,
|
|
||||||
const shared_ptr<SSLKey> &key ) const;
|
|
||||||
|
|
||||||
// deprecated - for backward compatibility
|
private:
|
||||||
void setIVec_old( unsigned char *ivec, unsigned int seed,
|
void setIVec(unsigned char *ivec, uint64_t seed,
|
||||||
const shared_ptr<SSLKey> &key ) const;
|
const shared_ptr<SSLKey> &key) const;
|
||||||
|
|
||||||
|
// deprecated - for backward compatibility
|
||||||
|
void setIVec_old(unsigned char *ivec, unsigned int seed,
|
||||||
|
const shared_ptr<SSLKey> &key) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -32,17 +32,16 @@
|
|||||||
using namespace rel;
|
using namespace rel;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static shared_ptr<NameIO> NewStreamNameIO( const Interface &iface,
|
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 ) );
|
return shared_ptr<NameIO>(new StreamNameIO(iface, cipher, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool StreamIO_registered = NameIO::Register("Stream",
|
static bool StreamIO_registered = NameIO::Register(
|
||||||
gettext_noop("Stream encoding, keeps filenames as short as possible"),
|
"Stream",
|
||||||
StreamNameIO::CurrentInterface(),
|
gettext_noop("Stream encoding, keeps filenames as short as possible"),
|
||||||
NewStreamNameIO);
|
StreamNameIO::CurrentInterface(), NewStreamNameIO);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
- Version 0.1 is for EncFS 0.x support. The difference to 1.0 is that 0.x
|
- Version 0.1 is for EncFS 0.x support. The difference to 1.0 is that 0.x
|
||||||
@ -65,145 +64,117 @@ static bool StreamIO_registered = NameIO::Register("Stream",
|
|||||||
|
|
||||||
- Version 2.1 adds support for version 0 for EncFS 0.x compatibility.
|
- 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
|
||||||
// implement major version 2, 1, and 0
|
return Interface("nameio/stream", 2, 1, 2);
|
||||||
return Interface("nameio/stream", 2, 1, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamNameIO::StreamNameIO( const rel::Interface &iface,
|
StreamNameIO::StreamNameIO(const rel::Interface &iface,
|
||||||
const shared_ptr<Cipher> &cipher,
|
const shared_ptr<Cipher> &cipher,
|
||||||
const CipherKey &key )
|
const CipherKey &key)
|
||||||
: _interface( iface.current() )
|
: _interface(iface.current()), _cipher(cipher), _key(key) {}
|
||||||
, _cipher( cipher )
|
|
||||||
, _key( key )
|
|
||||||
{
|
|
||||||
|
|
||||||
|
StreamNameIO::~StreamNameIO() {}
|
||||||
|
|
||||||
|
Interface StreamNameIO::interface() const { return CurrentInterface(); }
|
||||||
|
|
||||||
|
int StreamNameIO::maxEncodedNameLen(int plaintextStreamLen) const {
|
||||||
|
int encodedStreamLen = 2 + plaintextStreamLen;
|
||||||
|
return B256ToB64Bytes(encodedStreamLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamNameIO::~StreamNameIO()
|
int StreamNameIO::maxDecodedNameLen(int encodedStreamLen) const {
|
||||||
{
|
int decLen256 = B64ToB256Bytes(encodedStreamLen);
|
||||||
|
return decLen256 - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface StreamNameIO::interface() const
|
int StreamNameIO::encodeName(const char *plaintextName, int length,
|
||||||
{
|
uint64_t *iv, char *encodedName) const {
|
||||||
return CurrentInterface();
|
uint64_t tmpIV = 0;
|
||||||
|
if (iv && _interface >= 2) tmpIV = *iv;
|
||||||
|
|
||||||
|
unsigned int mac =
|
||||||
|
_cipher->MAC_16((const unsigned char *)plaintextName, length, _key, iv);
|
||||||
|
|
||||||
|
// add on checksum bytes
|
||||||
|
unsigned char *encodeBegin;
|
||||||
|
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 {
|
||||||
|
// encfs 0.x stored checksums at the end.
|
||||||
|
encodedName[length] = (mac >> 8) & 0xff;
|
||||||
|
encodedName[length + 1] = (mac) & 0xff;
|
||||||
|
encodeBegin = (unsigned char *)encodedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stream encode the plaintext bytes
|
||||||
|
memcpy(encodeBegin, plaintextName, length);
|
||||||
|
_cipher->nameEncode(encodeBegin, length, (uint64_t)mac ^ tmpIV, _key);
|
||||||
|
|
||||||
|
// convert the entire thing to base 64 ascii..
|
||||||
|
int encodedStreamLen = length + 2;
|
||||||
|
int encLen64 = B256ToB64Bytes(encodedStreamLen);
|
||||||
|
|
||||||
|
changeBase2Inline((unsigned char *)encodedName, encodedStreamLen, 8, 6, true);
|
||||||
|
B64ToAscii((unsigned char *)encodedName, encLen64);
|
||||||
|
|
||||||
|
return encLen64;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StreamNameIO::maxEncodedNameLen( int plaintextStreamLen ) const
|
int StreamNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
|
||||||
{
|
char *plaintextName) const {
|
||||||
int encodedStreamLen = 2 + plaintextStreamLen;
|
rAssert(length > 2);
|
||||||
return B256ToB64Bytes( encodedStreamLen );
|
int decLen256 = B64ToB256Bytes(length);
|
||||||
}
|
int decodedStreamLen = decLen256 - 2;
|
||||||
|
|
||||||
int StreamNameIO::maxDecodedNameLen( int encodedStreamLen ) const
|
if (decodedStreamLen <= 0) throw ERROR("Filename too small to decode");
|
||||||
{
|
|
||||||
int decLen256 = B64ToB256Bytes( encodedStreamLen );
|
BUFFER_INIT(tmpBuf, 32, (unsigned int)length);
|
||||||
return decLen256 - 2;
|
|
||||||
}
|
// decode into tmpBuf, because this step produces more data then we can fit
|
||||||
|
// into the result buffer..
|
||||||
int StreamNameIO::encodeName( const char *plaintextName, int length,
|
AsciiToB64((unsigned char *)tmpBuf, (unsigned char *)encodedName, length);
|
||||||
uint64_t *iv, char *encodedName ) const
|
changeBase2Inline((unsigned char *)tmpBuf, length, 6, 8, false);
|
||||||
{
|
|
||||||
uint64_t tmpIV = 0;
|
// pull out the checksum value which is used as an initialization vector
|
||||||
if( iv && _interface >= 2 )
|
uint64_t tmpIV = 0;
|
||||||
tmpIV = *iv;
|
unsigned int mac;
|
||||||
|
if (_interface >= 1) {
|
||||||
unsigned int mac = _cipher->MAC_16( (const unsigned char *)plaintextName,
|
// current versions store the checksum at the beginning
|
||||||
length, _key, iv );
|
mac = ((unsigned int)((unsigned char)tmpBuf[0])) << 8 |
|
||||||
|
((unsigned int)((unsigned char)tmpBuf[1]));
|
||||||
// add on checksum bytes
|
|
||||||
unsigned char *encodeBegin;
|
// version 2 adds support for IV chaining..
|
||||||
if(_interface >= 1)
|
if (iv && _interface >= 2) tmpIV = *iv;
|
||||||
{
|
|
||||||
// current versions store the checksum at the beginning
|
memcpy(plaintextName, tmpBuf + 2, decodedStreamLen);
|
||||||
encodedName[0] = (mac >> 8) & 0xff;
|
} else {
|
||||||
encodedName[1] = (mac ) & 0xff;
|
// encfs 0.x stored checksums at the end.
|
||||||
encodeBegin = (unsigned char *)encodedName+2;
|
mac = ((unsigned int)((unsigned char)tmpBuf[decodedStreamLen])) << 8 |
|
||||||
} else
|
((unsigned int)((unsigned char)tmpBuf[decodedStreamLen + 1]));
|
||||||
{
|
|
||||||
// encfs 0.x stored checksums at the end.
|
memcpy(plaintextName, tmpBuf, decodedStreamLen);
|
||||||
encodedName[length] = (mac >> 8) & 0xff;
|
}
|
||||||
encodedName[length+1] = (mac ) & 0xff;
|
|
||||||
encodeBegin = (unsigned char *)encodedName;
|
// use nameDeocde instead of streamDecode for backward compatibility
|
||||||
}
|
_cipher->nameDecode((unsigned char *)plaintextName, decodedStreamLen,
|
||||||
|
(uint64_t)mac ^ tmpIV, _key);
|
||||||
// stream encode the plaintext bytes
|
|
||||||
memcpy( encodeBegin, plaintextName, length );
|
// compute MAC to check with stored value
|
||||||
_cipher->nameEncode( encodeBegin, length, (uint64_t)mac ^ tmpIV, _key);
|
unsigned int mac2 = _cipher->MAC_16((const unsigned char *)plaintextName,
|
||||||
|
decodedStreamLen, _key, iv);
|
||||||
// convert the entire thing to base 64 ascii..
|
|
||||||
int encodedStreamLen = length + 2;
|
BUFFER_RESET(tmpBuf);
|
||||||
int encLen64 = B256ToB64Bytes( encodedStreamLen );
|
if (mac2 != mac) {
|
||||||
|
rDebug("checksum mismatch: expected %u, got %u", mac, mac2);
|
||||||
changeBase2Inline( (unsigned char *)encodedName, encodedStreamLen,
|
rDebug("on decode of %i bytes", decodedStreamLen);
|
||||||
8, 6, true );
|
throw ERROR("checksum mismatch in filename decode");
|
||||||
B64ToAscii( (unsigned char *)encodedName, encLen64 );
|
}
|
||||||
|
|
||||||
return encLen64;
|
return decodedStreamLen;
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
BUFFER_INIT( tmpBuf, 32, (unsigned int)length );
|
|
||||||
|
|
||||||
// decode into tmpBuf, because this step produces more data then we can fit
|
|
||||||
// into the result buffer..
|
|
||||||
AsciiToB64( (unsigned char *)tmpBuf, (unsigned char *)encodedName, length );
|
|
||||||
changeBase2Inline((unsigned char *)tmpBuf, length, 6, 8, false);
|
|
||||||
|
|
||||||
// pull out the checksum value which is used as an initialization vector
|
|
||||||
uint64_t tmpIV = 0;
|
|
||||||
unsigned int mac;
|
|
||||||
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]));
|
|
||||||
|
|
||||||
// version 2 adds support for IV chaining..
|
|
||||||
if( iv && _interface >= 2 )
|
|
||||||
tmpIV = *iv;
|
|
||||||
|
|
||||||
memcpy( plaintextName, tmpBuf+2, decodedStreamLen );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
// encfs 0.x stored checksums at the end.
|
|
||||||
mac = ((unsigned int)((unsigned char)tmpBuf[decodedStreamLen])) << 8
|
|
||||||
| ((unsigned int)((unsigned char)tmpBuf[decodedStreamLen+1]));
|
|
||||||
|
|
||||||
memcpy( plaintextName, tmpBuf, decodedStreamLen );
|
|
||||||
}
|
|
||||||
|
|
||||||
// use nameDeocde instead of streamDecode for backward compatibility
|
|
||||||
_cipher->nameDecode( (unsigned char *)plaintextName, decodedStreamLen,
|
|
||||||
(uint64_t)mac ^ tmpIV, _key);
|
|
||||||
|
|
||||||
// compute MAC to check with stored value
|
|
||||||
unsigned int mac2 = _cipher->MAC_16((const unsigned char *)plaintextName,
|
|
||||||
decodedStreamLen, _key, iv);
|
|
||||||
|
|
||||||
BUFFER_RESET( tmpBuf );
|
|
||||||
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" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return decodedStreamLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StreamNameIO::Enabled()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StreamNameIO::Enabled() { return true; }
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -26,34 +26,32 @@
|
|||||||
|
|
||||||
class Cipher;
|
class Cipher;
|
||||||
|
|
||||||
class StreamNameIO : public NameIO
|
class StreamNameIO : public NameIO {
|
||||||
{
|
public:
|
||||||
public:
|
static rel::Interface CurrentInterface();
|
||||||
static rel::Interface CurrentInterface();
|
|
||||||
|
|
||||||
StreamNameIO( const rel::Interface &iface,
|
StreamNameIO(const rel::Interface &iface, const shared_ptr<Cipher> &cipher,
|
||||||
const shared_ptr<Cipher> &cipher,
|
const CipherKey &key);
|
||||||
const CipherKey &key );
|
virtual ~StreamNameIO();
|
||||||
virtual ~StreamNameIO();
|
|
||||||
|
|
||||||
virtual rel::Interface interface() const;
|
virtual rel::Interface interface() const;
|
||||||
|
|
||||||
virtual int maxEncodedNameLen( int plaintextNameLen ) const;
|
virtual int maxEncodedNameLen(int plaintextNameLen) const;
|
||||||
virtual int maxDecodedNameLen( int encodedNameLen ) const;
|
virtual int maxDecodedNameLen(int encodedNameLen) const;
|
||||||
|
|
||||||
// hack to help with static builds
|
// hack to help with static builds
|
||||||
static bool Enabled();
|
static bool Enabled();
|
||||||
protected:
|
|
||||||
virtual int encodeName( const char *plaintextName, int length,
|
protected:
|
||||||
uint64_t *iv, char *encodedName ) const;
|
virtual int encodeName(const char *plaintextName, int length, uint64_t *iv,
|
||||||
virtual int decodeName( const char *encodedName, int length,
|
char *encodedName) const;
|
||||||
uint64_t *iv, char *plaintextName ) const;
|
virtual int decodeName(const char *encodedName, int length, uint64_t *iv,
|
||||||
private:
|
char *plaintextName) const;
|
||||||
int _interface;
|
|
||||||
shared_ptr<Cipher> _cipher;
|
private:
|
||||||
CipherKey _key;
|
int _interface;
|
||||||
|
shared_ptr<Cipher> _cipher;
|
||||||
|
CipherKey _key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
253
encfs/base64.cpp
253
encfs/base64.cpp
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -27,32 +27,28 @@
|
|||||||
// It is the caller's responsibility to make sure the output array is large
|
// It is the caller's responsibility to make sure the output array is large
|
||||||
// enough.
|
// enough.
|
||||||
void changeBase2(unsigned char *src, int srcLen, int src2Pow,
|
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;
|
||||||
unsigned long work = 0;
|
int workBits = 0; // number of bits left in the work buffer
|
||||||
int workBits = 0; // number of bits left in the work buffer
|
unsigned char *end = src + srcLen;
|
||||||
unsigned char *end = src + srcLen;
|
unsigned char *origDst = dst;
|
||||||
unsigned char *origDst = dst;
|
const int mask = (1 << dst2Pow) - 1;
|
||||||
const int mask = (1 << dst2Pow) -1;
|
|
||||||
|
|
||||||
// copy the new bits onto the high bits of the stream.
|
// copy the new bits onto the high bits of the stream.
|
||||||
// The bits that fall off the low end are the output bits.
|
// The bits that fall off the low end are the output bits.
|
||||||
while(src != end)
|
while (src != end) {
|
||||||
{
|
work |= ((unsigned long)(*src++)) << workBits;
|
||||||
work |= ((unsigned long)(*src++)) << workBits;
|
workBits += src2Pow;
|
||||||
workBits += src2Pow;
|
|
||||||
|
|
||||||
while(workBits >= dst2Pow)
|
while (workBits >= dst2Pow) {
|
||||||
{
|
*dst++ = work & mask;
|
||||||
*dst++ = work & mask;
|
work >>= dst2Pow;
|
||||||
work >>= dst2Pow;
|
workBits -= dst2Pow;
|
||||||
workBits -= dst2Pow;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// now, we could have a partial value left in the work buffer..
|
// now, we could have a partial value left in the work buffer..
|
||||||
if(workBits && ((dst - origDst) < dstLen))
|
if (workBits && ((dst - origDst) < dstLen)) *dst++ = work & mask;
|
||||||
*dst++ = work & mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -62,65 +58,52 @@ void changeBase2(unsigned char *src, int srcLen, int src2Pow,
|
|||||||
Uses the stack to store output values. Recurse every time a new value is
|
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.
|
to be written, then write the value at the tail end of the recursion.
|
||||||
*/
|
*/
|
||||||
static
|
static void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow,
|
||||||
void changeBase2Inline(unsigned char *src, int srcLen,
|
int dst2Pow, bool outputPartialLastByte,
|
||||||
int src2Pow, int dst2Pow,
|
unsigned long work, int workBits,
|
||||||
bool outputPartialLastByte,
|
unsigned char *outLoc) {
|
||||||
unsigned long work,
|
const int mask = (1 << dst2Pow) - 1;
|
||||||
int workBits,
|
if (!outLoc) outLoc = src;
|
||||||
unsigned char *outLoc)
|
|
||||||
{
|
|
||||||
const int mask = (1 << dst2Pow) -1;
|
|
||||||
if(!outLoc)
|
|
||||||
outLoc = src;
|
|
||||||
|
|
||||||
// copy the new bits onto the high bits of the stream.
|
// copy the new bits onto the high bits of the stream.
|
||||||
// The bits that fall off the low end are the output bits.
|
// 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;
|
||||||
work |= ((unsigned long)(*src++)) << workBits;
|
workBits += src2Pow;
|
||||||
workBits += src2Pow;
|
--srcLen;
|
||||||
--srcLen;
|
}
|
||||||
}
|
|
||||||
|
// we have at least one value that can be output
|
||||||
// we have at least one value that can be output
|
unsigned char outVal = work & mask;
|
||||||
unsigned char outVal = work & mask;
|
work >>= dst2Pow;
|
||||||
work >>= dst2Pow;
|
workBits -= dst2Pow;
|
||||||
workBits -= dst2Pow;
|
|
||||||
|
if (srcLen) {
|
||||||
if(srcLen)
|
// more input left, so recurse
|
||||||
{
|
changeBase2Inline(src, srcLen, src2Pow, dst2Pow, outputPartialLastByte,
|
||||||
// more input left, so recurse
|
work, workBits, outLoc + 1);
|
||||||
changeBase2Inline( src, srcLen, src2Pow, dst2Pow,
|
*outLoc = outVal;
|
||||||
outputPartialLastByte, work, workBits, outLoc+1);
|
} else {
|
||||||
*outLoc = outVal;
|
// no input left, we can write remaining values directly
|
||||||
} else
|
*outLoc++ = outVal;
|
||||||
{
|
|
||||||
// no input left, we can write remaining values directly
|
// we could have a partial value left in the work buffer..
|
||||||
*outLoc++ = outVal;
|
if (outputPartialLastByte) {
|
||||||
|
while (workBits > 0) {
|
||||||
// we could have a partial value left in the work buffer..
|
*outLoc++ = work & mask;
|
||||||
if(outputPartialLastByte)
|
work >>= dst2Pow;
|
||||||
{
|
workBits -= dst2Pow;
|
||||||
while(workBits > 0)
|
}
|
||||||
{
|
|
||||||
*outLoc++ = work & mask;
|
|
||||||
work >>= dst2Pow;
|
|
||||||
workBits -= dst2Pow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeBase2Inline(unsigned char *src, int srcLen,
|
void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow, int dst2Pow,
|
||||||
int src2Pow, int dst2Pow,
|
bool outputPartialLastByte) {
|
||||||
bool outputPartialLastByte)
|
changeBase2Inline(src, srcLen, src2Pow, dst2Pow, outputPartialLastByte, 0, 0,
|
||||||
{
|
0);
|
||||||
changeBase2Inline(src, srcLen, src2Pow, dst2Pow,
|
|
||||||
outputPartialLastByte, 0, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// character set for ascii b64:
|
// character set for ascii b64:
|
||||||
// ",-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
// ",-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
// a standard base64 (eg a64l doesn't use ',-' but uses './'. We don't
|
// a standard base64 (eg a64l doesn't use ',-' but uses './'. We don't
|
||||||
@ -128,83 +111,69 @@ void changeBase2Inline(unsigned char *src, int srcLen,
|
|||||||
// '.' included in the encrypted names, so that it can be reserved for files
|
// '.' included in the encrypted names, so that it can be reserved for files
|
||||||
// with special meaning.
|
// with special meaning.
|
||||||
static const char B642AsciiTable[] = ",-0123456789";
|
static const char B642AsciiTable[] = ",-0123456789";
|
||||||
void B64ToAscii(unsigned char *in, int length)
|
void B64ToAscii(unsigned char *in, int length) {
|
||||||
{
|
for (int offset = 0; offset < length; ++offset) {
|
||||||
for(int offset=0; offset<length; ++offset)
|
int ch = in[offset];
|
||||||
{
|
if (ch > 11) {
|
||||||
int ch = in[offset];
|
if (ch > 37)
|
||||||
if(ch > 11)
|
ch += 'a' - 38;
|
||||||
{
|
else
|
||||||
if(ch > 37)
|
ch += 'A' - 12;
|
||||||
ch += 'a' - 38;
|
} else
|
||||||
else
|
ch = B642AsciiTable[ch];
|
||||||
ch += 'A' - 12;
|
|
||||||
} else
|
in[offset] = ch;
|
||||||
ch = B642AsciiTable[ ch ];
|
}
|
||||||
|
|
||||||
in[offset] = ch;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char Ascii2B64Table[] =
|
static const unsigned char Ascii2B64Table[] =
|
||||||
" 01 23456789:; ";
|
" 01 23456789:; ";
|
||||||
// 0123456789 123456789 123456789 123456789 123456789 123456789 1234
|
// 0123456789 123456789 123456789 123456789 123456789 123456789 1234
|
||||||
// 0 1 2 3 4 5 6
|
// 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);
|
||||||
return AsciiToB64(in, in, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsciiToB64(unsigned char *out, const unsigned char *in, int length)
|
void AsciiToB64(unsigned char *out, const unsigned char *in, int length) {
|
||||||
{
|
while (length--) {
|
||||||
while(length--)
|
unsigned char ch = *in++;
|
||||||
{
|
if (ch >= 'A') {
|
||||||
unsigned char ch = *in++;
|
if (ch >= 'a')
|
||||||
if(ch >= 'A')
|
ch += 38 - 'a';
|
||||||
{
|
else
|
||||||
if(ch >= 'a')
|
ch += 12 - 'A';
|
||||||
ch += 38 - 'a';
|
} else
|
||||||
else
|
ch = Ascii2B64Table[ch] - '0';
|
||||||
ch += 12 - 'A';
|
|
||||||
} else
|
|
||||||
ch = Ascii2B64Table[ ch ] - '0';
|
|
||||||
|
|
||||||
*out++ = ch;
|
*out++ = ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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';
|
||||||
|
else
|
||||||
|
ch += '2' - 26;
|
||||||
|
|
||||||
void B32ToAscii(unsigned char *buf, int len)
|
buf[offset] = ch;
|
||||||
{
|
}
|
||||||
for(int offset=0; offset<len; ++offset)
|
|
||||||
{
|
|
||||||
int ch = buf[offset];
|
|
||||||
if (ch >= 0 && ch < 26)
|
|
||||||
ch += 'A';
|
|
||||||
else
|
|
||||||
ch += '2' - 26;
|
|
||||||
|
|
||||||
buf[offset] = ch;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsciiToB32(unsigned char *in, int length)
|
void AsciiToB32(unsigned char *in, int length) {
|
||||||
{
|
return AsciiToB32(in, in, length);
|
||||||
return AsciiToB32(in, in, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsciiToB32(unsigned char *out, const unsigned char *in, int length)
|
void AsciiToB32(unsigned char *out, const unsigned char *in, int length) {
|
||||||
{
|
while (length--) {
|
||||||
while(length--)
|
unsigned char ch = *in++;
|
||||||
{
|
int lch = toupper(ch);
|
||||||
unsigned char ch = *in++;
|
if (lch >= 'A')
|
||||||
int lch = toupper(ch);
|
lch -= 'A';
|
||||||
if (lch >= 'A')
|
else
|
||||||
lch -= 'A';
|
lch += 26 - '2';
|
||||||
else
|
|
||||||
lch += 26 - '2';
|
|
||||||
|
|
||||||
*out++ = (unsigned char)lch;
|
*out++ = (unsigned char)lch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -21,41 +21,33 @@
|
|||||||
#ifndef _base64_incl_
|
#ifndef _base64_incl_
|
||||||
#define _base64_incl_
|
#define _base64_incl_
|
||||||
|
|
||||||
|
inline int B64ToB256Bytes(int numB64Bytes) {
|
||||||
inline int B64ToB256Bytes( int numB64Bytes )
|
return (numB64Bytes * 6) / 8; // round down
|
||||||
{
|
|
||||||
return (numB64Bytes * 6) / 8; // round down
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int B32ToB256Bytes( int numB32Bytes )
|
inline int B32ToB256Bytes(int numB32Bytes) {
|
||||||
{
|
return (numB32Bytes * 5) / 8; // round down
|
||||||
return (numB32Bytes * 5) / 8; // round down
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int B256ToB64Bytes( int numB256Bytes )
|
inline int B256ToB64Bytes(int numB256Bytes) {
|
||||||
{
|
return (numB256Bytes * 8 + 5) / 6; // round up
|
||||||
return (numB256Bytes * 8 + 5) / 6; // round up
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int B256ToB32Bytes( int numB256Bytes )
|
inline int B256ToB32Bytes(int numB256Bytes) {
|
||||||
{
|
return (numB256Bytes * 8 + 4) / 5; // round up
|
||||||
return (numB256Bytes * 8 + 4) / 5; // round up
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
convert data between different bases - each being a power of 2.
|
convert data between different bases - each being a power of 2.
|
||||||
*/
|
*/
|
||||||
void changeBase2(unsigned char *src, int srcLength, int srcPow2,
|
void changeBase2(unsigned char *src, int srcLength, int srcPow2,
|
||||||
unsigned char *dst, int dstLength, int dstPow2);
|
unsigned char *dst, int dstLength, int dstPow2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
same as changeBase2, but writes output over the top of input data.
|
same as changeBase2, but writes output over the top of input data.
|
||||||
*/
|
*/
|
||||||
void changeBase2Inline(unsigned char *buf, int srcLength,
|
void changeBase2Inline(unsigned char *buf, int srcLength, int srcPow2,
|
||||||
int srcPow2, int dst2Pow,
|
int dst2Pow, bool outputPartialLastByte);
|
||||||
bool outputPartialLastByte);
|
|
||||||
|
|
||||||
|
|
||||||
// inplace translation from values [0,2^6] => base64 ASCII
|
// inplace translation from values [0,2^6] => base64 ASCII
|
||||||
void B64ToAscii(unsigned char *buf, int length);
|
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);
|
void AsciiToB32(unsigned char *out, const unsigned char *in, int length);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
// This header stores workaround code for dealing with incompatible changes
|
// This header stores workaround code for dealing with incompatible changes
|
||||||
// made to boost archive/serialization classes.
|
// made to boost archive/serialization classes.
|
||||||
|
|
||||||
|
|
||||||
#if (BOOST_VERSION <= 104100)
|
#if (BOOST_VERSION <= 104100)
|
||||||
// Easy case, boost archive serial numbers are sizeof(int)
|
// Easy case, boost archive serial numbers are sizeof(int)
|
||||||
BOOST_CLASS_VERSION(EncFSConfig, V6SubVersion)
|
BOOST_CLASS_VERSION(EncFSConfig, V6SubVersion)
|
||||||
@ -23,74 +22,60 @@ BOOST_CLASS_VERSION(EncFSConfig, V6SubVersion)
|
|||||||
|
|
||||||
BOOST_CLASS_VERSION(EncFSConfig, 20)
|
BOOST_CLASS_VERSION(EncFSConfig, 20)
|
||||||
|
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace archive {
|
namespace archive {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
|
||||||
// Specialize iserializer class in order to get rid of version check
|
// Specialize iserializer class in order to get rid of version check
|
||||||
template<class Archive>
|
template <class Archive>
|
||||||
class iserializer<Archive, EncFSConfig> : public basic_iserializer
|
class iserializer<Archive, EncFSConfig> : public basic_iserializer {
|
||||||
{
|
private:
|
||||||
private:
|
virtual void destroy(/*const*/ void *address) const {
|
||||||
virtual void destroy(/*const*/ void *address) const {
|
boost::serialization::access::destroy(static_cast<EncFSConfig *>(address));
|
||||||
boost::serialization::access::destroy(static_cast<EncFSConfig *>(address));
|
}
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
explicit iserializer() :
|
explicit iserializer()
|
||||||
basic_iserializer(
|
: basic_iserializer(boost::serialization::singleton<
|
||||||
boost::serialization::singleton<
|
BOOST_DEDUCED_TYPENAME boost::serialization::
|
||||||
BOOST_DEDUCED_TYPENAME
|
type_info_implementation<
|
||||||
boost::serialization::type_info_implementation<EncFSConfig>::type
|
EncFSConfig>::type>::get_const_instance()) {}
|
||||||
>::get_const_instance()
|
|
||||||
)
|
public:
|
||||||
{}
|
virtual BOOST_DLLEXPORT void load_object_data(
|
||||||
public:
|
basic_iarchive &ar, void *x,
|
||||||
virtual BOOST_DLLEXPORT void load_object_data(
|
const unsigned int file_version) const BOOST_USED;
|
||||||
basic_iarchive & ar,
|
virtual bool class_info() const {
|
||||||
void *x,
|
return boost::serialization::implementation_level<EncFSConfig>::value >=
|
||||||
const unsigned int file_version
|
boost::serialization::object_class_info;
|
||||||
) const BOOST_USED;
|
}
|
||||||
virtual bool class_info() const {
|
virtual bool tracking(const unsigned int /* flags */) const {
|
||||||
return boost::serialization::implementation_level<EncFSConfig>::value
|
return boost::serialization::tracking_level<EncFSConfig>::value ==
|
||||||
>= boost::serialization::object_class_info;
|
boost::serialization::track_always ||
|
||||||
}
|
(boost::serialization::tracking_level<EncFSConfig>::value ==
|
||||||
virtual bool tracking(const unsigned int /* flags */) const {
|
boost::serialization::track_selectively &&
|
||||||
return boost::serialization::tracking_level<EncFSConfig>::value
|
serialized_as_pointer());
|
||||||
== boost::serialization::track_always
|
}
|
||||||
|| ( boost::serialization::tracking_level<EncFSConfig>::value
|
virtual version_type version() const {
|
||||||
== boost::serialization::track_selectively
|
return version_type(::boost::serialization::version<EncFSConfig>::value);
|
||||||
&& serialized_as_pointer());
|
}
|
||||||
}
|
virtual bool is_polymorphic() const {
|
||||||
virtual version_type version() const {
|
return boost::is_polymorphic<EncFSConfig>::value;
|
||||||
return version_type(::boost::serialization::version<EncFSConfig>::value);
|
}
|
||||||
}
|
virtual ~iserializer() {};
|
||||||
virtual bool is_polymorphic() const {
|
|
||||||
return boost::is_polymorphic<EncFSConfig>::value;
|
|
||||||
}
|
|
||||||
virtual ~iserializer(){};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Archive>
|
template <class Archive>
|
||||||
BOOST_DLLEXPORT void iserializer<Archive, EncFSConfig>::load_object_data(
|
BOOST_DLLEXPORT void iserializer<Archive, EncFSConfig>::load_object_data(
|
||||||
basic_iarchive & ar,
|
basic_iarchive &ar, void *x, const unsigned int file_version) const {
|
||||||
void *x,
|
boost::serialization::serialize_adl(
|
||||||
const unsigned int file_version
|
boost::serialization::smart_cast_reference<Archive &>(ar),
|
||||||
) const {
|
*static_cast<EncFSConfig *>(x), file_version);
|
||||||
boost::serialization::serialize_adl(
|
|
||||||
boost::serialization::smart_cast_reference<Archive &>(ar),
|
|
||||||
* static_cast<EncFSConfig *>(x),
|
|
||||||
file_version
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // BOOST_VERSIONING_INCL
|
||||||
|
|
||||||
#endif // BOOST_VERSIONING_INCL
|
|
||||||
|
1061
encfs/encfs.cpp
1061
encfs/encfs.cpp
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -32,34 +32,30 @@
|
|||||||
#ifndef linux
|
#ifndef linux
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
|
||||||
static __inline int setfsuid(uid_t uid)
|
static __inline int setfsuid(uid_t uid) {
|
||||||
{
|
uid_t olduid = geteuid();
|
||||||
uid_t olduid = geteuid();
|
|
||||||
|
|
||||||
seteuid(uid);
|
seteuid(uid);
|
||||||
|
|
||||||
if (errno != EINVAL)
|
if (errno != EINVAL) errno = 0;
|
||||||
errno = 0;
|
|
||||||
|
|
||||||
return olduid;
|
return olduid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline int setfsgid(gid_t gid)
|
static __inline int setfsgid(gid_t gid) {
|
||||||
{
|
gid_t oldgid = getegid();
|
||||||
gid_t oldgid = getegid();
|
|
||||||
|
|
||||||
setegid(gid);
|
setegid(gid);
|
||||||
|
|
||||||
if (errno != EINVAL)
|
if (errno != EINVAL) errno = 0;
|
||||||
errno = 0;
|
|
||||||
|
|
||||||
return oldgid;
|
return oldgid;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int encfs_getattr(const char *path, struct stat *stbuf);
|
int encfs_getattr(const char *path, struct stat *stbuf);
|
||||||
int encfs_fgetattr(const char *path, struct stat *stbuf,
|
int encfs_fgetattr(const char *path, struct stat *stbuf,
|
||||||
struct fuse_file_info *fi);
|
struct fuse_file_info *fi);
|
||||||
int encfs_readlink(const char *path, char *buf, size_t size);
|
int encfs_readlink(const char *path, char *buf, size_t size);
|
||||||
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);
|
||||||
int encfs_mknod(const char *path, mode_t mode, dev_t rdev);
|
int encfs_mknod(const char *path, mode_t mode, dev_t rdev);
|
||||||
@ -72,38 +68,36 @@ int encfs_link(const char *from, const char *to);
|
|||||||
int encfs_chmod(const char *path, mode_t mode);
|
int encfs_chmod(const char *path, mode_t mode);
|
||||||
int encfs_chown(const char *path, uid_t uid, gid_t gid);
|
int encfs_chown(const char *path, uid_t uid, gid_t gid);
|
||||||
int encfs_truncate(const char *path, off_t size);
|
int encfs_truncate(const char *path, off_t size);
|
||||||
int encfs_ftruncate(const char *path, off_t size,
|
int encfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi);
|
||||||
struct fuse_file_info *fi);
|
|
||||||
int encfs_utime(const char *path, struct utimbuf *buf);
|
int encfs_utime(const char *path, struct utimbuf *buf);
|
||||||
int encfs_open(const char *path, struct fuse_file_info *info);
|
int encfs_open(const char *path, struct fuse_file_info *info);
|
||||||
int encfs_release(const char *path, struct fuse_file_info *info);
|
int encfs_release(const char *path, struct fuse_file_info *info);
|
||||||
int encfs_read(const char *path, char *buf, size_t size, off_t offset,
|
int encfs_read(const char *path, char *buf, size_t size, off_t offset,
|
||||||
struct fuse_file_info *info);
|
struct fuse_file_info *info);
|
||||||
int encfs_write(const char *path, const char *buf, size_t size, off_t offset,
|
int encfs_write(const char *path, const char *buf, size_t size, off_t offset,
|
||||||
struct fuse_file_info *info);
|
struct fuse_file_info *info);
|
||||||
int encfs_statfs(const char *, struct statvfs *fst);
|
int encfs_statfs(const char *, struct statvfs *fst);
|
||||||
int encfs_flush(const char *, struct fuse_file_info *info);
|
int encfs_flush(const char *, struct fuse_file_info *info);
|
||||||
int encfs_fsync(const char *path, int flags, struct fuse_file_info *info);
|
int encfs_fsync(const char *path, int flags, struct fuse_file_info *info);
|
||||||
|
|
||||||
#ifdef HAVE_XATTR
|
#ifdef HAVE_XATTR
|
||||||
|
|
||||||
# ifdef XATTR_ADD_OPT
|
#ifdef XATTR_ADD_OPT
|
||||||
int encfs_setxattr( const char *path, const char *name, const char *value,
|
int encfs_setxattr(const char *path, const char *name, const char *value,
|
||||||
size_t size, int flags, uint32_t position);
|
size_t size, int flags, uint32_t position);
|
||||||
int encfs_getxattr( const char *path, const char *name, char *value,
|
int encfs_getxattr(const char *path, const char *name, char *value, size_t size,
|
||||||
size_t size, uint32_t position );
|
uint32_t position);
|
||||||
# else
|
#else
|
||||||
int encfs_setxattr( const char *path, const char *name, const char *value,
|
int encfs_setxattr(const char *path, const char *name, const char *value,
|
||||||
size_t size, int flags);
|
size_t size, int flags);
|
||||||
int encfs_getxattr( const char *path, const char *name, char *value,
|
int encfs_getxattr(const char *path, const char *name, char *value,
|
||||||
size_t size );
|
size_t size);
|
||||||
# endif
|
|
||||||
|
|
||||||
int encfs_listxattr( const char *path, char *list, size_t size );
|
|
||||||
int encfs_removexattr( const char *path, const char *name );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int encfs_utimens( const char *path, const struct timespec ts[2] );
|
int encfs_listxattr(const char *path, char *list, size_t size);
|
||||||
|
int encfs_removexattr(const char *path, const char *name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int encfs_utimens(const char *path, const struct timespec ts[2]);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
1261
encfs/encfsctl.cpp
1261
encfs/encfsctl.cpp
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -25,8 +25,6 @@
|
|||||||
#include "intl/gettext.h"
|
#include "intl/gettext.h"
|
||||||
|
|
||||||
// make shortcut for gettext
|
// make shortcut for gettext
|
||||||
# define _(STR) gettext (STR)
|
#define _(STR) gettext(STR)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
1203
encfs/main.cpp
1203
encfs/main.cpp
File diff suppressed because it is too large
Load Diff
@ -4,10 +4,10 @@
|
|||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
* Copyright (c) 2008, Valient Gough
|
* Copyright (c) 2008, Valient Gough
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by
|
* under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -31,36 +31,32 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void genKey( const shared_ptr<Cipher> &cipher )
|
void genKey(const shared_ptr<Cipher> &cipher) {
|
||||||
{
|
CipherKey key = cipher->newRandomKey();
|
||||||
CipherKey key = cipher->newRandomKey();
|
|
||||||
|
|
||||||
// encode with itself
|
// encode with itself
|
||||||
string b64Key = cipher->encodeAsString( key, key );
|
string b64Key = cipher->encodeAsString(key, key);
|
||||||
|
|
||||||
cout << b64Key << "\n";
|
cout << b64Key << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv) {
|
||||||
{
|
pid_t pid = getpid();
|
||||||
pid_t pid = getpid();
|
cerr << "pid = " << pid << "\n";
|
||||||
cerr << "pid = " << pid << "\n";
|
|
||||||
|
|
||||||
if(argc != 3)
|
if (argc != 3) {
|
||||||
{
|
cerr << "usage: makeKey [AES|Blowfish] [128|160|192|224|256]\n";
|
||||||
cerr << "usage: makeKey [AES|Blowfish] [128|160|192|224|256]\n";
|
return 1;
|
||||||
return 1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const char *type = argv[1];
|
const char *type = argv[1];
|
||||||
int size = atoi(argv[2]);
|
int size = atoi(argv[2]);
|
||||||
|
|
||||||
openssl_init(false);
|
openssl_init(false);
|
||||||
|
|
||||||
// get a list of the available algorithms
|
// get a list of the available algorithms
|
||||||
shared_ptr<Cipher> cipher = Cipher::New( type, size );
|
shared_ptr<Cipher> cipher = Cipher::New(type, size);
|
||||||
genKey( cipher );
|
genKey(cipher);
|
||||||
|
|
||||||
//openssl_shutdown(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// openssl_shutdown(false);
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -31,79 +31,65 @@
|
|||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned long pthreads_thread_id()
|
unsigned long pthreads_thread_id() { return (unsigned long)pthread_self(); }
|
||||||
{
|
|
||||||
return (unsigned long)pthread_self();
|
|
||||||
}
|
|
||||||
|
|
||||||
static pthread_mutex_t *crypto_locks = NULL;
|
static pthread_mutex_t *crypto_locks = NULL;
|
||||||
void pthreads_locking_callback( int mode, int n,
|
void pthreads_locking_callback(int mode, int n, const char *caller_file,
|
||||||
const char *caller_file, int caller_line )
|
int caller_line) {
|
||||||
{
|
(void)caller_file;
|
||||||
(void)caller_file;
|
(void)caller_line;
|
||||||
(void)caller_line;
|
|
||||||
|
|
||||||
if(!crypto_locks)
|
if (!crypto_locks) {
|
||||||
{
|
rDebug("Allocating %i locks for OpenSSL", CRYPTO_num_locks());
|
||||||
rDebug("Allocating %i locks for OpenSSL", CRYPTO_num_locks() );
|
crypto_locks = new pthread_mutex_t[CRYPTO_num_locks()];
|
||||||
crypto_locks = new pthread_mutex_t[ CRYPTO_num_locks() ];
|
for (int i = 0; i < CRYPTO_num_locks(); ++i)
|
||||||
for(int i=0; i<CRYPTO_num_locks(); ++i)
|
pthread_mutex_init(crypto_locks + i, 0);
|
||||||
pthread_mutex_init( crypto_locks+i, 0 );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(mode & CRYPTO_LOCK)
|
if (mode & CRYPTO_LOCK) {
|
||||||
{
|
pthread_mutex_lock(crypto_locks + n);
|
||||||
pthread_mutex_lock( crypto_locks + n );
|
} else {
|
||||||
} else
|
pthread_mutex_unlock(crypto_locks + n);
|
||||||
{
|
}
|
||||||
pthread_mutex_unlock( crypto_locks + n );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pthreads_locking_cleanup()
|
void pthreads_locking_cleanup() {
|
||||||
{
|
if (crypto_locks) {
|
||||||
if(crypto_locks)
|
for (int i = 0; i < CRYPTO_num_locks(); ++i)
|
||||||
{
|
pthread_mutex_destroy(crypto_locks + i);
|
||||||
for(int i=0; i<CRYPTO_num_locks(); ++i)
|
delete[] crypto_locks;
|
||||||
pthread_mutex_destroy( crypto_locks+i );
|
crypto_locks = NULL;
|
||||||
delete[] crypto_locks;
|
}
|
||||||
crypto_locks = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void openssl_init(bool threaded)
|
void openssl_init(bool threaded) {
|
||||||
{
|
// initialize the SSL library
|
||||||
// initialize the SSL library
|
SSL_load_error_strings();
|
||||||
SSL_load_error_strings();
|
SSL_library_init();
|
||||||
SSL_library_init();
|
|
||||||
|
|
||||||
unsigned int randSeed = 0;
|
unsigned int randSeed = 0;
|
||||||
RAND_bytes( (unsigned char*)&randSeed, sizeof(randSeed) );
|
RAND_bytes((unsigned char *)&randSeed, sizeof(randSeed));
|
||||||
srand( randSeed );
|
srand(randSeed);
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
/* Load all bundled ENGINEs into memory and make them visible */
|
/* Load all bundled ENGINEs into memory and make them visible */
|
||||||
ENGINE_load_builtin_engines();
|
ENGINE_load_builtin_engines();
|
||||||
/* Register all of them for every algorithm they collectively implement */
|
/* Register all of them for every algorithm they collectively implement */
|
||||||
ENGINE_register_all_complete();
|
ENGINE_register_all_complete();
|
||||||
#endif // NO_ENGINE
|
#endif // NO_ENGINE
|
||||||
|
|
||||||
if(threaded)
|
if (threaded) {
|
||||||
{
|
// provide locking functions to OpenSSL since we'll be running with
|
||||||
// provide locking functions to OpenSSL since we'll be running with
|
// threads accessing openssl in parallel.
|
||||||
// threads accessing openssl in parallel.
|
CRYPTO_set_id_callback(pthreads_thread_id);
|
||||||
CRYPTO_set_id_callback( pthreads_thread_id );
|
CRYPTO_set_locking_callback(pthreads_locking_callback);
|
||||||
CRYPTO_set_locking_callback( pthreads_locking_callback );
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void openssl_shutdown(bool threaded)
|
void openssl_shutdown(bool threaded) {
|
||||||
{
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
ENGINE_cleanup();
|
ENGINE_cleanup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(threaded)
|
if (threaded) pthreads_locking_cleanup();
|
||||||
pthreads_locking_cleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
* option) any later version.
|
* option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -25,5 +25,3 @@ void openssl_init(bool isThreaded);
|
|||||||
void openssl_shutdown(bool isThreaded);
|
void openssl_shutdown(bool isThreaded);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -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>
|
* Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
@ -28,7 +29,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(LIBC_SCCS) && !defined(lint)
|
#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 */
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
//#include "includes.h"
|
//#include "includes.h"
|
||||||
@ -50,134 +52,126 @@ static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:
|
|||||||
#include <readpassphrase.h>
|
#include <readpassphrase.h>
|
||||||
|
|
||||||
#ifdef TCSASOFT
|
#ifdef TCSASOFT
|
||||||
# define _T_FLUSH (TCSAFLUSH|TCSASOFT)
|
#define _T_FLUSH (TCSAFLUSH | TCSASOFT)
|
||||||
#else
|
#else
|
||||||
# define _T_FLUSH (TCSAFLUSH)
|
#define _T_FLUSH (TCSAFLUSH)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
|
/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
|
||||||
#if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
|
#if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
|
||||||
# define _POSIX_VDISABLE VDISABLE
|
#define _POSIX_VDISABLE VDISABLE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static volatile sig_atomic_t signo;
|
static volatile sig_atomic_t signo;
|
||||||
|
|
||||||
static void handler(int);
|
static void handler(int);
|
||||||
|
|
||||||
char *
|
char *readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) {
|
||||||
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
|
ssize_t nr;
|
||||||
{
|
int input, output, save_errno;
|
||||||
ssize_t nr;
|
char ch, *p, *end;
|
||||||
int input, output, save_errno;
|
struct termios term, oterm;
|
||||||
char ch, *p, *end;
|
struct sigaction sa, saveint, savehup, savequit, saveterm;
|
||||||
struct termios term, oterm;
|
struct sigaction savetstp, savettin, savettou;
|
||||||
struct sigaction sa, saveint, savehup, savequit, saveterm;
|
|
||||||
struct sigaction savetstp, savettin, savettou;
|
|
||||||
|
|
||||||
/* I suppose we could alloc on demand in this case (XXX). */
|
/* I suppose we could alloc on demand in this case (XXX). */
|
||||||
if (bufsiz == 0) {
|
if (bufsiz == 0) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return(NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
/*
|
/*
|
||||||
* Read and write to /dev/tty if available. If not, read from
|
* Read and write to /dev/tty if available. If not, read from
|
||||||
* stdin and write to stderr unless a tty is required.
|
* stdin and write to stderr unless a tty is required.
|
||||||
*/
|
*/
|
||||||
if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) {
|
if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) {
|
||||||
if (flags & RPP_REQUIRE_TTY) {
|
if (flags & RPP_REQUIRE_TTY) {
|
||||||
errno = ENOTTY;
|
errno = ENOTTY;
|
||||||
return(NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
input = STDIN_FILENO;
|
input = STDIN_FILENO;
|
||||||
output = STDERR_FILENO;
|
output = STDERR_FILENO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Catch signals that would otherwise cause the user to end
|
* Catch signals that would otherwise cause the user to end
|
||||||
* up with echo turned off in the shell. Don't worry about
|
* up with echo turned off in the shell. Don't worry about
|
||||||
* things like SIGALRM and SIGPIPE for now.
|
* things like SIGALRM and SIGPIPE for now.
|
||||||
*/
|
*/
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = 0; /* don't restart system calls */
|
sa.sa_flags = 0; /* don't restart system calls */
|
||||||
sa.sa_handler = handler;
|
sa.sa_handler = handler;
|
||||||
(void)sigaction(SIGINT, &sa, &saveint);
|
(void)sigaction(SIGINT, &sa, &saveint);
|
||||||
(void)sigaction(SIGHUP, &sa, &savehup);
|
(void)sigaction(SIGHUP, &sa, &savehup);
|
||||||
(void)sigaction(SIGQUIT, &sa, &savequit);
|
(void)sigaction(SIGQUIT, &sa, &savequit);
|
||||||
(void)sigaction(SIGTERM, &sa, &saveterm);
|
(void)sigaction(SIGTERM, &sa, &saveterm);
|
||||||
(void)sigaction(SIGTSTP, &sa, &savetstp);
|
(void)sigaction(SIGTSTP, &sa, &savetstp);
|
||||||
(void)sigaction(SIGTTIN, &sa, &savettin);
|
(void)sigaction(SIGTTIN, &sa, &savettin);
|
||||||
(void)sigaction(SIGTTOU, &sa, &savettou);
|
(void)sigaction(SIGTTOU, &sa, &savettou);
|
||||||
|
|
||||||
/* Turn off echo if possible. */
|
/* Turn off echo if possible. */
|
||||||
if (tcgetattr(input, &oterm) == 0) {
|
if (tcgetattr(input, &oterm) == 0) {
|
||||||
memcpy(&term, &oterm, sizeof(term));
|
memcpy(&term, &oterm, sizeof(term));
|
||||||
if (!(flags & RPP_ECHO_ON))
|
if (!(flags & RPP_ECHO_ON)) term.c_lflag &= ~(ECHO | ECHONL);
|
||||||
term.c_lflag &= ~(ECHO | ECHONL);
|
|
||||||
#ifdef VSTATUS
|
#ifdef VSTATUS
|
||||||
if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
|
if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
|
||||||
term.c_cc[VSTATUS] = _POSIX_VDISABLE;
|
term.c_cc[VSTATUS] = _POSIX_VDISABLE;
|
||||||
#endif
|
#endif
|
||||||
(void)tcsetattr(input, _T_FLUSH, &term);
|
(void)tcsetattr(input, _T_FLUSH, &term);
|
||||||
} else {
|
} else {
|
||||||
memset(&term, 0, sizeof(term));
|
memset(&term, 0, sizeof(term));
|
||||||
memset(&oterm, 0, sizeof(oterm));
|
memset(&oterm, 0, sizeof(oterm));
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)write(output, prompt, strlen(prompt));
|
(void)write(output, prompt, strlen(prompt));
|
||||||
end = buf + bufsiz - 1;
|
end = buf + bufsiz - 1;
|
||||||
for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) {
|
for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) {
|
||||||
if (p < end) {
|
if (p < end) {
|
||||||
if ((flags & RPP_SEVENBIT))
|
if ((flags & RPP_SEVENBIT)) ch &= 0x7f;
|
||||||
ch &= 0x7f;
|
if (isalpha(ch)) {
|
||||||
if (isalpha(ch)) {
|
if ((flags & RPP_FORCELOWER)) ch = tolower(ch);
|
||||||
if ((flags & RPP_FORCELOWER))
|
if ((flags & RPP_FORCEUPPER)) ch = toupper(ch);
|
||||||
ch = tolower(ch);
|
}
|
||||||
if ((flags & RPP_FORCEUPPER))
|
*p++ = ch;
|
||||||
ch = toupper(ch);
|
}
|
||||||
}
|
}
|
||||||
*p++ = ch;
|
*p = '\0';
|
||||||
}
|
save_errno = errno;
|
||||||
}
|
if (!(term.c_lflag & ECHO)) (void)write(output, "\n", 1);
|
||||||
*p = '\0';
|
|
||||||
save_errno = errno;
|
|
||||||
if (!(term.c_lflag & ECHO))
|
|
||||||
(void)write(output, "\n", 1);
|
|
||||||
|
|
||||||
/* Restore old terminal settings and signals. */
|
/* Restore old terminal settings and signals. */
|
||||||
if (memcmp(&term, &oterm, sizeof(term)) != 0)
|
if (memcmp(&term, &oterm, sizeof(term)) != 0)
|
||||||
(void)tcsetattr(input, _T_FLUSH, &oterm);
|
(void)tcsetattr(input, _T_FLUSH, &oterm);
|
||||||
(void)sigaction(SIGINT, &saveint, NULL);
|
(void)sigaction(SIGINT, &saveint, NULL);
|
||||||
(void)sigaction(SIGHUP, &savehup, NULL);
|
(void)sigaction(SIGHUP, &savehup, NULL);
|
||||||
(void)sigaction(SIGQUIT, &savequit, NULL);
|
(void)sigaction(SIGQUIT, &savequit, NULL);
|
||||||
(void)sigaction(SIGTERM, &saveterm, NULL);
|
(void)sigaction(SIGTERM, &saveterm, NULL);
|
||||||
(void)sigaction(SIGTSTP, &savetstp, NULL);
|
(void)sigaction(SIGTSTP, &savetstp, NULL);
|
||||||
(void)sigaction(SIGTTIN, &savettin, NULL);
|
(void)sigaction(SIGTTIN, &savettin, NULL);
|
||||||
(void)sigaction(SIGTTOU, &savettou, NULL);
|
(void)sigaction(SIGTTOU, &savettou, NULL);
|
||||||
if (input != STDIN_FILENO)
|
if (input != STDIN_FILENO) (void)close(input);
|
||||||
(void)close(input);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we were interrupted by a signal, resend it to ourselves
|
* If we were interrupted by a signal, resend it to ourselves
|
||||||
* now that we have restored the signal handlers.
|
* now that we have restored the signal handlers.
|
||||||
*/
|
*/
|
||||||
if (signo) {
|
if (signo) {
|
||||||
kill(getpid(), signo);
|
kill(getpid(), signo);
|
||||||
switch (signo) {
|
switch (signo) {
|
||||||
case SIGTSTP:
|
case SIGTSTP:
|
||||||
case SIGTTIN:
|
case SIGTTIN:
|
||||||
case SIGTTOU:
|
case SIGTTOU:
|
||||||
signo = 0;
|
signo = 0;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
return(nr == -1 ? NULL : buf);
|
return (nr == -1 ? NULL : buf);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_READPASSPHRASE */
|
#endif /* HAVE_READPASSPHRASE */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
char *
|
char *
|
||||||
getpass(const char *prompt)
|
getpass(const char *prompt)
|
||||||
@ -188,8 +182,4 @@ getpass(const char *prompt)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void handler(int s)
|
static void handler(int s) { signo = s; }
|
||||||
{
|
|
||||||
|
|
||||||
signo = s;
|
|
||||||
}
|
|
||||||
|
765
encfs/test.cpp
765
encfs/test.cpp
@ -47,491 +47,398 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace rel;
|
using namespace rel;
|
||||||
using namespace rlog;
|
using namespace rlog;
|
||||||
|
|
||||||
const int FSBlockSize = 256;
|
const int FSBlockSize = 256;
|
||||||
|
|
||||||
static
|
static int checkErrorPropogation(const shared_ptr<Cipher> &cipher, int size,
|
||||||
int checkErrorPropogation( const shared_ptr<Cipher> &cipher,
|
int byteToChange, const CipherKey &key) {
|
||||||
int size, int byteToChange, const CipherKey &key )
|
MemBlock orig = MemoryPool::allocate(size);
|
||||||
{
|
MemBlock data = MemoryPool::allocate(size);
|
||||||
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();
|
||||||
unsigned char tmp = rand();
|
orig.data[i] = tmp;
|
||||||
orig.data[i] = tmp;
|
data.data[i] = tmp;
|
||||||
data.data[i] = tmp;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(size != FSBlockSize)
|
if (size != FSBlockSize)
|
||||||
cipher->streamEncode( data.data, size, 0, key );
|
cipher->streamEncode(data.data, size, 0, key);
|
||||||
else
|
else
|
||||||
cipher->blockEncode( data.data, size, 0, key );
|
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)
|
|
||||||
{
|
|
||||||
unsigned char previousValue = data.data[byteToChange];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
data.data[byteToChange] = rand();
|
|
||||||
} while(data.data[byteToChange] == previousValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(size != FSBlockSize)
|
// intoduce an error in the encoded data, so we can check error propogation
|
||||||
cipher->streamDecode( data.data, size, 0, key );
|
if (byteToChange >= 0 && byteToChange < size) {
|
||||||
else
|
unsigned char previousValue = data.data[byteToChange];
|
||||||
cipher->blockDecode( data.data, size, 0, key );
|
do {
|
||||||
|
data.data[byteToChange] = rand();
|
||||||
|
} while (data.data[byteToChange] == previousValue);
|
||||||
|
}
|
||||||
|
|
||||||
int numByteErrors = 0;
|
if (size != FSBlockSize)
|
||||||
for(int i=0; i<size; ++i)
|
cipher->streamDecode(data.data, size, 0, key);
|
||||||
{
|
else
|
||||||
if( data.data[i] != orig.data[i] )
|
cipher->blockDecode(data.data, size, 0, key);
|
||||||
++numByteErrors;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryPool::release( data );
|
int numByteErrors = 0;
|
||||||
MemoryPool::release( orig );
|
for (int i = 0; i < size; ++i) {
|
||||||
|
if (data.data[i] != orig.data[i]) ++numByteErrors;
|
||||||
|
}
|
||||||
|
|
||||||
return numByteErrors;
|
MemoryPool::release(data);
|
||||||
|
MemoryPool::release(orig);
|
||||||
|
|
||||||
|
return numByteErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char TEST_ROOTDIR[] = "/foo";
|
const char TEST_ROOTDIR[] = "/foo";
|
||||||
|
|
||||||
static
|
static bool testNameCoding(DirNode &dirNode, bool verbose) {
|
||||||
bool testNameCoding( DirNode &dirNode, bool verbose )
|
// encrypt a name
|
||||||
{
|
const char *name[] = {
|
||||||
// encrypt a name
|
"1234567", "12345678", "123456789",
|
||||||
const char *name[] = {
|
"123456789ABCDEF", "123456789ABCDEF0", "123456789ABCDEF01",
|
||||||
"1234567",
|
"test-name", "test-name2", "test",
|
||||||
"12345678",
|
"../test", "/foo/bar/blah", "test-name.21",
|
||||||
"123456789",
|
"test-name.22", "test-name.o", "1.test",
|
||||||
"123456789ABCDEF",
|
"2.test", "a/b/c/d", "a/c/d/e",
|
||||||
"123456789ABCDEF0",
|
"b/c/d/e", "b/a/c/d", NULL};
|
||||||
"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;
|
const char **orig = name;
|
||||||
while(*orig)
|
while (*orig) {
|
||||||
{
|
if (verbose) cerr << " coding name \"" << *orig << "\"";
|
||||||
if(verbose)
|
|
||||||
cerr << " coding name \"" << *orig << "\"";
|
|
||||||
|
|
||||||
string encName = dirNode.relativeCipherPath( *orig );
|
string encName = dirNode.relativeCipherPath(*orig);
|
||||||
|
|
||||||
if(verbose)
|
if (verbose) cerr << " -> \"" << encName.c_str() << "\"";
|
||||||
cerr << " -> \"" << encName.c_str() << "\"";
|
|
||||||
|
|
||||||
// decrypt name
|
// decrypt name
|
||||||
string decName = dirNode.plainPath( encName.c_str() );
|
string decName = dirNode.plainPath(encName.c_str());
|
||||||
|
|
||||||
if(decName == *orig)
|
if (decName == *orig) {
|
||||||
{
|
if (verbose) cerr << " OK\n";
|
||||||
if(verbose)
|
} else {
|
||||||
cerr << " OK\n";
|
if (verbose) cerr << " FAILED (got " << decName << ")\n";
|
||||||
} else
|
return false;
|
||||||
{
|
|
||||||
if(verbose)
|
|
||||||
cerr << " FAILED (got " << decName << ")\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
orig++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
orig++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
|
||||||
{
|
// create a random key
|
||||||
// create a random key
|
if (verbose)
|
||||||
if(verbose)
|
cerr << "Generating new key, output will be different on each run\n\n";
|
||||||
cerr << "Generating new key, output will be different on each run\n\n";
|
CipherKey key = cipher->newRandomKey();
|
||||||
CipherKey key = cipher->newRandomKey();
|
|
||||||
|
|
||||||
if(verbose)
|
if (verbose) cerr << "Testing key save / restore :";
|
||||||
cerr << "Testing key save / restore :";
|
{
|
||||||
{
|
CipherKey encodingKey = cipher->newRandomKey();
|
||||||
CipherKey encodingKey = cipher->newRandomKey();
|
int encodedKeySize = cipher->encodedKeySize();
|
||||||
int encodedKeySize = cipher->encodedKeySize();
|
unsigned char *keyBuf = new unsigned char[encodedKeySize];
|
||||||
unsigned char *keyBuf = new unsigned char [ encodedKeySize ];
|
|
||||||
|
|
||||||
cipher->writeKey( key, keyBuf, encodingKey );
|
cipher->writeKey(key, keyBuf, encodingKey);
|
||||||
CipherKey key2 = cipher->readKey( keyBuf, encodingKey );
|
CipherKey key2 = cipher->readKey(keyBuf, encodingKey);
|
||||||
if(!key2)
|
if (!key2) {
|
||||||
{
|
if (verbose) cerr << " FAILED (decode error)\n";
|
||||||
if(verbose)
|
return false;
|
||||||
cerr << " FAILED (decode error)\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 :";
|
|
||||||
{
|
|
||||||
CipherKey encodingKey = cipher->newRandomKey();
|
|
||||||
int encodedKeySize = cipher->encodedKeySize();
|
|
||||||
unsigned char *keyBuf = new unsigned char [ encodedKeySize ];
|
|
||||||
|
|
||||||
cipher->writeKey( key, keyBuf, encodingKey );
|
|
||||||
|
|
||||||
// store in config struct..
|
|
||||||
EncFSConfig cfg;
|
|
||||||
cfg.cipherIface = cipher->interface();
|
|
||||||
cfg.keySize = 8 * cipher->keySize();
|
|
||||||
cfg.blockSize = FSBlockSize;
|
|
||||||
cfg.assignKeyData( keyBuf, encodedKeySize );
|
|
||||||
|
|
||||||
// save config
|
|
||||||
string data;
|
|
||||||
{
|
|
||||||
ostringstream st;
|
|
||||||
st << cfg;
|
|
||||||
data = st.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// read back in and check everything..
|
|
||||||
EncFSConfig cfg2;
|
|
||||||
{
|
|
||||||
istringstream st(data);
|
|
||||||
st >> cfg2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check..
|
|
||||||
rAssert( cfg.cipherIface.implements(cfg2.cipherIface) );
|
|
||||||
rAssert( cfg.keySize == cfg2.keySize );
|
|
||||||
rAssert( cfg.blockSize == cfg2.blockSize );
|
|
||||||
|
|
||||||
// try decoding key..
|
|
||||||
|
|
||||||
CipherKey key2 = cipher->readKey( cfg2.getKeyData(), encodingKey );
|
|
||||||
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";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FSConfigPtr fsCfg = FSConfigPtr(new FSConfig);
|
if (cipher->compareKey(key, key2)) {
|
||||||
fsCfg->cipher = cipher;
|
if (verbose) cerr << " OK\n";
|
||||||
fsCfg->key = key;
|
} else {
|
||||||
fsCfg->config.reset(new EncFSConfig);
|
if (verbose) cerr << " FAILED\n";
|
||||||
fsCfg->config->blockSize = FSBlockSize;
|
return false;
|
||||||
|
|
||||||
if(verbose)
|
|
||||||
cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
|
|
||||||
{
|
|
||||||
fsCfg->opts.reset(new EncFS_Opts);
|
|
||||||
fsCfg->opts->idleTracking = false;
|
|
||||||
fsCfg->config->uniqueIV = false;
|
|
||||||
|
|
||||||
fsCfg->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(verbose)
|
|
||||||
cerr << "Testing name encode/decode (block coding w/ IV chaining)\n";
|
if (verbose) cerr << "Testing Config interface load / store :";
|
||||||
|
{
|
||||||
|
CipherKey encodingKey = cipher->newRandomKey();
|
||||||
|
int encodedKeySize = cipher->encodedKeySize();
|
||||||
|
unsigned char *keyBuf = new unsigned char[encodedKeySize];
|
||||||
|
|
||||||
|
cipher->writeKey(key, keyBuf, encodingKey);
|
||||||
|
|
||||||
|
// store in config struct..
|
||||||
|
EncFSConfig cfg;
|
||||||
|
cfg.cipherIface = cipher->interface();
|
||||||
|
cfg.keySize = 8 * cipher->keySize();
|
||||||
|
cfg.blockSize = FSBlockSize;
|
||||||
|
cfg.assignKeyData(keyBuf, encodedKeySize);
|
||||||
|
|
||||||
|
// save config
|
||||||
|
string data;
|
||||||
{
|
{
|
||||||
fsCfg->opts->idleTracking = false;
|
ostringstream st;
|
||||||
fsCfg->config->uniqueIV = false;
|
st << cfg;
|
||||||
fsCfg->nameCoding.reset( new BlockNameIO(
|
data = st.str();
|
||||||
BlockNameIO::CurrentInterface(), cipher, key,
|
|
||||||
cipher->cipherBlockSize() ) );
|
|
||||||
fsCfg->nameCoding->setChainedNameIV( true );
|
|
||||||
|
|
||||||
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
|
||||||
|
|
||||||
if(!testNameCoding( dirNode, verbose ))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(verbose)
|
|
||||||
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,
|
|
||||||
cipher->cipherBlockSize(), true ) );
|
|
||||||
fsCfg->nameCoding->setChainedNameIV( true );
|
|
||||||
|
|
||||||
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
|
||||||
|
|
||||||
if(!testNameCoding( dirNode, verbose ))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!verbose)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
// test stream mode, this time without IV chaining
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// test block mode, this time without IV chaining
|
|
||||||
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(verbose)
|
// read back in and check everything..
|
||||||
cerr << "Testing block encode/decode on full block - ";
|
EncFSConfig cfg2;
|
||||||
{
|
{
|
||||||
int numErrors = checkErrorPropogation( cipher,
|
istringstream st(data);
|
||||||
FSBlockSize, -1, key );
|
st >> cfg2;
|
||||||
if(numErrors)
|
|
||||||
{
|
|
||||||
if(verbose)
|
|
||||||
cerr << " FAILED!\n";
|
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
if(verbose)
|
|
||||||
cerr << " OK\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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";
|
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
if(verbose)
|
|
||||||
cerr << " OK\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose)
|
// check..
|
||||||
cerr << "Checking error propogation in partial block:\n";
|
rAssert(cfg.cipherIface.implements(cfg2.cipherIface));
|
||||||
{
|
rAssert(cfg.keySize == cfg2.keySize);
|
||||||
int minChanges = FSBlockSize-1;
|
rAssert(cfg.blockSize == cfg2.blockSize);
|
||||||
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 );
|
|
||||||
|
|
||||||
if(numErrors < minChanges)
|
// try decoding key..
|
||||||
{
|
|
||||||
minChanges = numErrors;
|
|
||||||
minAt = i;
|
|
||||||
}
|
|
||||||
if(numErrors > maxChanges)
|
|
||||||
{
|
|
||||||
maxChanges = numErrors;
|
|
||||||
maxAt = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(verbose)
|
CipherKey key2 = cipher->readKey(cfg2.getKeyData(), encodingKey);
|
||||||
{
|
if (!key2) {
|
||||||
cerr << "modification of 1 byte affected between " << minChanges
|
if (verbose) cerr << " FAILED (decode error)\n";
|
||||||
<< " and " << maxChanges << " decoded bytes\n";
|
return false;
|
||||||
cerr << "minimum change at byte " << minAt
|
|
||||||
<< " and maximum at byte " << maxAt << "\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 );
|
|
||||||
|
|
||||||
if(numErrors < minChanges)
|
|
||||||
{
|
|
||||||
minChanges = numErrors;
|
|
||||||
minAt = i;
|
|
||||||
}
|
|
||||||
if(numErrors > maxChanges)
|
|
||||||
{
|
|
||||||
maxChanges = numErrors;
|
|
||||||
maxAt = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (cipher->compareKey(key, key2)) {
|
||||||
|
if (verbose) cerr << " OK\n";
|
||||||
|
} else {
|
||||||
|
if (verbose) cerr << " FAILED\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FSConfigPtr fsCfg = FSConfigPtr(new FSConfig);
|
||||||
|
fsCfg->cipher = cipher;
|
||||||
|
fsCfg->key = key;
|
||||||
|
fsCfg->config.reset(new EncFSConfig);
|
||||||
|
fsCfg->config->blockSize = FSBlockSize;
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
|
||||||
|
{
|
||||||
|
fsCfg->opts.reset(new EncFS_Opts);
|
||||||
|
fsCfg->opts->idleTracking = false;
|
||||||
|
fsCfg->config->uniqueIV = false;
|
||||||
|
|
||||||
|
fsCfg->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 (verbose)
|
||||||
|
cerr << "Testing name encode/decode (block coding w/ IV chaining)\n";
|
||||||
|
{
|
||||||
|
fsCfg->opts->idleTracking = false;
|
||||||
|
fsCfg->config->uniqueIV = false;
|
||||||
|
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 (verbose)
|
||||||
|
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,
|
||||||
|
cipher->cipherBlockSize(), true));
|
||||||
|
fsCfg->nameCoding->setChainedNameIV(true);
|
||||||
|
|
||||||
|
DirNode dirNode(NULL, TEST_ROOTDIR, fsCfg);
|
||||||
|
|
||||||
|
if (!testNameCoding(dirNode, verbose)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!verbose) {
|
||||||
|
{
|
||||||
|
// test stream mode, this time without IV chaining
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// test block mode, this time without IV chaining
|
||||||
|
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 (verbose) cerr << "Testing block encode/decode on full block - ";
|
||||||
|
{
|
||||||
|
int numErrors = checkErrorPropogation(cipher, FSBlockSize, -1, key);
|
||||||
|
if (numErrors) {
|
||||||
|
if (verbose) cerr << " FAILED!\n";
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (verbose) cerr << " OK\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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";
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (verbose) cerr << " OK\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);
|
||||||
|
|
||||||
|
if (numErrors < minChanges) {
|
||||||
|
minChanges = numErrors;
|
||||||
|
minAt = i;
|
||||||
|
}
|
||||||
|
if (numErrors > maxChanges) {
|
||||||
|
maxChanges = numErrors;
|
||||||
|
maxAt = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (numErrors < minChanges) {
|
||||||
|
minChanges = numErrors;
|
||||||
|
minAt = i;
|
||||||
|
}
|
||||||
|
if (numErrors > maxChanges) {
|
||||||
|
maxChanges = numErrors;
|
||||||
|
maxAt = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
RLogInit(argc, argv);
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
StdioNode stdLog(STDERR_FILENO);
|
||||||
{
|
stdLog.subscribeTo(RLOG_CHANNEL("error"));
|
||||||
RLogInit( argc, argv );
|
stdLog.subscribeTo(RLOG_CHANNEL("warning"));
|
||||||
|
|
||||||
StdioNode stdLog( STDERR_FILENO );
|
|
||||||
stdLog.subscribeTo( RLOG_CHANNEL("error") );
|
|
||||||
stdLog.subscribeTo( RLOG_CHANNEL("warning") );
|
|
||||||
#ifndef NO_DEBUG
|
#ifndef NO_DEBUG
|
||||||
stdLog.subscribeTo( RLOG_CHANNEL("debug") );
|
stdLog.subscribeTo(RLOG_CHANNEL("debug"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
ENGINE_load_builtin_engines();
|
ENGINE_load_builtin_engines();
|
||||||
ENGINE_register_all_ciphers();
|
ENGINE_register_all_ciphers();
|
||||||
ENGINE_register_all_digests();
|
ENGINE_register_all_digests();
|
||||||
ENGINE_register_all_RAND();
|
ENGINE_register_all_RAND();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
srand( time(0) );
|
srand(time(0));
|
||||||
|
|
||||||
// get a list of the available algorithms
|
// get a list of the available algorithms
|
||||||
std::list<Cipher::CipherAlgorithm> algorithms =
|
std::list<Cipher::CipherAlgorithm> algorithms = Cipher::GetAlgorithmList();
|
||||||
Cipher::GetAlgorithmList();
|
std::list<Cipher::CipherAlgorithm>::const_iterator it;
|
||||||
std::list<Cipher::CipherAlgorithm>::const_iterator it;
|
cerr << "Supported Crypto interfaces:\n";
|
||||||
cerr << "Supported Crypto interfaces:\n";
|
for (it = algorithms.begin(); it != algorithms.end(); ++it) {
|
||||||
for(it = algorithms.begin(); it != algorithms.end(); ++it)
|
cerr << it->name << " ( " << it->iface.name() << " " << it->iface.current()
|
||||||
{
|
<< ":" << it->iface.revision() << ":" << it->iface.age()
|
||||||
cerr << it->name
|
<< " ) : " << it->description << "\n";
|
||||||
<< " ( " << it->iface.name() << " "
|
cerr << " - key length " << it->keyLength.min() << " to "
|
||||||
<< it->iface.current() << ":"
|
<< it->keyLength.max() << " , block size " << it->blockSize.min()
|
||||||
<< it->iface.revision() << ":"
|
<< " to " << it->blockSize.max() << "\n";
|
||||||
<< it->iface.age() << " ) : " << it->description << "\n";
|
}
|
||||||
cerr << " - key length " << it->keyLength.min() << " to "
|
cerr << "\n";
|
||||||
<< it->keyLength.max() << " , block size " << it->blockSize.min()
|
|
||||||
<< " to " << it->blockSize.max() << "\n";
|
cerr << "Testing interfaces\n";
|
||||||
|
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 << ": ";
|
||||||
|
|
||||||
|
shared_ptr<Cipher> cipher = Cipher::New(it->name, keySize);
|
||||||
|
if (!cipher) {
|
||||||
|
cerr << "FAILED TO CREATE\n";
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if (runTests(cipher, false))
|
||||||
|
cerr << "OK\n";
|
||||||
|
else
|
||||||
|
cerr << "FAILED\n";
|
||||||
|
}
|
||||||
|
catch (rlog::Error &er) {
|
||||||
|
cerr << "Error: " << er.what() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cerr << "\n";
|
}
|
||||||
|
|
||||||
cerr << "Testing interfaces\n";
|
// run one test with verbose output too..
|
||||||
for(it = algorithms.begin(); it != algorithms.end(); ++it)
|
shared_ptr<Cipher> cipher = Cipher::New("AES", 192);
|
||||||
{
|
if (!cipher) {
|
||||||
int blockSize = it->blockSize.closest( 256 );
|
cerr << "\nNo AES cipher found, skipping verbose test.\n";
|
||||||
for(int keySize = it->keyLength.min(); keySize <= it->keyLength.max();
|
} else {
|
||||||
keySize += it->keyLength.inc())
|
cerr << "\nVerbose output for " << cipher->interface().name()
|
||||||
{
|
<< " test, key length " << cipher->keySize() * 8 << ", block size "
|
||||||
cerr << it->name << ", key length " << keySize
|
<< FSBlockSize << ":\n";
|
||||||
<< ", block size " << blockSize << ": ";
|
|
||||||
|
|
||||||
shared_ptr<Cipher> cipher = Cipher::New( it->name, keySize );
|
runTests(cipher, true);
|
||||||
if(!cipher)
|
}
|
||||||
{
|
|
||||||
cerr << "FAILED TO CREATE\n";
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(runTests( cipher, false ))
|
|
||||||
cerr << "OK\n";
|
|
||||||
else
|
|
||||||
cerr << "FAILED\n";
|
|
||||||
} catch( rlog::Error &er )
|
|
||||||
{
|
|
||||||
cerr << "Error: " << er.what() << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// run one test with verbose output too..
|
MemoryPool::destroyAll();
|
||||||
shared_ptr<Cipher> cipher = Cipher::New("AES", 192);
|
|
||||||
if(!cipher)
|
|
||||||
{
|
|
||||||
cerr << "\nNo AES cipher found, skipping verbose test.\n";
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
cerr << "\nVerbose output for " << cipher->interface().name()
|
|
||||||
<< " test, key length " << cipher->keySize()*8 << ", block size "
|
|
||||||
<< FSBlockSize << ":\n";
|
|
||||||
|
|
||||||
runTests( cipher, true );
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
MemoryPool::destroyAll();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user