Merge pull request #364 from vgough/lint-fixes

Lots of lint fixes from clang-tidy
This commit is contained in:
Valient Gough 2017-08-04 00:03:45 -07:00 committed by GitHub
commit cb954aeae5
49 changed files with 1196 additions and 833 deletions

View File

@ -146,7 +146,8 @@ if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.5) # Need 3.6 or abo
message(STATUS "clang-tidy not found.") message(STATUS "clang-tidy not found.")
else() else()
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-checks=*,-clang-analyzer-alpha.*") set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-checks=*,-modernize-loop-convert,-cppcoreguidelines-pro-*,-readability-inconsistent-declaration-parameter-name,-google-readability-casting,-cert-err58-cpp,-google-runtime-int,-readability-named-parameter,-google-build-using-namespace,-misc-unused-parameters,-google-runtime-references")
#set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-fix" "-checks=-*,google-readability-redundant-smartptr-get")
endif() endif()
endif() endif()

View File

@ -67,31 +67,34 @@ ssize_t BlockFileIO::cacheReadOneBlock(const IORequest &req) const {
* in the last block of a file, which may be smaller than the blocksize. * in the last block of a file, which may be smaller than the blocksize.
* For reverse encryption, the cache must not be used at all, because * For reverse encryption, the cache must not be used at all, because
* the lower file may have changed behind our back. */ * the lower file may have changed behind our back. */
if ((_noCache == false) && (req.offset == _cache.offset) && if ((!_noCache) && (req.offset == _cache.offset) && (_cache.dataLen != 0)) {
(_cache.dataLen != 0)) {
// satisfy request from cache // satisfy request from cache
int len = req.dataLen; int len = req.dataLen;
if (_cache.dataLen < len) len = _cache.dataLen; // Don't read past EOF if (_cache.dataLen < len) {
len = _cache.dataLen; // Don't read past EOF
}
memcpy(req.data, _cache.data, len); memcpy(req.data, _cache.data, len);
return len; return len;
} else {
if (_cache.dataLen > 0) clearCache(_cache, _blockSize);
// cache results of read -- issue reads for full blocks
IORequest tmp;
tmp.offset = req.offset;
tmp.data = _cache.data;
tmp.dataLen = _blockSize;
ssize_t result = readOneBlock(tmp);
if (result > 0) {
_cache.offset = req.offset;
_cache.dataLen = result; // the amount we really have
if (result > req.dataLen)
result = req.dataLen; // only as much as requested
memcpy(req.data, _cache.data, result);
}
return result;
} }
if (_cache.dataLen > 0) {
clearCache(_cache, _blockSize);
}
// cache results of read -- issue reads for full blocks
IORequest tmp;
tmp.offset = req.offset;
tmp.data = _cache.data;
tmp.dataLen = _blockSize;
ssize_t result = readOneBlock(tmp);
if (result > 0) {
_cache.offset = req.offset;
_cache.dataLen = result; // the amount we really have
if (result > req.dataLen) {
result = req.dataLen; // only as much as requested
}
memcpy(req.data, _cache.data, result);
}
return result;
} }
bool BlockFileIO::cacheWriteOneBlock(const IORequest &req) { bool BlockFileIO::cacheWriteOneBlock(const IORequest &req) {
@ -101,7 +104,9 @@ bool BlockFileIO::cacheWriteOneBlock(const IORequest &req) {
_cache.offset = req.offset; _cache.offset = req.offset;
_cache.dataLen = req.dataLen; _cache.dataLen = req.dataLen;
bool ok = writeOneBlock(req); bool ok = writeOneBlock(req);
if (!ok) clearCache(_cache, _blockSize); if (!ok) {
clearCache(_cache, _blockSize);
}
return ok; return ok;
} }
@ -123,49 +128,57 @@ ssize_t BlockFileIO::read(const IORequest &req) const {
// read completely within a single block -- can be handled as-is by // read completely within a single block -- can be handled as-is by
// readOneBlock(). // readOneBlock().
return cacheReadOneBlock(req); return cacheReadOneBlock(req);
} else { }
size_t size = req.dataLen; size_t size = req.dataLen;
// if the request is larger then a block, then request each block // if the request is larger then a block, then request each block
// individually // individually
MemBlock mb; // in case we need to allocate a temporary block.. MemBlock mb; // in case we need to allocate a temporary block..
IORequest blockReq; // for requests we may need to make IORequest blockReq; // for requests we may need to make
blockReq.dataLen = _blockSize; blockReq.dataLen = _blockSize;
blockReq.data = NULL; blockReq.data = nullptr;
unsigned char *out = req.data; unsigned char *out = req.data;
while (size) { while (size != 0u) {
blockReq.offset = blockNum * _blockSize; blockReq.offset = blockNum * _blockSize;
// if we're reading a full block, then read directly into the // if we're reading a full block, then read directly into the
// result buffer instead of using a temporary // result buffer instead of using a temporary
if (partialOffset == 0 && size >= (size_t)_blockSize) if (partialOffset == 0 && size >= (size_t)_blockSize) {
blockReq.data = out; blockReq.data = out;
else { } else {
if (!mb.data) mb = MemoryPool::allocate(_blockSize); if (mb.data == nullptr) {
blockReq.data = mb.data; mb = MemoryPool::allocate(_blockSize);
} }
blockReq.data = mb.data;
ssize_t readSize = cacheReadOneBlock(blockReq);
if (readSize <= partialOffset) break; // didn't get enough bytes
int cpySize = min((size_t)(readSize - partialOffset), size);
CHECK(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 (readSize < _blockSize) break;
} }
if (mb.data) MemoryPool::release(mb); ssize_t readSize = cacheReadOneBlock(blockReq);
if (readSize <= partialOffset) {
break; // didn't get enough bytes
}
int cpySize = min((size_t)(readSize - partialOffset), size);
CHECK(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 (readSize < _blockSize) {
break;
}
}
if (mb.data != nullptr) {
MemoryPool::release(mb);
} }
return result; return result;
@ -175,7 +188,9 @@ bool BlockFileIO::write(const IORequest &req) {
CHECK(_blockSize != 0); CHECK(_blockSize != 0);
off_t fileSize = getSize(); off_t fileSize = getSize();
if (fileSize < 0) return false; if (fileSize < 0) {
return false;
}
// where write request begins // where write request begins
off_t blockNum = req.offset / _blockSize; off_t blockNum = req.offset / _blockSize;
@ -186,7 +201,9 @@ bool BlockFileIO::write(const IORequest &req) {
ssize_t lastBlockSize = fileSize % _blockSize; ssize_t lastBlockSize = fileSize % _blockSize;
off_t lastNonEmptyBlock = lastFileBlock; off_t lastNonEmptyBlock = lastFileBlock;
if (lastBlockSize == 0) --lastNonEmptyBlock; if (lastBlockSize == 0) {
--lastNonEmptyBlock;
}
if (req.offset > fileSize) { if (req.offset > fileSize) {
// extend file first to fill hole with 0's.. // extend file first to fill hole with 0's..
@ -198,25 +215,28 @@ bool BlockFileIO::write(const IORequest &req) {
// request as-is.. // request as-is..
if (partialOffset == 0 && req.dataLen <= _blockSize) { if (partialOffset == 0 && req.dataLen <= _blockSize) {
// if writing a full block.. pretty safe.. // if writing a full block.. pretty safe..
if (req.dataLen == _blockSize) return cacheWriteOneBlock(req); if (req.dataLen == _blockSize) {
return cacheWriteOneBlock(req);
}
// if writing a partial block, but at least as much as what is // if writing a partial block, but at least as much as what is
// already there.. // already there..
if (blockNum == lastFileBlock && req.dataLen >= lastBlockSize) if (blockNum == lastFileBlock && req.dataLen >= lastBlockSize) {
return cacheWriteOneBlock(req); return cacheWriteOneBlock(req);
}
} }
// have to merge data with existing block(s).. // have to merge data with existing block(s)..
MemBlock mb; MemBlock mb;
IORequest blockReq; IORequest blockReq;
blockReq.data = NULL; blockReq.data = nullptr;
blockReq.dataLen = _blockSize; blockReq.dataLen = _blockSize;
bool ok = true; bool ok = true;
size_t size = req.dataLen; size_t size = req.dataLen;
unsigned char *inPtr = req.data; unsigned char *inPtr = req.data;
while (size) { while (size != 0u) {
blockReq.offset = blockNum * _blockSize; blockReq.offset = blockNum * _blockSize;
int toCopy = min((size_t)(_blockSize - partialOffset), size); int toCopy = min((size_t)(_blockSize - partialOffset), size);
@ -230,7 +250,9 @@ bool BlockFileIO::write(const IORequest &req) {
} else { } else {
// need a temporary buffer, since we have to either merge or pad // need a temporary buffer, since we have to either merge or pad
// the data. // the data.
if (!mb.data) mb = MemoryPool::allocate(_blockSize); if (mb.data == nullptr) {
mb = MemoryPool::allocate(_blockSize);
}
memset(mb.data, 0, _blockSize); memset(mb.data, 0, _blockSize);
blockReq.data = mb.data; blockReq.data = mb.data;
@ -243,8 +265,9 @@ bool BlockFileIO::write(const IORequest &req) {
blockReq.dataLen = cacheReadOneBlock(blockReq); blockReq.dataLen = cacheReadOneBlock(blockReq);
// extend data if necessary.. // extend data if necessary..
if (partialOffset + toCopy > blockReq.dataLen) if (partialOffset + toCopy > blockReq.dataLen) {
blockReq.dataLen = partialOffset + toCopy; blockReq.dataLen = partialOffset + toCopy;
}
} }
// merge in the data to be written.. // merge in the data to be written..
memcpy(blockReq.data + partialOffset, inPtr, toCopy); memcpy(blockReq.data + partialOffset, inPtr, toCopy);
@ -263,7 +286,9 @@ bool BlockFileIO::write(const IORequest &req) {
partialOffset = 0; partialOffset = 0;
} }
if (mb.data) MemoryPool::release(mb); if (mb.data != nullptr) {
MemoryPool::release(mb);
}
return ok; return ok;
} }
@ -290,7 +315,7 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
req.dataLen = oldSize % _blockSize; req.dataLen = oldSize % _blockSize;
int outSize = newSize % _blockSize; // outSize > req.dataLen int outSize = newSize % _blockSize; // outSize > req.dataLen
if (outSize) { if (outSize != 0) {
memset(mb.data, 0, outSize); memset(mb.data, 0, outSize);
cacheReadOneBlock(req); cacheReadOneBlock(req);
req.dataLen = outSize; req.dataLen = outSize;
@ -331,7 +356,7 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
} }
// 3. only necessary if write is forced and block is non 0 length // 3. only necessary if write is forced and block is non 0 length
if (forceWrite && newBlockSize) { if (forceWrite && (newBlockSize != 0)) {
req.offset = newLastBlock * _blockSize; req.offset = newLastBlock * _blockSize;
req.dataLen = newBlockSize; req.dataLen = newBlockSize;
memset(mb.data, 0, req.dataLen); memset(mb.data, 0, req.dataLen);
@ -339,7 +364,9 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
} }
} }
if (mb.data) MemoryPool::release(mb); if (mb.data != nullptr) {
MemoryPool::release(mb);
}
} }
int BlockFileIO::truncateBase(off_t size, FileIO *base) { int BlockFileIO::truncateBase(off_t size, FileIO *base) {
@ -353,13 +380,15 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
// states that it will pad with 0's. // states that it will pad with 0's.
// do the truncate so that the underlying filesystem can allocate // do the truncate so that the underlying filesystem can allocate
// the space, and then we'll fill it in padFile.. // the space, and then we'll fill it in padFile..
if (base) base->truncate(size); if (base != nullptr) {
base->truncate(size);
}
const bool forceWrite = true; const bool forceWrite = true;
padFile(oldSize, size, forceWrite); padFile(oldSize, size, forceWrite);
} else if (size == oldSize) { } else if (size == oldSize) {
// the easiest case, but least likely.... // the easiest case, but least likely....
} else if (partialBlock) { } else if (partialBlock != 0) {
// partial block after truncate. Need to read in the block being // partial block after truncate. Need to read in the block being
// truncated before the truncate. Then write it back out afterwards, // truncated before the truncate. Then write it back out afterwards,
// since the encoding will change.. // since the encoding will change..
@ -374,7 +403,9 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
ssize_t rdSz = cacheReadOneBlock(req); ssize_t rdSz = cacheReadOneBlock(req);
// do the truncate // do the truncate
if (base) res = base->truncate(size); if (base != nullptr) {
res = base->truncate(size);
}
// write back out partial block // write back out partial block
req.dataLen = partialBlock; req.dataLen = partialBlock;
@ -390,7 +421,9 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
} else { } else {
// truncating on a block bounday. No need to re-encode the last // truncating on a block bounday. No need to re-encode the last
// block.. // block..
if (base) res = base->truncate(size); if (base != nullptr) {
res = base->truncate(size);
}
} }
return res; return res;

View File

@ -22,6 +22,7 @@
#include <cstring> #include <cstring>
#include <memory> #include <memory>
#include <utility>
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
@ -38,7 +39,9 @@ static std::shared_ptr<NameIO> NewBlockNameIO(
const Interface &iface, const std::shared_ptr<Cipher> &cipher, const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key) { const CipherKey &key) {
int blockSize = 8; int blockSize = 8;
if (cipher) blockSize = cipher->cipherBlockSize(); if (cipher) {
blockSize = cipher->cipherBlockSize();
}
return std::shared_ptr<NameIO>( return std::shared_ptr<NameIO>(
new BlockNameIO(iface, cipher, key, blockSize, false)); new BlockNameIO(iface, cipher, key, blockSize, false));
@ -48,7 +51,9 @@ static std::shared_ptr<NameIO> NewBlockNameIO32(
const Interface &iface, const std::shared_ptr<Cipher> &cipher, const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key) { const CipherKey &key) {
int blockSize = 8; int blockSize = 8;
if (cipher) blockSize = cipher->cipherBlockSize(); if (cipher) {
blockSize = cipher->cipherBlockSize();
}
return std::shared_ptr<NameIO>( return std::shared_ptr<NameIO>(
new BlockNameIO(iface, cipher, key, blockSize, true)); new BlockNameIO(iface, cipher, key, blockSize, true));
@ -88,26 +93,25 @@ static bool BlockIO32_registered = NameIO::Register(
*/ */
Interface BlockNameIO::CurrentInterface(bool caseInsensitive) { Interface BlockNameIO::CurrentInterface(bool caseInsensitive) {
// implement major version 4 plus support for two prior versions // implement major version 4 plus support for two prior versions
if (caseInsensitive) if (caseInsensitive) {
return Interface("nameio/block32", 4, 0, 2); return Interface("nameio/block32", 4, 0, 2);
else }
return Interface("nameio/block", 4, 0, 2); return Interface("nameio/block", 4, 0, 2);
} }
BlockNameIO::BlockNameIO(const Interface &iface, BlockNameIO::BlockNameIO(const Interface &iface, std::shared_ptr<Cipher> cipher,
const std::shared_ptr<Cipher> &cipher, CipherKey key, int blockSize,
const CipherKey &key, int blockSize,
bool caseInsensitiveEncoding) bool caseInsensitiveEncoding)
: _interface(iface.current()), : _interface(iface.current()),
_bs(blockSize), _bs(blockSize),
_cipher(cipher), _cipher(std::move(cipher)),
_key(key), _key(std::move(key)),
_caseInsensitive(caseInsensitiveEncoding) { _caseInsensitive(caseInsensitiveEncoding) {
// just to be safe.. // just to be safe..
rAssert(blockSize < 128); rAssert(blockSize < 128);
} }
BlockNameIO::~BlockNameIO() {} BlockNameIO::~BlockNameIO() = default;
Interface BlockNameIO::interface() const { Interface BlockNameIO::interface() const {
return CurrentInterface(_caseInsensitive); return CurrentInterface(_caseInsensitive);
@ -118,10 +122,10 @@ int BlockNameIO::maxEncodedNameLen(int plaintextNameLen) const {
// the size of too much space rather then too little. // the size of too much space rather then too little.
int numBlocks = (plaintextNameLen + _bs) / _bs; int numBlocks = (plaintextNameLen + _bs) / _bs;
int encodedNameLen = numBlocks * _bs + 2; // 2 checksum bytes int encodedNameLen = numBlocks * _bs + 2; // 2 checksum bytes
if (_caseInsensitive) if (_caseInsensitive) {
return B256ToB32Bytes(encodedNameLen); return B256ToB32Bytes(encodedNameLen);
else }
return B256ToB64Bytes(encodedNameLen); return B256ToB64Bytes(encodedNameLen);
} }
int BlockNameIO::maxDecodedNameLen(int encodedNameLen) const { int BlockNameIO::maxDecodedNameLen(int encodedNameLen) const {
@ -135,7 +139,9 @@ int BlockNameIO::encodeName(const char *plaintextName, int length, uint64_t *iv,
// Pad encryption buffer to block boundary.. // Pad encryption buffer to block boundary..
int padding = _bs - length % _bs; int padding = _bs - length % _bs;
if (padding == 0) padding = _bs; // padding a full extra block! if (padding == 0) {
padding = _bs; // padding a full extra block!
}
rAssert(bufferLength >= length + 2 + padding); rAssert(bufferLength >= length + 2 + padding);
memset(encodedName + length + 2, (unsigned char)padding, padding); memset(encodedName + length + 2, (unsigned char)padding, padding);
@ -145,7 +151,9 @@ int BlockNameIO::encodeName(const char *plaintextName, int length, uint64_t *iv,
// store the IV before it is modified by the MAC call. // store the IV before it is modified by the MAC call.
uint64_t tmpIV = 0; uint64_t tmpIV = 0;
if (iv && _interface >= 3) tmpIV = *iv; if ((iv != nullptr) && _interface >= 3) {
tmpIV = *iv;
}
// include padding in MAC computation // include padding in MAC computation
unsigned int mac = _cipher->MAC_16((unsigned char *)encodedName + 2, unsigned int mac = _cipher->MAC_16((unsigned char *)encodedName + 2,
@ -207,7 +215,9 @@ int BlockNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
((unsigned int)((unsigned char)tmpBuf[1])); ((unsigned int)((unsigned char)tmpBuf[1]));
uint64_t tmpIV = 0; uint64_t tmpIV = 0;
if (iv && _interface >= 3) tmpIV = *iv; if ((iv != nullptr) && _interface >= 3) {
tmpIV = *iv;
}
_cipher->blockDecode((unsigned char *)tmpBuf + 2, decodedStreamLen, _cipher->blockDecode((unsigned char *)tmpBuf + 2, decodedStreamLen,
(uint64_t)mac ^ tmpIV, _key); (uint64_t)mac ^ tmpIV, _key);

View File

@ -41,8 +41,8 @@ class BlockNameIO : public NameIO {
public: public:
static Interface CurrentInterface(bool caseInsensitive = false); static Interface CurrentInterface(bool caseInsensitive = false);
BlockNameIO(const Interface &iface, const std::shared_ptr<Cipher> &cipher, BlockNameIO(const Interface &iface, std::shared_ptr<Cipher> cipher,
const CipherKey &key, int blockSize, CipherKey key, int blockSize,
bool caseInsensitiveEncoding = false); bool caseInsensitiveEncoding = false);
virtual ~BlockNameIO(); virtual ~BlockNameIO();

View File

@ -18,10 +18,10 @@
* 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 <cstddef>
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <map> #include <map>
#include <stddef.h>
#include <string> #include <string>
#include <utility> #include <utility>
@ -56,8 +56,8 @@ struct CipherAlg {
Range blockSize; Range blockSize;
}; };
typedef multimap<string, CipherAlg> CipherMap_t; using CipherMap_t = multimap<string, CipherAlg>;
static CipherMap_t *gCipherMap = NULL; static CipherMap_t *gCipherMap = nullptr;
std::list<Cipher::CipherAlgorithm> Cipher::GetAlgorithmList( std::list<Cipher::CipherAlgorithm> Cipher::GetAlgorithmList(
bool includeHidden) { bool includeHidden) {
@ -65,7 +65,9 @@ std::list<Cipher::CipherAlgorithm> Cipher::GetAlgorithmList(
list<CipherAlgorithm> result; list<CipherAlgorithm> result;
if (!gCipherMap) return result; if (gCipherMap == nullptr) {
return result;
}
CipherMap_t::const_iterator it; CipherMap_t::const_iterator it;
CipherMap_t::const_iterator mapEnd = gCipherMap->end(); CipherMap_t::const_iterator mapEnd = gCipherMap->end();
@ -98,7 +100,9 @@ bool Cipher::Register(const char *name, const char *description,
const Interface &iface, const Range &keyLength, const Interface &iface, const Range &keyLength,
const Range &blockSize, CipherConstructor fn, const Range &blockSize, CipherConstructor fn,
bool hidden) { bool hidden) {
if (!gCipherMap) gCipherMap = new CipherMap_t; if (gCipherMap == nullptr) {
gCipherMap = new CipherMap_t;
}
CipherAlg ca; CipherAlg ca;
ca.hidden = hidden; ca.hidden = hidden;
@ -114,7 +118,7 @@ bool Cipher::Register(const char *name, const char *description,
std::shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) { std::shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
std::shared_ptr<Cipher> result; std::shared_ptr<Cipher> result;
if (gCipherMap) { if (gCipherMap != nullptr) {
CipherMap_t::const_iterator it = gCipherMap->find(name); CipherMap_t::const_iterator it = gCipherMap->find(name);
if (it != gCipherMap->end()) { if (it != gCipherMap->end()) {
CipherConstructor fn = it->second.constructor; CipherConstructor fn = it->second.constructor;
@ -127,7 +131,7 @@ std::shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
} }
std::shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) { std::shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) {
std::shared_ptr<Cipher> result; std::shared_ptr<Cipher> result;
if (gCipherMap) { if (gCipherMap != nullptr) {
CipherMap_t::const_iterator it; CipherMap_t::const_iterator it;
CipherMap_t::const_iterator mapEnd = gCipherMap->end(); CipherMap_t::const_iterator mapEnd = gCipherMap->end();
@ -148,9 +152,9 @@ std::shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) {
return result; return result;
} }
Cipher::Cipher() {} Cipher::Cipher() = default;
Cipher::~Cipher() {} Cipher::~Cipher() = default;
unsigned int Cipher::MAC_32(const unsigned char *src, int len, unsigned int Cipher::MAC_32(const unsigned char *src, int len,
const CipherKey &key, uint64_t *chainedIV) const { const CipherKey &key, uint64_t *chainedIV) const {
@ -184,13 +188,13 @@ bool Cipher::nameDecode(unsigned char *data, int len, uint64_t iv64,
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]; auto *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]; auto *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);

View File

@ -44,8 +44,8 @@ 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 std::shared_ptr<Cipher> (*CipherConstructor)(const Interface &iface, using CipherConstructor = std::shared_ptr<Cipher> (*)(const Interface &iface,
int keyLenBits); int keyLenBits);
struct CipherAlgorithm { struct CipherAlgorithm {
std::string name; std::string name;
@ -55,7 +55,7 @@ class Cipher {
Range blockSize; Range blockSize;
}; };
typedef std::list<CipherAlgorithm> AlgorithmList; using AlgorithmList = std::list<CipherAlgorithm>;
static AlgorithmList GetAlgorithmList(bool includeHidden = false); static AlgorithmList GetAlgorithmList(bool includeHidden = false);
static std::shared_ptr<Cipher> New(const Interface &iface, int keyLen = -1); static std::shared_ptr<Cipher> New(const Interface &iface, int keyLen = -1);

View File

@ -22,12 +22,13 @@
#include "internal/easylogging++.h" #include "internal/easylogging++.h"
#include <cerrno> #include <cerrno>
#include <cinttypes>
#include <cstring>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h>
#include <memory> #include <memory>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <utility>
#include "BlockFileIO.h" #include "BlockFileIO.h"
#include "Cipher.h" #include "Cipher.h"
@ -47,10 +48,10 @@ static 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..
CipherFileIO::CipherFileIO(const std::shared_ptr<FileIO> &_base, CipherFileIO::CipherFileIO(std::shared_ptr<FileIO> _base,
const FSConfigPtr &cfg) const FSConfigPtr &cfg)
: BlockFileIO(cfg->config->blockSize, cfg), : BlockFileIO(cfg->config->blockSize, cfg),
base(_base), base(std::move(_base)),
haveHeader(cfg->config->uniqueIV), haveHeader(cfg->config->uniqueIV),
externalIV(0), externalIV(0),
fileIV(0), fileIV(0),
@ -63,14 +64,16 @@ CipherFileIO::CipherFileIO(const std::shared_ptr<FileIO> &_base,
<< "FS block size must be multiple of cipher block size"; << "FS block size must be multiple of cipher block size";
} }
CipherFileIO::~CipherFileIO() {} CipherFileIO::~CipherFileIO() = default;
Interface CipherFileIO::interface() const { return CipherFileIO_iface; } Interface CipherFileIO::interface() const { return CipherFileIO_iface; }
int CipherFileIO::open(int flags) { int CipherFileIO::open(int flags) {
int res = base->open(flags); int res = base->open(flags);
if (res >= 0) lastFlags = flags; if (res >= 0) {
lastFlags = flags;
}
return res; return res;
} }
@ -104,10 +107,9 @@ bool CipherFileIO::setIV(uint64_t iv) {
// duh -- there are no file headers for directories! // duh -- there are no file headers for directories!
externalIV = iv; externalIV = iv;
return base->setIV(iv); return base->setIV(iv);
} else {
VLOG(1) << "writeHeader failed to re-open for write";
return false;
} }
VLOG(1) << "writeHeader failed to re-open for write";
return false;
} }
initHeader(); initHeader();
} }
@ -188,7 +190,9 @@ void CipherFileIO::initHeader() {
cipher->streamDecode(buf, sizeof(buf), externalIV, key); cipher->streamDecode(buf, sizeof(buf), externalIV, key);
fileIV = 0; fileIV = 0;
for (int i = 0; i < 8; ++i) fileIV = (fileIV << 8) | (uint64_t)buf[i]; for (int i = 0; i < 8; ++i) {
fileIV = (fileIV << 8) | (uint64_t)buf[i];
}
rAssert(fileIV != 0); // 0 is never used.. rAssert(fileIV != 0); // 0 is never used..
} else { } else {
@ -196,14 +200,18 @@ void CipherFileIO::initHeader() {
unsigned char buf[8] = {0}; unsigned char buf[8] = {0};
do { do {
if (!cipher->randomize(buf, 8, false)) if (!cipher->randomize(buf, 8, false)) {
throw Error("Unable to generate a random file IV"); throw Error("Unable to generate a random file IV");
}
fileIV = 0; fileIV = 0;
for (int i = 0; i < 8; ++i) fileIV = (fileIV << 8) | (uint64_t)buf[i]; for (int i = 0; i < 8; ++i) {
fileIV = (fileIV << 8) | (uint64_t)buf[i];
}
if (fileIV == 0) if (fileIV == 0) {
RLOG(WARNING) << "Unexpected result: randomize returned 8 null bytes!"; RLOG(WARNING) << "Unexpected result: randomize returned 8 null bytes!";
}
} while (fileIV == 0); // don't accept 0 as an option.. } while (fileIV == 0); // don't accept 0 as an option..
if (base->isWritable()) { if (base->isWritable()) {
@ -324,8 +332,9 @@ ssize_t CipherFileIO::readOneBlock(const IORequest &req) const {
bool ok; bool ok;
if (readSize > 0) { if (readSize > 0) {
if (haveHeader && fileIV == 0) if (haveHeader && fileIV == 0) {
const_cast<CipherFileIO *>(this)->initHeader(); const_cast<CipherFileIO *>(this)->initHeader();
}
if (readSize != bs) { if (readSize != bs) {
VLOG(1) << "streamRead(data, " << readSize << ", IV)"; VLOG(1) << "streamRead(data, " << readSize << ", IV)";
@ -357,7 +366,9 @@ bool CipherFileIO::writeOneBlock(const IORequest &req) {
int bs = blockSize(); int bs = blockSize();
off_t blockNum = req.offset / bs; off_t blockNum = req.offset / bs;
if (haveHeader && fileIV == 0) initHeader(); if (haveHeader && fileIV == 0) {
initHeader();
}
bool ok; bool ok;
if (req.dataLen != bs) { if (req.dataLen != bs) {
@ -371,8 +382,9 @@ bool CipherFileIO::writeOneBlock(const IORequest &req) {
IORequest tmpReq = req; IORequest tmpReq = req;
tmpReq.offset += HEADER_SIZE; tmpReq.offset += HEADER_SIZE;
ok = base->write(tmpReq); ok = base->write(tmpReq);
} else } else {
ok = base->write(req); ok = base->write(req);
}
} else { } else {
VLOG(1) << "encodeBlock failed for block " << blockNum << ", size " VLOG(1) << "encodeBlock failed for block " << blockNum << ", size "
<< req.dataLen; << req.dataLen;
@ -384,43 +396,45 @@ bool CipherFileIO::writeOneBlock(const IORequest &req) {
bool CipherFileIO::blockWrite(unsigned char *buf, int size, bool CipherFileIO::blockWrite(unsigned char *buf, int size,
uint64_t _iv64) const { uint64_t _iv64) const {
VLOG(1) << "Called blockWrite"; VLOG(1) << "Called blockWrite";
if (!fsConfig->reverseEncryption) if (!fsConfig->reverseEncryption) {
return cipher->blockEncode(buf, size, _iv64, key); return cipher->blockEncode(buf, size, _iv64, key);
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 {
VLOG(1) << "Called streamWrite"; VLOG(1) << "Called streamWrite";
if (!fsConfig->reverseEncryption) if (!fsConfig->reverseEncryption) {
return cipher->streamEncode(buf, size, _iv64, key); return cipher->streamEncode(buf, size, _iv64, key);
else }
return cipher->streamDecode(buf, size, _iv64, key); return cipher->streamDecode(buf, size, _iv64, key);
} }
bool CipherFileIO::blockRead(unsigned char *buf, int size, bool CipherFileIO::blockRead(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 {
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);
} }
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;
}
return cipher->blockDecode(buf, size, _iv64, key);
} }
bool CipherFileIO::streamRead(unsigned char *buf, int size, bool CipherFileIO::streamRead(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 }
return cipher->streamDecode(buf, size, _iv64, key); return cipher->streamDecode(buf, size, _iv64, key);
} }
int CipherFileIO::truncate(off_t size) { int CipherFileIO::truncate(off_t size) {
@ -433,17 +447,20 @@ int CipherFileIO::truncate(off_t size) {
if (!base->isWritable()) { if (!base->isWritable()) {
// open for write.. // open for write..
int newFlags = lastFlags | O_RDWR; int newFlags = lastFlags | O_RDWR;
if (base->open(newFlags) < 0) if (base->open(newFlags) < 0) {
VLOG(1) << "writeHeader failed to re-open for write"; VLOG(1) << "writeHeader failed to re-open for write";
}
} }
initHeader(); initHeader();
} }
// can't let BlockFileIO call base->truncate(), since it would be using // can't let BlockFileIO call base->truncate(), since it would be using
// the wrong size.. // the wrong size..
res = BlockFileIO::truncateBase(size, 0); res = BlockFileIO::truncateBase(size, nullptr);
if (res == 0) base->truncate(size + HEADER_SIZE); if (res == 0) {
base->truncate(size + HEADER_SIZE);
}
} }
return res; return res;
} }
@ -482,8 +499,9 @@ ssize_t CipherFileIO::read(const IORequest &origReq) const {
* to the data. */ * to the data. */
if (req.offset < 0) { if (req.offset < 0) {
headerBytes = -req.offset; headerBytes = -req.offset;
if (req.dataLen < headerBytes) if (req.dataLen < headerBytes) {
headerBytes = req.dataLen; // only up to the number of bytes requested headerBytes = req.dataLen; // only up to the number of bytes requested
}
VLOG(1) << "Adding " << headerBytes << " header bytes"; VLOG(1) << "Adding " << headerBytes << " header bytes";
// copy the header bytes into the data // copy the header bytes into the data
@ -491,7 +509,9 @@ ssize_t CipherFileIO::read(const IORequest &origReq) const {
memcpy(req.data, &headerBuf[headerOffset], headerBytes); memcpy(req.data, &headerBuf[headerOffset], headerBytes);
// the read does not want data beyond the header // the read does not want data beyond the header
if (headerBytes == req.dataLen) return headerBytes; if (headerBytes == req.dataLen) {
return headerBytes;
}
/* The rest of the request will be read from the backing file. /* The rest of the request will be read from the backing file.
* As we have already generated n=headerBytes bytes, the request is * As we have already generated n=headerBytes bytes, the request is
@ -505,13 +525,12 @@ ssize_t CipherFileIO::read(const IORequest &origReq) const {
// read the payload // read the payload
ssize_t readBytes = BlockFileIO::read(req); ssize_t readBytes = BlockFileIO::read(req);
VLOG(1) << "read " << readBytes << " bytes from backing file"; VLOG(1) << "read " << readBytes << " bytes from backing file";
if (readBytes < 0) if (readBytes < 0) {
return readBytes; // Return error code return readBytes; // Return error code
else {
ssize_t sum = headerBytes + readBytes;
VLOG(1) << "returning sum=" << sum;
return sum;
} }
ssize_t sum = headerBytes + readBytes;
VLOG(1) << "returning sum=" << sum;
return sum;
} }
bool CipherFileIO::isWritable() const { return base->isWritable(); } bool CipherFileIO::isWritable() const { return base->isWritable(); }

View File

@ -45,7 +45,7 @@ struct IORequest;
*/ */
class CipherFileIO : public BlockFileIO { class CipherFileIO : public BlockFileIO {
public: public:
CipherFileIO(const std::shared_ptr<FileIO> &base, const FSConfigPtr &cfg); CipherFileIO(std::shared_ptr<FileIO> base, const FSConfigPtr &cfg);
virtual ~CipherFileIO(); virtual ~CipherFileIO();
virtual Interface interface() const; virtual Interface interface() const;

View File

@ -22,8 +22,8 @@
namespace encfs { namespace encfs {
AbstractCipherKey::AbstractCipherKey() {} AbstractCipherKey::AbstractCipherKey() = default;
AbstractCipherKey::~AbstractCipherKey() {} AbstractCipherKey::~AbstractCipherKey() = default;
} // namespace encfs } // namespace encfs

View File

@ -31,7 +31,7 @@ class AbstractCipherKey {
virtual ~AbstractCipherKey(); virtual ~AbstractCipherKey();
}; };
typedef std::shared_ptr<AbstractCipherKey> CipherKey; using CipherKey = std::shared_ptr<AbstractCipherKey>;
} // namespace encfs } // namespace encfs

View File

@ -33,23 +33,27 @@ using namespace std;
namespace encfs { namespace encfs {
ConfigReader::ConfigReader() {} ConfigReader::ConfigReader() = default;
ConfigReader::~ConfigReader() {} ConfigReader::~ConfigReader() = default;
// 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 ConfigReader::load(const char *fileName) { bool ConfigReader::load(const char *fileName) {
struct stat stbuf; struct stat stbuf;
memset(&stbuf, 0, sizeof(struct stat)); memset(&stbuf, 0, sizeof(struct stat));
if (lstat(fileName, &stbuf) != 0) return false; if (lstat(fileName, &stbuf) != 0) {
return false;
}
int size = stbuf.st_size; int size = stbuf.st_size;
int fd = open(fileName, O_RDONLY); int fd = open(fileName, O_RDONLY);
if (fd < 0) return false; if (fd < 0) {
return false;
}
char *buf = new char[size]; auto *buf = new char[size];
int res = ::read(fd, buf, size); int res = ::read(fd, buf, size);
close(fd); close(fd);
@ -126,11 +130,11 @@ ConfigVar ConfigReader::toVar() const {
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); auto it = vars.find(varName);
if (it == vars.end()) if (it == vars.end()) {
return ConfigVar(); return ConfigVar();
else }
return it->second; return it->second;
} }
ConfigVar &ConfigReader::operator[](const std::string &varName) { ConfigVar &ConfigReader::operator[](const std::string &varName) {

View File

@ -43,10 +43,10 @@ ConfigVar::ConfigVar(const ConfigVar &src) { pd = src.pd; }
ConfigVar::~ConfigVar() { pd.reset(); } ConfigVar::~ConfigVar() { pd.reset(); }
ConfigVar &ConfigVar::operator=(const ConfigVar &src) { ConfigVar &ConfigVar::operator=(const ConfigVar &src) {
if (src.pd == pd) if (src.pd == pd) {
return *this; return *this;
else }
pd = src.pd; pd = src.pd;
return *this; return *this;
} }
@ -56,7 +56,9 @@ void ConfigVar::resetOffset() { pd->offset = 0; }
int ConfigVar::read(unsigned char *buffer_, int bytes) const { int ConfigVar::read(unsigned char *buffer_, int bytes) const {
int toCopy = MIN(bytes, pd->buffer.size() - pd->offset); int toCopy = MIN(bytes, pd->buffer.size() - pd->offset);
if (toCopy > 0) memcpy(buffer_, pd->buffer.data() + pd->offset, toCopy); if (toCopy > 0) {
memcpy(buffer_, pd->buffer.data() + pd->offset, toCopy);
}
pd->offset += toCopy; pd->offset += toCopy;
@ -106,13 +108,15 @@ void ConfigVar::writeInt(int val) {
// 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) ++start; while (digit[start] == 0x80) {
++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 auto *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;
@ -122,7 +126,7 @@ int ConfigVar::readInt() const {
do { do {
unsigned char tmp = buf[offset++]; unsigned char tmp = buf[offset++];
highBitSet = tmp & 0x80; highBitSet = ((tmp & 0x80) != 0);
value = (value << 7) | (int)(tmp & 0x7f); value = (value << 7) | (int)(tmp & 0x7f);
} while (highBitSet && offset < bytes); } while (highBitSet && offset < bytes);
@ -139,10 +143,10 @@ 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 }
return readInt(); return readInt();
} }
bool ConfigVar::readBool(bool defaultValue) const { bool ConfigVar::readBool(bool defaultValue) const {
@ -184,7 +188,7 @@ const ConfigVar &operator>>(const ConfigVar &src, std::string &result) {
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]; auto *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;

View File

@ -29,9 +29,9 @@
namespace encfs { namespace encfs {
EncFS_Context::EncFS_Context() { EncFS_Context::EncFS_Context() {
pthread_cond_init(&wakeupCond, 0); pthread_cond_init(&wakeupCond, nullptr);
pthread_mutex_init(&wakeupMutex, 0); pthread_mutex_init(&wakeupMutex, nullptr);
pthread_mutex_init(&contextMutex, 0); pthread_mutex_init(&contextMutex, nullptr);
usageCount = 0; usageCount = 0;
currentFuseFh = 1; currentFuseFh = 1;
@ -70,10 +70,12 @@ void EncFS_Context::setRoot(const std::shared_ptr<DirNode> &r) {
Lock lock(contextMutex); Lock lock(contextMutex);
root = r; root = r;
if (r) rootCipherDir = r->rootDirectory(); if (r) {
rootCipherDir = r->rootDirectory();
}
} }
bool EncFS_Context::isMounted() { return root.get() != nullptr; } bool EncFS_Context::isMounted() { return root != nullptr; }
void EncFS_Context::getAndResetUsageCounter(int *usage, int *openCount) { void EncFS_Context::getAndResetUsageCounter(int *usage, int *openCount) {
Lock lock(contextMutex); Lock lock(contextMutex);
@ -87,7 +89,7 @@ void EncFS_Context::getAndResetUsageCounter(int *usage, int *openCount) {
std::shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) { std::shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
Lock lock(contextMutex); Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(path)); auto it = openFiles.find(std::string(path));
if (it != openFiles.end()) { if (it != openFiles.end()) {
// every entry in the list is fine... so just use the // every entry in the list is fine... so just use the
// first // first
@ -99,7 +101,7 @@ std::shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
void EncFS_Context::renameNode(const char *from, const char *to) { void EncFS_Context::renameNode(const char *from, const char *to) {
Lock lock(contextMutex); Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(from)); auto it = openFiles.find(std::string(from));
if (it != openFiles.end()) { if (it != openFiles.end()) {
auto val = it->second; auto val = it->second;
openFiles.erase(it); openFiles.erase(it);
@ -109,8 +111,7 @@ void EncFS_Context::renameNode(const char *from, const char *to) {
// putNode stores "node" under key "path" in the "openFiles" map. It // putNode stores "node" under key "path" in the "openFiles" map. It
// increments the reference count if the key already exists. // increments the reference count if the key already exists.
void EncFS_Context::putNode(const char *path, void EncFS_Context::putNode(const char *path, std::shared_ptr<FileNode> node) {
std::shared_ptr<FileNode> node) {
Lock lock(contextMutex); Lock lock(contextMutex);
auto &list = openFiles[std::string(path)]; auto &list = openFiles[std::string(path)];
// The length of "list" serves as the reference count. // The length of "list" serves as the reference count.
@ -120,10 +121,11 @@ void EncFS_Context::putNode(const char *path,
// eraseNode is called by encfs_release in response to the RELEASE // eraseNode is called by encfs_release in response to the RELEASE
// FUSE-command we get from the kernel. // FUSE-command we get from the kernel.
void EncFS_Context::eraseNode(const char *path, std::shared_ptr<FileNode> fnode) { void EncFS_Context::eraseNode(const char *path,
std::shared_ptr<FileNode> fnode) {
Lock lock(contextMutex); Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(path)); auto it = openFiles.find(std::string(path));
rAssert(it != openFiles.end()); rAssert(it != openFiles.end());
auto &list = it->second; auto &list = it->second;

View File

@ -21,14 +21,14 @@
#ifndef _Context_incl_ #ifndef _Context_incl_
#define _Context_incl_ #define _Context_incl_
#include <list>
#include <algorithm> #include <algorithm>
#include <atomic>
#include <list>
#include <memory> #include <memory>
#include <pthread.h> #include <pthread.h>
#include <set> #include <set>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <atomic>
#include "encfs.h" #include "encfs.h"
@ -47,7 +47,7 @@ class EncFS_Context {
std::shared_ptr<FileNode> lookupNode(const char *path); std::shared_ptr<FileNode> lookupNode(const char *path);
void getAndResetUsageCounter(int *usage, int *openCount); void getAndResetUsageCounter(int *usage, int *openCount);
void putNode(const char *path, std::shared_ptr<FileNode> node); void putNode(const char *path, std::shared_ptr<FileNode> node);
void eraseNode(const char *path, std::shared_ptr<FileNode> fnode); void eraseNode(const char *path, std::shared_ptr<FileNode> fnode);
@ -85,9 +85,8 @@ class EncFS_Context {
* us. * us.
*/ */
typedef std::unordered_map<std::string, using FileMap =
std::list<std::shared_ptr<FileNode>>> std::unordered_map<std::string, std::list<std::shared_ptr<FileNode>>>;
FileMap;
mutable pthread_mutex_t contextMutex; mutable pthread_mutex_t contextMutex;
FileMap openFiles; FileMap openFiles;

View File

@ -37,6 +37,7 @@
#include "internal/easylogging++.h" #include "internal/easylogging++.h"
#include <cstring> #include <cstring>
#include <utility>
#include "Context.h" #include "Context.h"
#include "Error.h" #include "Error.h"
@ -51,20 +52,13 @@ class DirDeleter {
void operator()(DIR *d) { ::closedir(d); } void operator()(DIR *d) { ::closedir(d); }
}; };
DirTraverse::DirTraverse(const std::shared_ptr<DIR> &_dirPtr, uint64_t _iv, DirTraverse::DirTraverse(std::shared_ptr<DIR> _dirPtr, uint64_t _iv,
const std::shared_ptr<NameIO> &_naming) std::shared_ptr<NameIO> _naming)
: dir(_dirPtr), iv(_iv), naming(_naming) {} : dir(std::move(_dirPtr)), iv(_iv), naming(std::move(_naming)) {}
DirTraverse::DirTraverse(const DirTraverse &src) DirTraverse::DirTraverse(const DirTraverse &src) = default;
: dir(src.dir), iv(src.iv), naming(src.naming) {}
DirTraverse &DirTraverse::operator=(const DirTraverse &src) { DirTraverse &DirTraverse::operator=(const DirTraverse &src) = default;
dir = src.dir;
iv = src.iv;
naming = src.naming;
return *this;
}
DirTraverse::~DirTraverse() { DirTraverse::~DirTraverse() {
dir.reset(); dir.reset();
@ -76,8 +70,8 @@ static bool _nextName(struct dirent *&de, const std::shared_ptr<DIR> &dir,
int *fileType, ino_t *inode) { int *fileType, ino_t *inode) {
de = ::readdir(dir.get()); de = ::readdir(dir.get());
if (de) { if (de != nullptr) {
if (fileType) { if (fileType != nullptr) {
#if defined(_DIRENT_HAVE_D_TYPE) || defined(__FreeBSD__) || defined(__APPLE__) #if defined(_DIRENT_HAVE_D_TYPE) || defined(__FreeBSD__) || defined(__APPLE__)
*fileType = de->d_type; *fileType = de->d_type;
#else #else
@ -85,16 +79,19 @@ static bool _nextName(struct dirent *&de, const std::shared_ptr<DIR> &dir,
*fileType = 0; *fileType = 0;
#endif #endif
} }
if (inode) *inode = de->d_ino; if (inode != nullptr) {
*inode = de->d_ino;
}
return true; return true;
} else {
if (fileType) *fileType = 0;
return false;
} }
if (fileType != nullptr) {
*fileType = 0;
}
return false;
} }
std::string DirTraverse::nextPlaintextName(int *fileType, ino_t *inode) { std::string DirTraverse::nextPlaintextName(int *fileType, ino_t *inode) {
struct dirent *de = 0; struct dirent *de = nullptr;
while (_nextName(de, dir, fileType, inode)) { while (_nextName(de, dir, fileType, inode)) {
try { try {
uint64_t localIv = iv; uint64_t localIv = iv;
@ -109,9 +106,9 @@ std::string DirTraverse::nextPlaintextName(int *fileType, ino_t *inode) {
} }
std::string DirTraverse::nextInvalid() { std::string DirTraverse::nextInvalid() {
struct dirent *de = 0; struct dirent *de = nullptr;
// find the first name which produces a decoding error... // find the first name which produces a decoding error...
while (_nextName(de, dir, (int *)0, (ino_t *)0)) { while (_nextName(de, dir, (int *)nullptr, (ino_t *)nullptr)) {
try { try {
uint64_t localIv = iv; uint64_t localIv = iv;
naming->decodePath(de->d_name, &localIv); naming->decodePath(de->d_name, &localIv);
@ -143,17 +140,16 @@ class RenameOp {
list<RenameEl>::const_iterator last; list<RenameEl>::const_iterator last;
public: public:
RenameOp(DirNode *_dn, const std::shared_ptr<list<RenameEl> > &_renameList) RenameOp(DirNode *_dn, std::shared_ptr<list<RenameEl> > _renameList)
: dn(_dn), renameList(_renameList) { : dn(_dn), renameList(std::move(_renameList)) {
last = renameList->begin(); last = renameList->begin();
} }
RenameOp(const RenameOp &src) RenameOp(const RenameOp &src) = default;
: dn(src.dn), renameList(src.renameList), last(src.last) {}
~RenameOp(); ~RenameOp();
operator bool() const { return renameList.get() != nullptr; } operator bool() const { return renameList != nullptr; }
bool apply(); bool apply();
void undo(); void undo();
@ -219,7 +215,7 @@ void RenameOp::undo() {
// list has to be processed backwards, otherwise we may rename // list has to be processed backwards, otherwise we may rename
// directories and directory contents in the wrong order! // directories and directory contents in the wrong order!
int undoCount = 0; int undoCount = 0;
list<RenameEl>::const_iterator it = last; auto it = last;
while (it != renameList->begin()) { while (it != renameList->begin()) {
--it; --it;
@ -241,7 +237,7 @@ void RenameOp::undo() {
DirNode::DirNode(EncFS_Context *_ctx, const string &sourceDir, DirNode::DirNode(EncFS_Context *_ctx, const string &sourceDir,
const FSConfigPtr &_config) { const FSConfigPtr &_config) {
pthread_mutex_init(&mutex, 0); pthread_mutex_init(&mutex, nullptr);
Lock _lock(mutex); Lock _lock(mutex);
@ -252,7 +248,7 @@ DirNode::DirNode(EncFS_Context *_ctx, const string &sourceDir,
naming = fsConfig->nameCoding; naming = fsConfig->nameCoding;
} }
DirNode::~DirNode() {} DirNode::~DirNode() = default;
bool DirNode::hasDirectoryNameDependency() const { bool DirNode::hasDirectoryNameDependency() const {
return naming ? naming->getChainedNameIV() : false; return naming ? naming->getChainedNameIV() : false;
@ -354,22 +350,23 @@ DirTraverse DirNode::openDir(const char *plaintextPath) {
string cyName = rootDir + naming->encodePath(plaintextPath); string cyName = rootDir + naming->encodePath(plaintextPath);
DIR *dir = ::opendir(cyName.c_str()); DIR *dir = ::opendir(cyName.c_str());
if (dir == NULL) { if (dir == nullptr) {
VLOG(1) << "opendir error " << strerror(errno); VLOG(1) << "opendir error " << strerror(errno);
return DirTraverse(shared_ptr<DIR>(), 0, std::shared_ptr<NameIO>()); return DirTraverse(shared_ptr<DIR>(), 0, std::shared_ptr<NameIO>());
} else {
std::shared_ptr<DIR> dp(dir, DirDeleter());
uint64_t iv = 0;
// if we're using chained IV mode, then compute the IV at this
// directory level..
try {
if (naming->getChainedNameIV()) naming->encodePath(plaintextPath, &iv);
} catch (encfs::Error &err) {
RLOG(ERROR) << "encode err: " << err.what();
}
return DirTraverse(dp, iv, naming);
} }
std::shared_ptr<DIR> dp(dir, DirDeleter());
uint64_t iv = 0;
// if we're using chained IV mode, then compute the IV at this
// directory level..
try {
if (naming->getChainedNameIV()) {
naming->encodePath(plaintextPath, &iv);
}
} catch (encfs::Error &err) {
RLOG(ERROR) << "encode err: " << err.what();
}
return DirTraverse(dp, iv, naming);
} }
bool DirNode::genRenameList(list<RenameEl> &renameList, const char *fromP, bool DirNode::genRenameList(list<RenameEl> &renameList, const char *fromP,
@ -384,16 +381,20 @@ bool DirNode::genRenameList(list<RenameEl> &renameList, const char *fromP,
string sourcePath = rootDir + fromCPart; string sourcePath = rootDir + fromCPart;
// ok..... we wish it was so simple.. should almost never happen // ok..... we wish it was so simple.. should almost never happen
if (fromIV == toIV) return true; if (fromIV == toIV) {
return true;
}
// generate the real destination path, where we expect to find the files.. // generate the real destination path, where we expect to find the files..
VLOG(1) << "opendir " << sourcePath; VLOG(1) << "opendir " << sourcePath;
std::shared_ptr<DIR> dir = std::shared_ptr<DIR> dir =
std::shared_ptr<DIR>(opendir(sourcePath.c_str()), DirDeleter()); std::shared_ptr<DIR>(opendir(sourcePath.c_str()), DirDeleter());
if (!dir) return false; if (!dir) {
return false;
}
struct dirent *de = NULL; struct dirent *de = nullptr;
while ((de = ::readdir(dir.get())) != NULL) { while ((de = ::readdir(dir.get())) != nullptr) {
// decode the name using the oldIV // decode the name using the oldIV
uint64_t localIV = fromIV; uint64_t localIV = fromIV;
string plainName; string plainName;
@ -475,16 +476,17 @@ bool DirNode::genRenameList(list<RenameEl> &renameList, const char *fromP,
will have changed.. will have changed..
Returns a list of renamed items on success, a null list on failure. Returns a list of renamed items on success, a null list on failure.
*/ std::shared_ptr<RenameOp> DirNode::newRenameOp(const char *fromP, */
const char *toP) { std::shared_ptr<RenameOp> DirNode::newRenameOp(const char *fromP,
const char *toP) {
// Do the rename in two stages to avoid chasing our tail // Do the rename in two stages to avoid chasing our tail
// Undo everything if we encounter an error! // Undo everything if we encounter an error!
std::shared_ptr<list<RenameEl> > renameList(new list<RenameEl>); std::shared_ptr<list<RenameEl> > renameList(new list<RenameEl>);
if (!genRenameList(*renameList.get(), fromP, toP)) { if (!genRenameList(*renameList.get(), fromP, toP)) {
RLOG(WARNING) << "Error during generation of recursive rename list"; RLOG(WARNING) << "Error during generation of recursive rename list";
return std::shared_ptr<RenameOp>(); return std::shared_ptr<RenameOp>();
} else }
return std::shared_ptr<RenameOp>(new RenameOp(this, renameList)); return std::make_shared<RenameOp>(this, renameList);
} }
int DirNode::mkdir(const char *plaintextPath, mode_t mode, uid_t uid, int DirNode::mkdir(const char *plaintextPath, mode_t mode, uid_t uid,
@ -497,21 +499,30 @@ int DirNode::mkdir(const char *plaintextPath, mode_t mode, uid_t uid,
// if uid or gid are set, then that should be the directory owner // if uid or gid are set, then that should be the directory owner
int olduid = -1; int olduid = -1;
int oldgid = -1; int oldgid = -1;
if (uid != 0) olduid = setfsuid(uid); if (uid != 0) {
if (gid != 0) oldgid = setfsgid(gid); olduid = setfsuid(uid);
}
if (gid != 0) {
oldgid = setfsgid(gid);
}
int res = ::mkdir(cyName.c_str(), mode); int res = ::mkdir(cyName.c_str(), mode);
if (olduid >= 0) setfsuid(olduid); if (olduid >= 0) {
if (oldgid >= 0) setfsgid(oldgid); setfsuid(olduid);
}
if (oldgid >= 0) {
setfsgid(oldgid);
}
if (res == -1) { if (res == -1) {
int eno = errno; int eno = errno;
RLOG(WARNING) << "mkdir error on " << cyName << " mode " << mode << ": " RLOG(WARNING) << "mkdir error on " << cyName << " mode " << mode << ": "
<< strerror(eno); << strerror(eno);
res = -eno; res = -eno;
} else } else {
res = 0; res = 0;
}
return res; return res;
} }
@ -534,7 +545,9 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
renameOp = newRenameOp(fromPlaintext, toPlaintext); renameOp = newRenameOp(fromPlaintext, toPlaintext);
if (!renameOp || !renameOp->apply()) { if (!renameOp || !renameOp->apply()) {
if (renameOp) renameOp->undo(); if (renameOp) {
renameOp->undo();
}
RLOG(WARNING) << "rename aborted"; RLOG(WARNING) << "rename aborted";
return -EACCES; return -EACCES;
@ -555,7 +568,9 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
res = -errno; res = -errno;
renameNode(toPlaintext, fromPlaintext, false); renameNode(toPlaintext, fromPlaintext, false);
if (renameOp) renameOp->undo(); if (renameOp) {
renameOp->undo();
}
} else if (preserve_mtime) { } else if (preserve_mtime) {
struct utimbuf ut; struct utimbuf ut;
ut.actime = st.st_atime; ut.actime = st.st_atime;
@ -592,10 +607,11 @@ int DirNode::link(const char *from, const char *to) {
VLOG(1) << "hard links not supported with external IV chaining!"; VLOG(1) << "hard links not supported with external IV chaining!";
} else { } else {
res = ::link(fromCName.c_str(), toCName.c_str()); res = ::link(fromCName.c_str(), toCName.c_str());
if (res == -1) if (res == -1) {
res = -errno; res = -errno;
else } else {
res = 0; res = 0;
}
} }
return res; return res;
@ -604,10 +620,12 @@ int DirNode::link(const char *from, const char *to) {
/* /*
The node is keyed by filename, so a rename means the internal node names The node is keyed by filename, so a rename means the internal node names
must be changed. must be changed.
*/ std::shared_ptr<FileNode> DirNode::renameNode(const char *from, */
const char *to) { std::shared_ptr<FileNode> DirNode::renameNode(const char *from,
const char *to) {
return renameNode(from, to, true); return renameNode(from, to, true);
} }
std::shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to, std::shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to,
bool forwardMode) { bool forwardMode) {
std::shared_ptr<FileNode> node = findOrCreate(from); std::shared_ptr<FileNode> node = findOrCreate(from);
@ -620,7 +638,9 @@ std::shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to,
<< cname; << cname;
if (node->setName(to, cname.c_str(), newIV, forwardMode)) { if (node->setName(to, cname.c_str(), newIV, forwardMode)) {
if (ctx) ctx->renameNode(from, to); if (ctx != nullptr) {
ctx->renameNode(from, to);
}
} else { } else {
// rename error! - put it back // rename error! - put it back
RLOG(ERROR) << "renameNode failed"; RLOG(ERROR) << "renameNode failed";
@ -637,20 +657,23 @@ std::shared_ptr<FileNode> DirNode::findOrCreate(const char *plainName) {
std::shared_ptr<FileNode> node; std::shared_ptr<FileNode> node;
// See if we already have a FileNode for this path. // See if we already have a FileNode for this path.
if (ctx) if (ctx != nullptr) {
node = ctx->lookupNode(plainName); node = ctx->lookupNode(plainName);
// If we don't, create a new one. // If we don't, create a new one.
if (!node) { if (!node) {
uint64_t iv = 0; uint64_t iv = 0;
string cipherName = naming->encodePath(plainName, &iv); string cipherName = naming->encodePath(plainName, &iv);
uint64_t fuseFh = ctx->nextFuseFh(); uint64_t fuseFh = ctx->nextFuseFh();
node.reset(new FileNode(this, fsConfig, plainName, node.reset(new FileNode(this, fsConfig, plainName,
(rootDir + cipherName).c_str(), fuseFh)); (rootDir + cipherName).c_str(), fuseFh));
if (fsConfig->config->externalIVChaining) node->setName(0, 0, iv); if (fsConfig->config->externalIVChaining) {
node->setName(nullptr, nullptr, iv);
}
VLOG(1) << "created FileNode for " << node->cipherName(); VLOG(1) << "created FileNode for " << node->cipherName();
}
} }
return node; return node;
@ -669,18 +692,18 @@ shared_ptr<FileNode> DirNode::lookupNode(const char *plainName,
"result" is set to -1 on failure, a value >= 0 on success. "result" is set to -1 on failure, a value >= 0 on success.
*/ */
std::shared_ptr<FileNode> DirNode::openNode(const char *plainName, std::shared_ptr<FileNode> DirNode::openNode(const char *plainName,
const char *requestor, int flags, const char *requestor, int flags,
int *result) { int *result) {
(void)requestor; (void)requestor;
rAssert(result != NULL); rAssert(result != nullptr);
Lock _lock(mutex); Lock _lock(mutex);
std::shared_ptr<FileNode> node = findOrCreate(plainName); std::shared_ptr<FileNode> node = findOrCreate(plainName);
if (node && (*result = node->open(flags)) >= 0) if (node && (*result = node->open(flags)) >= 0) {
return node; return node;
else }
return std::shared_ptr<FileNode>(); return std::shared_ptr<FileNode>();
} }
int DirNode::unlink(const char *plaintextName) { int DirNode::unlink(const char *plaintextName) {
@ -690,7 +713,7 @@ int DirNode::unlink(const char *plaintextName) {
Lock _lock(mutex); Lock _lock(mutex);
int res = 0; int res = 0;
if (ctx && ctx->lookupNode(plaintextName)) { if ((ctx != nullptr) && ctx->lookupNode(plaintextName)) {
// If FUSE is running with "hard_remove" option where it doesn't // If FUSE is running with "hard_remove" option where it doesn't
// hide open files for us, then we can't allow an unlink of an open // hide open files for us, then we can't allow an unlink of an open
// file.. // file..

View File

@ -48,8 +48,8 @@ struct RenameEl;
class DirTraverse { class DirTraverse {
public: public:
DirTraverse(const std::shared_ptr<DIR> &dirPtr, uint64_t iv, DirTraverse(std::shared_ptr<DIR> dirPtr, uint64_t iv,
const std::shared_ptr<NameIO> &naming); std::shared_ptr<NameIO> naming);
DirTraverse(const DirTraverse &src); DirTraverse(const DirTraverse &src);
~DirTraverse(); ~DirTraverse();

View File

@ -18,18 +18,17 @@ void initLogging(bool enable_debug, bool is_daemon) {
if (is_daemon) { if (is_daemon) {
prefix = ""; prefix = "";
encfs::rlogAction = el::base::DispatchAction::SysLog; encfs::rlogAction = el::base::DispatchAction::SysLog;
} } else {
else {
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
} }
if (!enable_debug) { if (!enable_debug) {
suffix = ""; suffix = "";
defaultConf.set(el::Level::Debug, el::ConfigurationType::Enabled, "false"); defaultConf.set(el::Level::Debug, el::ConfigurationType::Enabled, "false");
} } else {
else {
el::Loggers::setVerboseLevel(1); el::Loggers::setVerboseLevel(1);
} }
defaultConf.setGlobally(el::ConfigurationType::Format, prefix + std::string("%level %msg") + suffix); defaultConf.setGlobally(el::ConfigurationType::Format,
prefix + std::string("%level %msg") + suffix);
el::Loggers::reconfigureLogger("default", defaultConf); el::Loggers::reconfigureLogger("default", defaultConf);
} }

View File

@ -21,7 +21,7 @@ class Error : public std::runtime_error {
RLOG(ERROR) << "Assert failed: " << STR(cond); \ RLOG(ERROR) << "Assert failed: " << STR(cond); \
throw encfs::Error(STR(cond)); \ throw encfs::Error(STR(cond)); \
} \ } \
} while (0) } while (false)
void initLogging(bool enable_debug = false, bool is_daemon = false); void initLogging(bool enable_debug = false, bool is_daemon = false);

View File

@ -130,7 +130,7 @@ struct FSConfig {
: forceDecode(false), reverseEncryption(false), idleTracking(false) {} : forceDecode(false), reverseEncryption(false), idleTracking(false) {}
}; };
typedef std::shared_ptr<FSConfig> FSConfigPtr; using FSConfigPtr = std::shared_ptr<FSConfig>;
} // namespace encfs } // namespace encfs

View File

@ -22,9 +22,9 @@
namespace encfs { namespace encfs {
FileIO::FileIO() {} FileIO::FileIO() = default;
FileIO::~FileIO() {} FileIO::~FileIO() = default;
int FileIO::blockSize() const { return 1; } int FileIO::blockSize() const { return 1; }

View File

@ -18,9 +18,9 @@
* 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 <errno.h> #include <cerrno>
#include <cinttypes>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
@ -53,9 +53,10 @@ namespace encfs {
*/ */
FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg, FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
const char *plaintextName_, const char *cipherName_, uint64_t fuseFh) { const char *plaintextName_, const char *cipherName_,
uint64_t fuseFh) {
pthread_mutex_init(&mutex, 0); pthread_mutex_init(&mutex, nullptr);
Lock _lock(mutex); Lock _lock(mutex);
@ -73,8 +74,10 @@ FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
std::shared_ptr<FileIO> rawIO(new RawFileIO(_cname)); std::shared_ptr<FileIO> rawIO(new RawFileIO(_cname));
io = std::shared_ptr<FileIO>(new CipherFileIO(rawIO, fsConfig)); io = std::shared_ptr<FileIO>(new CipherFileIO(rawIO, fsConfig));
if (cfg->config->blockMACBytes || cfg->config->blockMACRandBytes) if ((cfg->config->blockMACBytes != 0) ||
(cfg->config->blockMACRandBytes != 0)) {
io = std::shared_ptr<FileIO>(new MACFileIO(io, fsConfig)); io = std::shared_ptr<FileIO>(new MACFileIO(io, fsConfig));
}
} }
FileNode::~FileNode() { FileNode::~FileNode() {
@ -97,23 +100,29 @@ string FileNode::plaintextParent() const { return parentDirectory(_pname); }
static bool setIV(const std::shared_ptr<FileIO> &io, uint64_t iv) { static bool setIV(const std::shared_ptr<FileIO> &io, uint64_t iv) {
struct stat stbuf; struct stat stbuf;
if ((io->getAttr(&stbuf) < 0) || S_ISREG(stbuf.st_mode)) if ((io->getAttr(&stbuf) < 0) || S_ISREG(stbuf.st_mode)) {
return io->setIV(iv); return io->setIV(iv);
else }
return true; return true;
} }
bool FileNode::setName(const char *plaintextName_, const char *cipherName_, bool FileNode::setName(const char *plaintextName_, const char *cipherName_,
uint64_t iv, bool setIVFirst) { uint64_t iv, bool setIVFirst) {
// Lock _lock( mutex ); // Lock _lock( mutex );
if (cipherName_) VLOG(1) << "calling setIV on " << cipherName_; if (cipherName_ != nullptr) {
VLOG(1) << "calling setIV on " << cipherName_;
}
if (setIVFirst) { if (setIVFirst) {
if (fsConfig->config->externalIVChaining && !setIV(io, iv)) return false; if (fsConfig->config->externalIVChaining && !setIV(io, iv)) {
return false;
}
// now change the name.. // now change the name..
if (plaintextName_) this->_pname = plaintextName_; if (plaintextName_ != nullptr) {
if (cipherName_) { this->_pname = plaintextName_;
}
if (cipherName_ != nullptr) {
this->_cname = cipherName_; this->_cname = cipherName_;
io->setFileName(cipherName_); io->setFileName(cipherName_);
} }
@ -121,8 +130,10 @@ bool FileNode::setName(const char *plaintextName_, const char *cipherName_,
std::string oldPName = _pname; std::string oldPName = _pname;
std::string oldCName = _cname; std::string oldCName = _cname;
if (plaintextName_) this->_pname = plaintextName_; if (plaintextName_ != nullptr) {
if (cipherName_) { this->_pname = plaintextName_;
}
if (cipherName_ != nullptr) {
this->_cname = cipherName_; this->_cname = cipherName_;
io->setFileName(cipherName_); io->setFileName(cipherName_);
} }
@ -165,14 +176,21 @@ int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid) {
*/ */
if (S_ISREG(mode)) { if (S_ISREG(mode)) {
res = ::open(_cname.c_str(), O_CREAT | O_EXCL | O_WRONLY, mode); res = ::open(_cname.c_str(), O_CREAT | O_EXCL | O_WRONLY, mode);
if (res >= 0) res = ::close(res); if (res >= 0) {
} else if (S_ISFIFO(mode)) res = ::close(res);
}
} else if (S_ISFIFO(mode)) {
res = ::mkfifo(_cname.c_str(), mode); res = ::mkfifo(_cname.c_str(), mode);
else } else {
res = ::mknod(_cname.c_str(), mode, rdev); res = ::mknod(_cname.c_str(), mode, rdev);
}
if (olduid >= 0) setfsuid(olduid); if (olduid >= 0) {
if (oldgid >= 0) setfsgid(oldgid); setfsuid(olduid);
}
if (oldgid >= 0) {
setfsgid(oldgid);
}
if (res == -1) { if (res == -1) {
int eno = errno; int eno = errno;
@ -241,10 +259,11 @@ int FileNode::sync(bool datasync) {
if (fh >= 0) { if (fh >= 0) {
int res = -EIO; 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
@ -252,11 +271,13 @@ int FileNode::sync(bool datasync) {
res = fsync(fh); res = fsync(fh);
#endif #endif
if (res == -1) res = -errno; if (res == -1) {
res = -errno;
}
return res; return res;
} else }
return fh; return fh;
} }
} // namespace encfs } // namespace encfs

View File

@ -21,13 +21,13 @@
#ifndef _FileNode_incl_ #ifndef _FileNode_incl_
#define _FileNode_incl_ #define _FileNode_incl_
#include <atomic>
#include <inttypes.h> #include <inttypes.h>
#include <memory> #include <memory>
#include <pthread.h> #include <pthread.h>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <sys/types.h> #include <sys/types.h>
#include <atomic>
#include "CipherKey.h" #include "CipherKey.h"
#include "FSConfig.h" #include "FSConfig.h"

View File

@ -22,7 +22,8 @@
#ifdef linux #ifdef linux
#define _XOPEN_SOURCE 500 // make sure pwrite() is pulled in #define _XOPEN_SOURCE 500 // make sure pwrite() is pulled in
#endif #endif
#define _BSD_SOURCE // pick up setenv on RH7.3 #define _BSD_SOURCE // pick up setenv on RH7.3
#define _DEFAULT_SOURCE // Replaces _BSD_SOURCE
#include "internal/easylogging++.h" #include "internal/easylogging++.h"
#include <cctype> #include <cctype>
@ -111,54 +112,45 @@ struct ConfigInfo {
// backward compatible support for older versions // backward compatible support for older versions
{".encfs5", Config_V5, "ENCFS5_CONFIG", readV5Config, writeV5Config, {".encfs5", Config_V5, "ENCFS5_CONFIG", readV5Config, writeV5Config,
V5SubVersion, V5SubVersionDefault}, V5SubVersion, V5SubVersionDefault},
{".encfs4", Config_V4, NULL, readV4Config, writeV4Config, 0, 0}, {".encfs4", Config_V4, nullptr, readV4Config, writeV4Config, 0, 0},
// no longer support earlier versions // no longer support earlier versions
{".encfs3", Config_V3, NULL, NULL, NULL, 0, 0}, {".encfs3", Config_V3, nullptr, nullptr, nullptr, 0, 0},
{".encfs2", Config_Prehistoric, NULL, NULL, NULL, 0, 0}, {".encfs2", Config_Prehistoric, nullptr, nullptr, nullptr, 0, 0},
{".encfs", Config_Prehistoric, NULL, NULL, NULL, 0, 0}, {".encfs", Config_Prehistoric, nullptr, nullptr, nullptr, 0, 0},
{NULL, Config_None, NULL, NULL, NULL, 0, 0}}; {nullptr, Config_None, nullptr, nullptr, nullptr, 0, 0}};
EncFS_Root::EncFS_Root() {} EncFS_Root::EncFS_Root() = default;
EncFS_Root::~EncFS_Root() {} EncFS_Root::~EncFS_Root() = default;
bool fileExists(const char *fileName) { bool fileExists(const char *fileName) {
struct stat buf; struct stat buf;
if (!lstat(fileName, &buf)) { return lstat(fileName, &buf) == 0;
return true;
} else {
// XXX show perror?
return false;
}
} }
bool isDirectory(const char *fileName) { bool isDirectory(const char *fileName) {
struct stat buf; struct stat buf;
if (!lstat(fileName, &buf)) { if (lstat(fileName, &buf) == 0) {
return S_ISDIR(buf.st_mode); return S_ISDIR(buf.st_mode);
} else {
return false;
} }
return false;
} }
bool isAbsolutePath(const char *fileName) { bool isAbsolutePath(const char *fileName) {
if (fileName && fileName[0] != '\0' && fileName[0] == '/') return (fileName != nullptr) && fileName[0] != '\0' && fileName[0] == '/';
return true;
else
return false;
} }
const char *lastPathElement(const char *name) { const char *lastPathElement(const char *name) {
const char *loc = strrchr(name, '/'); const char *loc = strrchr(name, '/');
return loc ? loc + 1 : name; return loc != nullptr ? loc + 1 : name;
} }
std::string parentDirectory(const std::string &path) { std::string parentDirectory(const std::string &path) {
size_t last = path.find_last_of('/'); size_t last = path.find_last_of('/');
if (last == string::npos) if (last == string::npos) {
return string(""); return string("");
else }
return path.substr(0, last); return path.substr(0, last);
} }
bool userAllowMkdir(const char *path, mode_t mode) { bool userAllowMkdir(const char *path, mode_t mode) {
@ -188,18 +180,17 @@ bool userAllowMkdir(int promptno, const char *path, mode_t mode) {
} }
res = fgets(answer, sizeof(answer), stdin); res = fgets(answer, sizeof(answer), stdin);
if (res != 0 && toupper(answer[0]) == 'Y') { if (res != nullptr && toupper(answer[0]) == 'Y') {
int result = mkdir(path, mode); int result = mkdir(path, mode);
if (result < 0) { if (result < 0) {
perror(_("Unable to create directory: ")); perror(_("Unable to create directory: "));
return false; return false;
} else }
return true; return true;
} else {
// Directory not created, by user request
cerr << _("Directory not created.") << "\n";
return false;
} }
// Directory not created, by user request
cerr << _("Directory not created.") << "\n";
return false;
} }
/** /**
@ -207,7 +198,7 @@ bool userAllowMkdir(int promptno, const char *path, mode_t mode) {
*/ */
ConfigType readConfig_load(ConfigInfo *nm, const char *path, ConfigType readConfig_load(ConfigInfo *nm, const char *path,
EncFSConfig *config) { EncFSConfig *config) {
if (nm->loadFunc) { if (nm->loadFunc != nullptr) {
try { try {
if ((*nm->loadFunc)(path, config, nm)) { if ((*nm->loadFunc)(path, config, nm)) {
config->cfgType = nm->type; config->cfgType = nm->type;
@ -233,11 +224,11 @@ ConfigType readConfig_load(ConfigInfo *nm, const char *path,
*/ */
ConfigType readConfig(const string &rootDir, EncFSConfig *config) { ConfigType readConfig(const string &rootDir, EncFSConfig *config) {
ConfigInfo *nm = ConfigFileMapping; ConfigInfo *nm = ConfigFileMapping;
while (nm->fileName) { while (nm->fileName != nullptr) {
// allow environment variable to override default config path // allow environment variable to override default config path
if (nm->environmentOverride != NULL) { if (nm->environmentOverride != nullptr) {
char *envFile = getenv(nm->environmentOverride); char *envFile = getenv(nm->environmentOverride);
if (envFile != NULL) { if (envFile != nullptr) {
if (!fileExists(envFile)) { if (!fileExists(envFile)) {
RLOG(ERROR) RLOG(ERROR)
<< "fatal: config file specified by environment does not exist: " << "fatal: config file specified by environment does not exist: "
@ -249,8 +240,9 @@ ConfigType readConfig(const string &rootDir, EncFSConfig *config) {
} }
// the standard place to look is in the root directory // the standard place to look is in the root directory
string path = rootDir + nm->fileName; string path = rootDir + nm->fileName;
if (fileExists(path.c_str())) if (fileExists(path.c_str())) {
return readConfig_load(nm, path.c_str(), config); return readConfig_load(nm, path.c_str(), config);
}
++nm; ++nm;
} }
@ -323,7 +315,7 @@ bool readV6Config(const char *configFile, EncFSConfig *cfg, ConfigInfo *info) {
int encodedSize; int encodedSize;
config->read("encodedKeySize", &encodedSize); config->read("encodedKeySize", &encodedSize);
unsigned char *key = new unsigned char[encodedSize]; auto *key = new unsigned char[encodedSize];
config->readB64("encodedKeyData", key, encodedSize); config->readB64("encodedKeyData", key, encodedSize);
cfg->assignKeyData(key, encodedSize); cfg->assignKeyData(key, encodedSize);
delete[] key; delete[] key;
@ -331,7 +323,7 @@ bool readV6Config(const char *configFile, EncFSConfig *cfg, ConfigInfo *info) {
if (cfg->subVersion >= 20080816) { if (cfg->subVersion >= 20080816) {
int saltLen; int saltLen;
config->read("saltLen", &saltLen); config->read("saltLen", &saltLen);
unsigned char *salt = new unsigned char[saltLen]; auto *salt = new unsigned char[saltLen];
config->readB64("saltData", salt, saltLen); config->readB64("saltData", salt, saltLen);
cfg->assignSaltData(salt, saltLen); cfg->assignSaltData(salt, saltLen);
delete[] salt; delete[] salt;
@ -445,13 +437,15 @@ bool saveConfig(ConfigType type, const string &rootDir,
bool ok = false; bool ok = false;
ConfigInfo *nm = ConfigFileMapping; ConfigInfo *nm = ConfigFileMapping;
while (nm->fileName) { while (nm->fileName != nullptr) {
if (nm->type == type && nm->saveFunc) { if (nm->type == type && (nm->saveFunc != nullptr)) {
string path = rootDir + nm->fileName; string path = rootDir + nm->fileName;
if (nm->environmentOverride != NULL) { if (nm->environmentOverride != nullptr) {
// use environment file if specified.. // use environment file if specified..
const char *envFile = getenv(nm->environmentOverride); const char *envFile = getenv(nm->environmentOverride);
if (envFile != NULL) path.assign(envFile); if (envFile != nullptr) {
path.assign(envFile);
}
} }
try { try {
@ -592,7 +586,8 @@ static Cipher::CipherAlgorithm findCipherAlgorithm(const char *name,
Cipher::AlgorithmList algorithms = Cipher::GetAlgorithmList(); Cipher::AlgorithmList algorithms = Cipher::GetAlgorithmList();
Cipher::AlgorithmList::const_iterator it; Cipher::AlgorithmList::const_iterator it;
for (it = algorithms.begin(); it != algorithms.end(); ++it) { for (it = algorithms.begin(); it != algorithms.end(); ++it) {
if (!strcmp(name, it->name.c_str()) && it->keyLength.allowed(keySize)) { if ((strcmp(name, it->name.c_str()) == 0) &&
it->keyLength.allowed(keySize)) {
return *it; return *it;
} }
} }
@ -649,7 +644,7 @@ static Cipher::CipherAlgorithm selectCipherAlgorithm() {
cout << "\n" << _("Enter the number corresponding to your choice: "); cout << "\n" << _("Enter the number corresponding to your choice: ");
char answer[10]; char answer[10];
char *res = fgets(answer, sizeof(answer), stdin); char *res = fgets(answer, sizeof(answer), stdin);
int cipherNum = (res == 0 ? 0 : atoi(answer)); int cipherNum = (res == nullptr ? 0 : atoi(answer));
cout << "\n"; cout << "\n";
if (cipherNum < 1 || cipherNum > (int)algorithms.size()) { if (cipherNum < 1 || cipherNum > (int)algorithms.size()) {
@ -658,8 +653,9 @@ static Cipher::CipherAlgorithm selectCipherAlgorithm() {
} }
it = algorithms.begin(); it = algorithms.begin();
while (--cipherNum) // numbering starts at 1 while (--cipherNum != 0) { // numbering starts at 1
++it; ++it;
}
Cipher::CipherAlgorithm alg = *it; Cipher::CipherAlgorithm alg = *it;
@ -692,7 +688,7 @@ static Interface selectNameCoding() {
cout << "\n" << _("Enter the number corresponding to your choice: "); cout << "\n" << _("Enter the number corresponding to your choice: ");
char answer[10]; char answer[10];
char *res = fgets(answer, sizeof(answer), stdin); char *res = fgets(answer, sizeof(answer), stdin);
int algNum = (res == 0 ? 0 : atoi(answer)); int algNum = (res == nullptr ? 0 : atoi(answer));
cout << "\n"; cout << "\n";
if (algNum < 1 || algNum > (int)algorithms.size()) { if (algNum < 1 || algNum > (int)algorithms.size()) {
@ -701,8 +697,9 @@ static Interface selectNameCoding() {
} }
it = algorithms.begin(); it = algorithms.begin();
while (--algNum) // numbering starts at 1 while (--algNum != 0) { // numbering starts at 1
++it; ++it;
}
// xgroup(setup) // xgroup(setup)
cout << autosprintf(_("Selected algorithm \"%s\""), it->name.c_str()) cout << autosprintf(_("Selected algorithm \"%s\""), it->name.c_str())
@ -737,13 +734,17 @@ static int selectKeySize(const Cipher::CipherAlgorithm &alg) {
if (numAvail < 5) { if (numAvail < 5) {
// show them all // show them all
for (int i = 0; i <= numAvail; ++i) { for (int i = 0; i <= numAvail; ++i) {
if (i) cout << ", "; if (i != 0) {
cout << ", ";
}
cout << alg.keyLength.min() + i * alg.keyLength.inc(); cout << alg.keyLength.min() + i * alg.keyLength.inc();
} }
} else { } else {
// partial // partial
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
if (i) cout << ", "; if (i != 0) {
cout << ", ";
}
cout << alg.keyLength.min() + i * alg.keyLength.inc(); cout << alg.keyLength.min() + i * alg.keyLength.inc();
} }
cout << " ... " << alg.keyLength.max() - alg.keyLength.inc(); cout << " ... " << alg.keyLength.max() - alg.keyLength.inc();
@ -754,7 +755,7 @@ static int selectKeySize(const Cipher::CipherAlgorithm &alg) {
char answer[10]; char answer[10];
char *res = fgets(answer, sizeof(answer), stdin); char *res = fgets(answer, sizeof(answer), stdin);
int keySize = (res == 0 ? 0 : atoi(answer)); int keySize = (res == nullptr ? 0 : atoi(answer));
cout << "\n"; cout << "\n";
keySize = alg.keyLength.closest(keySize); keySize = alg.keyLength.closest(keySize);
@ -794,7 +795,9 @@ static int selectBlockSize(const Cipher::CipherAlgorithm &alg) {
char *res = fgets(answer, sizeof(answer), stdin); char *res = fgets(answer, sizeof(answer), stdin);
cout << "\n"; cout << "\n";
if (res != 0 && atoi(answer) >= alg.blockSize.min()) blockSize = atoi(answer); if (res != nullptr && atoi(answer) >= alg.blockSize.min()) {
blockSize = atoi(answer);
}
blockSize = alg.blockSize.closest(blockSize); blockSize = alg.blockSize.closest(blockSize);
@ -816,10 +819,11 @@ static bool boolDefault(const char *prompt, bool defaultValue) {
string yesno; string yesno;
if (defaultValue == true) if (defaultValue) {
yesno = "[y]/n: "; yesno = "[y]/n: ";
else } else {
yesno = "y/[n]: "; yesno = "y/[n]: ";
}
string response; string response;
bool value; bool value;
@ -831,10 +835,12 @@ static bool boolDefault(const char *prompt, bool defaultValue) {
if (cin.fail() || response == "") { if (cin.fail() || response == "") {
value = defaultValue; value = defaultValue;
break; break;
} else if (response == "y") { }
if (response == "y") {
value = true; value = true;
break; break;
} else if (response == "n") { }
if (response == "n") {
value = false; value = false;
break; break;
} }
@ -873,10 +879,11 @@ static void selectBlockMAC(int *macBytes, int *macRandBytes, bool forceMac) {
addMAC = true; addMAC = true;
} }
if (addMAC) if (addMAC) {
*macBytes = 8; *macBytes = 8;
else } else {
*macBytes = 0; *macBytes = 0;
}
// xgroup(setup) // xgroup(setup)
cout << _( cout << _(
@ -893,9 +900,13 @@ static void selectBlockMAC(int *macBytes, int *macRandBytes, bool forceMac) {
char *res = fgets(answer, sizeof(answer), stdin); char *res = fgets(answer, sizeof(answer), stdin);
cout << "\n"; cout << "\n";
randSize = (res == 0 ? 0 : atoi(answer)); randSize = (res == nullptr ? 0 : atoi(answer));
if (randSize < 0) randSize = 0; if (randSize < 0) {
if (randSize > 8) randSize = 8; randSize = 0;
}
if (randSize > 8) {
randSize = 8;
}
*macRandBytes = randSize; *macRandBytes = randSize;
} }
@ -976,7 +987,9 @@ RootPtr createV6Config(EncFS_Context *ctx,
" anything else, or an empty line will select standard mode.\n" " anything else, or an empty line will select standard mode.\n"
"?> "); "?> ");
if (annotate) cerr << "$PROMPT$ config_option" << endl; if (annotate) {
cerr << "$PROMPT$ config_option" << endl;
}
char *res = fgets(answer, sizeof(answer), stdin); char *res = fgets(answer, sizeof(answer), stdin);
(void)res; (void)res;
@ -1055,7 +1068,9 @@ RootPtr createV6Config(EncFS_Context *ctx,
/* Reverse mounts are read-only by default (set in main.cpp). /* Reverse mounts are read-only by default (set in main.cpp).
* If uniqueIV is off, writing can be allowed, because there * If uniqueIV is off, writing can be allowed, because there
* is no header that could be overwritten */ * is no header that could be overwritten */
if (uniqueIV == false) opts->readOnly = false; if (!uniqueIV) {
opts->readOnly = false;
}
} }
} }
@ -1083,13 +1098,15 @@ RootPtr createV6Config(EncFS_Context *ctx,
/* Reverse mounts are read-only by default (set in main.cpp). /* Reverse mounts are read-only by default (set in main.cpp).
* If uniqueIV is off, writing can be allowed, because there * If uniqueIV is off, writing can be allowed, because there
* is no header that could be overwritten */ * is no header that could be overwritten */
if (uniqueIV == false) opts->readOnly = false; if (!uniqueIV) {
opts->readOnly = false;
}
} else { } else {
chainedIV = selectChainedIV(); chainedIV = selectChainedIV();
uniqueIV = selectUniqueIV(true); uniqueIV = selectUniqueIV(true);
if (chainedIV && uniqueIV) if (chainedIV && uniqueIV) {
externalIV = selectExternalChainedIV(); externalIV = selectExternalChainedIV();
else { } else {
// xgroup(setup) // xgroup(setup)
cout << _("External chained IV disabled, as both 'IV chaining'\n" cout << _("External chained IV disabled, as both 'IV chaining'\n"
"and 'unique IV' features are required for this option.") "and 'unique IV' features are required for this option.")
@ -1107,10 +1124,9 @@ RootPtr createV6Config(EncFS_Context *ctx,
_("Unable to instanciate cipher %s, key size %i, block size %i"), _("Unable to instanciate cipher %s, key size %i, block size %i"),
alg.name.c_str(), keySize, blockSize); alg.name.c_str(), keySize, blockSize);
return rootInfo; return rootInfo;
} else {
VLOG(1) << "Using cipher " << alg.name << ", key size " << keySize
<< ", block size " << blockSize;
} }
VLOG(1) << "Using cipher " << alg.name << ", key size " << keySize
<< ", block size " << blockSize;
std::shared_ptr<EncFSConfig> config(new EncFSConfig); std::shared_ptr<EncFSConfig> config(new EncFSConfig);
@ -1160,7 +1176,7 @@ RootPtr createV6Config(EncFS_Context *ctx,
"later using encfsctl.\n\n"); "later using encfsctl.\n\n");
int encodedKeySize = cipher->encodedKeySize(); int encodedKeySize = cipher->encodedKeySize();
unsigned char *encodedKey = new unsigned char[encodedKeySize]; auto *encodedKey = new unsigned char[encodedKeySize];
CipherKey volumeKey = cipher->newRandomKey(); CipherKey volumeKey = cipher->newRandomKey();
@ -1168,12 +1184,15 @@ RootPtr createV6Config(EncFS_Context *ctx,
CipherKey userKey; CipherKey userKey;
VLOG(1) << "useStdin: " << useStdin; VLOG(1) << "useStdin: " << useStdin;
if (useStdin) { if (useStdin) {
if (annotate) cerr << "$PROMPT$ new_passwd" << endl; if (annotate) {
cerr << "$PROMPT$ new_passwd" << endl;
}
userKey = config->getUserKey(useStdin); userKey = config->getUserKey(useStdin);
} else if (!passwordProgram.empty()) } else if (!passwordProgram.empty()) {
userKey = config->getUserKey(passwordProgram, rootDir); userKey = config->getUserKey(passwordProgram, rootDir);
else } else {
userKey = config->getNewUserKey(); userKey = config->getNewUserKey();
}
cipher->writeKey(volumeKey, encodedKey, userKey); cipher->writeKey(volumeKey, encodedKey, userKey);
userKey.reset(); userKey.reset();
@ -1215,11 +1234,10 @@ RootPtr createV6Config(EncFS_Context *ctx,
fsConfig->idleTracking = enableIdleTracking; fsConfig->idleTracking = enableIdleTracking;
fsConfig->opts = opts; fsConfig->opts = opts;
rootInfo = RootPtr(new EncFS_Root); rootInfo = std::make_shared<encfs::EncFS_Root>();
rootInfo->cipher = cipher; rootInfo->cipher = cipher;
rootInfo->volumeKey = volumeKey; rootInfo->volumeKey = volumeKey;
rootInfo->root = rootInfo->root = std::make_shared<DirNode>(ctx, rootDir, fsConfig);
std::shared_ptr<DirNode>(new DirNode(ctx, rootDir, fsConfig));
return rootInfo; return rootInfo;
} }
@ -1233,17 +1251,18 @@ void showFSInfo(const EncFSConfig *config) {
config->cipherIface.name().c_str(), config->cipherIface.current(), config->cipherIface.name().c_str(), config->cipherIface.current(),
config->cipherIface.revision(), config->cipherIface.age()); config->cipherIface.revision(), config->cipherIface.age());
// check if we support this interface.. // check if we support this interface..
if (!cipher) if (!cipher) {
cout << _(" (NOT supported)\n"); cout << _(" (NOT supported)\n");
else { } else {
// if we're using a newer interface, show the version number // if we're using a newer interface, show the version number
if (config->cipherIface != cipher->interface()) { if (config->cipherIface != cipher->interface()) {
Interface iface = cipher->interface(); Interface iface = cipher->interface();
// xgroup(diag) // xgroup(diag)
cout << autosprintf(_(" (using %i:%i:%i)\n"), iface.current(), cout << autosprintf(_(" (using %i:%i:%i)\n"), iface.current(),
iface.revision(), iface.age()); iface.revision(), iface.age());
} else } else {
cout << "\n"; cout << "\n";
}
} }
} }
{ {
@ -1265,8 +1284,9 @@ void showFSInfo(const EncFSConfig *config) {
Interface iface = nameCoder->interface(); Interface iface = nameCoder->interface();
cout << autosprintf(_(" (using %i:%i:%i)\n"), iface.current(), cout << autosprintf(_(" (using %i:%i:%i)\n"), iface.current(),
iface.revision(), iface.age()); iface.revision(), iface.age());
} else } else {
cout << "\n"; cout << "\n";
}
} }
} }
{ {
@ -1275,17 +1295,18 @@ void showFSInfo(const EncFSConfig *config) {
if (!cipher) { if (!cipher) {
// xgroup(diag) // xgroup(diag)
cout << _(" (NOT supported)\n"); cout << _(" (NOT supported)\n");
} else } else {
cout << "\n"; cout << "\n";
}
} }
if (config->kdfIterations > 0 && config->salt.size() > 0) { if (config->kdfIterations > 0 && !config->salt.empty()) {
cout << autosprintf(_("Using PBKDF2, with %i iterations"), cout << autosprintf(_("Using PBKDF2, with %i iterations"),
config->kdfIterations) config->kdfIterations)
<< "\n"; << "\n";
cout << autosprintf(_("Salt Size: %i bits"), (int)(8 * config->salt.size())) cout << autosprintf(_("Salt Size: %i bits"), (int)(8 * config->salt.size()))
<< "\n"; << "\n";
} }
if (config->blockMACBytes || config->blockMACRandBytes) { if ((config->blockMACBytes != 0) || (config->blockMACRandBytes != 0)) {
if (config->subVersion < 20040813) { if (config->subVersion < 20040813) {
cout << autosprintf( cout << autosprintf(
// xgroup(diag) // xgroup(diag)
@ -1361,12 +1382,12 @@ CipherKey EncFSConfig::makeKey(const char *password, int passwdLen) {
// if no salt is set and we're creating a new password for a new // if no salt is set and we're creating a new password for a new
// FS type, then initialize salt.. // FS type, then initialize salt..
if (salt.size() == 0 && kdfIterations == 0 && cfgType >= Config_V6) { if (salt.empty() && kdfIterations == 0 && cfgType >= Config_V6) {
// upgrade to using salt // upgrade to using salt
salt.resize(20); salt.resize(20);
} }
if (salt.size() > 0) { if (!salt.empty()) {
// if iterations isn't known, then we're creating a new key, so // if iterations isn't known, then we're creating a new key, so
// randomize the salt.. // randomize the salt..
if (kdfIterations == 0 && if (kdfIterations == 0 &&
@ -1391,8 +1412,9 @@ CipherKey EncFSConfig::getUserKey(bool useStdin) {
if (useStdin) { if (useStdin) {
res = fgets(passBuf, sizeof(passBuf), stdin); res = fgets(passBuf, sizeof(passBuf), stdin);
// Kill the trailing newline. // Kill the trailing newline.
if (passBuf[strlen(passBuf) - 1] == '\n') if (passBuf[strlen(passBuf) - 1] == '\n') {
passBuf[strlen(passBuf) - 1] = '\0'; passBuf[strlen(passBuf) - 1] = '\0';
}
} else { } else {
// xgroup(common) // xgroup(common)
res = readpassphrase(_("EncFS Password: "), passBuf, sizeof(passBuf), res = readpassphrase(_("EncFS Password: "), passBuf, sizeof(passBuf),
@ -1400,7 +1422,7 @@ CipherKey EncFSConfig::getUserKey(bool useStdin) {
} }
CipherKey userKey; CipherKey userKey;
if (!res) { if (res == nullptr) {
cerr << _("fatal: error reading password\n"); cerr << _("fatal: error reading password\n");
exit(1); exit(1);
} else { } else {
@ -1416,21 +1438,23 @@ std::string readPassword(int FD) {
char buffer[1024]; char buffer[1024];
string result; string result;
while (1) { while (true) {
ssize_t rdSize = recv(FD, buffer, sizeof(buffer), 0); ssize_t rdSize = recv(FD, buffer, sizeof(buffer), 0);
if (rdSize > 0) { if (rdSize > 0) {
result.append(buffer, rdSize); result.append(buffer, rdSize);
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
} else } else {
break; break;
}
} }
// chop off trailing "\n" if present.. // chop off trailing "\n" if present..
// This is done so that we can use standard programs like ssh-askpass // This is done so that we can use standard programs like ssh-askpass
// without modification, as it returns trailing newline.. // without modification, as it returns trailing newline..
if (!result.empty() && result[result.length() - 1] == '\n') if (!result.empty() && result[result.length() - 1] == '\n') {
result.resize(result.length() - 1); result.resize(result.length() - 1);
}
return result; return result;
} }
@ -1462,7 +1486,7 @@ CipherKey EncFSConfig::getUserKey(const std::string &passProg,
argv[0] = "/bin/sh"; argv[0] = "/bin/sh";
argv[1] = "-c"; argv[1] = "-c";
argv[2] = passProg.c_str(); argv[2] = passProg.c_str();
argv[3] = 0; argv[3] = nullptr;
// child process.. run the command and send output to fds[0] // child process.. run the command and send output to fds[0]
close(fds[1]); // we don't use the other half.. close(fds[1]); // we don't use the other half..
@ -1500,7 +1524,7 @@ CipherKey EncFSConfig::getUserKey(const std::string &passProg,
string password = readPassword(fds[1]); string password = readPassword(fds[1]);
close(fds[1]); close(fds[1]);
waitpid(pid, NULL, 0); waitpid(pid, nullptr, 0);
// convert to key.. // convert to key..
result = makeKey(password.c_str(), password.length()); result = makeKey(password.c_str(), password.length());
@ -1524,7 +1548,8 @@ CipherKey EncFSConfig::getNewUserKey() {
char *res2 = readpassphrase(_("Verify Encfs Password: "), passBuf2, char *res2 = readpassphrase(_("Verify Encfs Password: "), passBuf2,
sizeof(passBuf2) - 1, RPP_ECHO_OFF); sizeof(passBuf2) - 1, RPP_ECHO_OFF);
if (res1 && res2 && !strcmp(passBuf, passBuf2)) { if ((res1 != nullptr) && (res2 != nullptr) &&
(strcmp(passBuf, passBuf2) == 0)) {
userKey = makeKey(passBuf, strlen(passBuf)); userKey = makeKey(passBuf, strlen(passBuf));
} else { } else {
// xgroup(common) -- probably not common, but group with the others // xgroup(common) -- probably not common, but group with the others
@ -1559,7 +1584,9 @@ RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts) {
/* Reverse mounts are read-only by default (set in main.cpp). /* Reverse mounts are read-only by default (set in main.cpp).
* If uniqueIV is off, writing can be allowed, because there * If uniqueIV is off, writing can be allowed, because there
* is no header that could be overwritten */ * is no header that could be overwritten */
if (config->uniqueIV == false) opts->readOnly = false; if (!config->uniqueIV) {
opts->readOnly = false;
}
} }
// first, instanciate the cipher. // first, instanciate the cipher.
@ -1575,7 +1602,7 @@ RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts) {
} }
if (opts->delayMount) { if (opts->delayMount) {
rootInfo = RootPtr(new EncFS_Root); rootInfo = std::make_shared<encfs::EncFS_Root>();
rootInfo->cipher = cipher; rootInfo->cipher = cipher;
rootInfo->root = std::shared_ptr<DirNode>(); rootInfo->root = std::shared_ptr<DirNode>();
return rootInfo; return rootInfo;
@ -1586,12 +1613,17 @@ RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts) {
if (opts->passwordProgram.empty()) { if (opts->passwordProgram.empty()) {
VLOG(1) << "useStdin: " << opts->useStdin; VLOG(1) << "useStdin: " << opts->useStdin;
if (opts->annotate) cerr << "$PROMPT$ passwd" << endl; if (opts->annotate) {
cerr << "$PROMPT$ passwd" << endl;
}
userKey = config->getUserKey(opts->useStdin); userKey = config->getUserKey(opts->useStdin);
} else } else {
userKey = config->getUserKey(opts->passwordProgram, opts->rootDir); userKey = config->getUserKey(opts->passwordProgram, opts->rootDir);
}
if (!userKey) return rootInfo; if (!userKey) {
return rootInfo;
}
VLOG(1) << "cipher key size = " << cipher->encodedKeySize(); VLOG(1) << "cipher key size = " << cipher->encodedKeySize();
// decode volume key.. // decode volume key..
@ -1631,11 +1663,10 @@ RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts) {
fsConfig->reverseEncryption = opts->reverseEncryption; fsConfig->reverseEncryption = opts->reverseEncryption;
fsConfig->opts = opts; fsConfig->opts = opts;
rootInfo = RootPtr(new EncFS_Root); rootInfo = std::make_shared<encfs::EncFS_Root>();
rootInfo->cipher = cipher; rootInfo->cipher = cipher;
rootInfo->volumeKey = volumeKey; rootInfo->volumeKey = volumeKey;
rootInfo->root = rootInfo->root = std::make_shared<DirNode>(ctx, opts->rootDir, fsConfig);
std::shared_ptr<DirNode>(new DirNode(ctx, opts->rootDir, fsConfig));
} else { } else {
if (opts->createIfNotFound) { if (opts->createIfNotFound) {
// creating a new encrypted filesystem // creating a new encrypted filesystem
@ -1653,10 +1684,9 @@ int remountFS(EncFS_Context *ctx) {
if (rootInfo) { if (rootInfo) {
ctx->setRoot(rootInfo->root); ctx->setRoot(rootInfo->root);
return 0; return 0;
} else {
RLOG(WARNING) << "Remount failed";
return -EACCES;
} }
RLOG(WARNING) << "Remount failed";
return -EACCES;
} }
} // namespace encfs } // namespace encfs

View File

@ -60,7 +60,7 @@ struct EncFS_Root {
~EncFS_Root(); ~EncFS_Root();
}; };
typedef std::shared_ptr<EncFS_Root> RootPtr; using RootPtr = std::shared_ptr<EncFS_Root>;
enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia }; enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia };

View File

@ -20,6 +20,8 @@
#include "Interface.h" #include "Interface.h"
#include <utility>
#include "ConfigVar.h" #include "ConfigVar.h"
#include "Error.h" #include "Error.h"
@ -28,25 +30,19 @@ namespace encfs {
Interface::Interface(const char *name_, int Current, int Revision, int Age) Interface::Interface(const char *name_, int Current, int Revision, int Age)
: _name(name_), _current(Current), _revision(Revision), _age(Age) {} : _name(name_), _current(Current), _revision(Revision), _age(Age) {}
Interface::Interface(const std::string &name_, int Current, int Revision, Interface::Interface(std::string name_, int Current, int Revision, int Age)
int Age) : _name(std::move(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),
_current(src._current), = default;
_revision(src._revision),
_age(src._age) {}
Interface::Interface() : _current(0), _revision(0), _age(0) {} Interface::Interface() : _current(0), _revision(0), _age(0) {}
Interface &Interface::operator=(const Interface &src) { Interface &Interface::operator=(const Interface &src) = default;
_name = src._name;
_current = src._current;
_revision = src._revision;
_age = src._age;
return *this;
}
const std::string &Interface::name() const { return _name; } const std::string &Interface::name() const { return _name; }
@ -87,12 +83,13 @@ 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) }
if (a == b) {
return 1; return 1;
else }
return 2; return 2;
} }
#endif #endif
@ -111,7 +108,9 @@ bool Interface::implements(const Interface &B) const {
<< ":" << age() << ") implements " << B.name() << "(" << B.current() << ":" << age() << ") implements " << B.name() << "(" << B.current()
<< ":" << B.revision() << ")"; << ":" << B.revision() << ")";
if (name() != B.name()) return false; if (name() != B.name()) {
return false;
}
int currentDiff = current() - B.current(); int currentDiff = current() - B.current();
return (currentDiff >= 0 && currentDiff <= age()); return (currentDiff >= 0 && currentDiff <= age());
@ -120,29 +119,29 @@ bool Interface::implements(const Interface &B) const {
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); return (diffSum(A, B) < EqualVersion);
} else }
return A.name() < B.name(); 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); return (diffSum(A, B) > EqualVersion);
} else }
return A.name() < B.name(); 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); return (diffSum(A, B) <= EqualVersion);
} else }
return A.name() < B.name(); 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); return (diffSum(A, B) >= EqualVersion);
} else }
return A.name() < B.name(); return A.name() < B.name();
} }
ConfigVar &operator<<(ConfigVar &dst, const Interface &iface) { ConfigVar &operator<<(ConfigVar &dst, const Interface &iface) {

View File

@ -37,7 +37,7 @@ class Interface {
are implemented. are implemented.
*/ */
Interface(const char *name, int Current, int Revision, int Age); Interface(const char *name, int Current, int Revision, int Age);
Interface(const std::string &name, int Current, int Revision, int Age); Interface(std::string name, int Current, int Revision, int Age);
Interface(const Interface &src); Interface(const Interface &src);
Interface(); Interface();

View File

@ -21,9 +21,10 @@
#include "MACFileIO.h" #include "MACFileIO.h"
#include "internal/easylogging++.h" #include "internal/easylogging++.h"
#include <cinttypes>
#include <cstring> #include <cstring>
#include <inttypes.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <utility>
#include "BlockFileIO.h" #include "BlockFileIO.h"
#include "Cipher.h" #include "Cipher.h"
@ -56,10 +57,9 @@ int dataBlockSize(const FSConfigPtr &cfg) {
cfg->config->blockMACRandBytes; cfg->config->blockMACRandBytes;
} }
MACFileIO::MACFileIO(const std::shared_ptr<FileIO> &_base, MACFileIO::MACFileIO(std::shared_ptr<FileIO> _base, const FSConfigPtr &cfg)
const FSConfigPtr &cfg)
: BlockFileIO(dataBlockSize(cfg), cfg), : BlockFileIO(dataBlockSize(cfg), cfg),
base(_base), base(std::move(_base)),
cipher(cfg->cipher), cipher(cfg->cipher),
key(cfg->key), key(cfg->key),
macBytes(cfg->config->blockMACBytes), macBytes(cfg->config->blockMACBytes),
@ -72,7 +72,7 @@ MACFileIO::MACFileIO(const std::shared_ptr<FileIO> &_base,
<< ", randBytes = " << cfg->config->blockMACRandBytes; << ", randBytes = " << cfg->config->blockMACRandBytes;
} }
MACFileIO::~MACFileIO() {} MACFileIO::~MACFileIO() = default;
Interface MACFileIO::interface() const { return MACFileIO_iface; } Interface MACFileIO::interface() const { return MACFileIO_iface; }
@ -137,7 +137,9 @@ off_t MACFileIO::getSize() const {
int bs = blockSize() + headerSize; int bs = blockSize() + headerSize;
off_t size = base->getSize(); off_t size = base->getSize();
if (size > 0) size = locWithoutHeader(size, bs, headerSize); if (size > 0) {
size = locWithoutHeader(size, bs, headerSize);
}
return size; return size;
} }
@ -160,13 +162,15 @@ ssize_t MACFileIO::readOneBlock(const IORequest &req) const {
// don't store zeros if configured for zero-block pass-through // don't store zeros if configured for zero-block pass-through
bool skipBlock = true; bool skipBlock = true;
if (_allowHoles) { if (_allowHoles) {
for (int i = 0; i < readSize; ++i) for (int i = 0; i < readSize; ++i) {
if (tmp.data[i] != 0) { if (tmp.data[i] != 0) {
skipBlock = false; skipBlock = false;
break; break;
} }
} else if (macBytes > 0) }
} else if (macBytes > 0) {
skipBlock = false; skipBlock = false;
}
if (readSize > headerSize) { if (readSize > headerSize) {
if (!skipBlock) { if (!skipBlock) {
@ -200,7 +204,9 @@ ssize_t MACFileIO::readOneBlock(const IORequest &req) const {
memcpy(req.data, tmp.data + headerSize, readSize); memcpy(req.data, tmp.data + headerSize, readSize);
} else { } else {
VLOG(1) << "readSize " << readSize << " at offset " << req.offset; VLOG(1) << "readSize " << readSize << " at offset " << req.offset;
if (readSize > 0) readSize = 0; if (readSize > 0) {
readSize = 0;
}
} }
MemoryPool::release(mb); MemoryPool::release(mb);
@ -224,8 +230,9 @@ bool MACFileIO::writeOneBlock(const IORequest &req) {
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) { if (macBytes > 0) {
@ -251,9 +258,11 @@ 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, nullptr);
if (res == 0) base->truncate(locWithHeader(size, bs, headerSize)); if (res == 0) {
base->truncate(locWithHeader(size, bs, headerSize));
}
return res; return res;
} }

View File

@ -44,7 +44,7 @@ class MACFileIO : public BlockFileIO {
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 std::shared_ptr<FileIO> &base, const FSConfigPtr &cfg); MACFileIO(std::shared_ptr<FileIO> base, const FSConfigPtr &cfg);
MACFileIO(); MACFileIO();
virtual ~MACFileIO(); virtual ~MACFileIO();

View File

@ -44,7 +44,7 @@ struct BlockList {
}; };
static BlockList *allocBlock(int size) { static BlockList *allocBlock(int size) {
BlockList *block = new BlockList; auto *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);
@ -61,30 +61,33 @@ static void freeBlock(BlockList *el) {
} }
static pthread_mutex_t gMPoolMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t gMPoolMutex = PTHREAD_MUTEX_INITIALIZER;
static BlockList *gMemPool = NULL; static BlockList *gMemPool = nullptr;
MemBlock MemoryPool::allocate(int size) { MemBlock MemoryPool::allocate(int size) {
pthread_mutex_lock(&gMPoolMutex); pthread_mutex_lock(&gMPoolMutex);
BlockList *parent = NULL; BlockList *parent = nullptr;
BlockList *block = gMemPool; BlockList *block = gMemPool;
// check if we already have a large enough block available.. // check if we already have a large enough block available..
while (block != NULL && block->size < size) { while (block != nullptr && block->size < size) {
parent = block; parent = block;
block = block->next; block = block->next;
} }
// unlink block from list // unlink block from list
if (block) { if (block != nullptr) {
if (!parent) if (parent == nullptr) {
gMemPool = block->next; gMemPool = block->next;
else } else {
parent->next = block->next; parent->next = block->next;
}
} }
pthread_mutex_unlock(&gMPoolMutex); pthread_mutex_unlock(&gMPoolMutex);
if (!block) block = allocBlock(size); if (block == nullptr) {
block->next = NULL; block = allocBlock(size);
}
block->next = nullptr;
MemBlock result; MemBlock result;
result.data = BLOCKDATA(block); result.data = BLOCKDATA(block);
@ -98,7 +101,7 @@ MemBlock MemoryPool::allocate(int size) {
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; auto *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);
@ -115,11 +118,11 @@ void MemoryPool::destroyAll() {
pthread_mutex_lock(&gMPoolMutex); pthread_mutex_lock(&gMPoolMutex);
BlockList *block = gMemPool; BlockList *block = gMemPool;
gMemPool = NULL; gMemPool = nullptr;
pthread_mutex_unlock(&gMPoolMutex); pthread_mutex_unlock(&gMPoolMutex);
while (block != NULL) { while (block != nullptr) {
BlockList *next = block->next; BlockList *next = block->next;
freeBlock(block); freeBlock(block);

View File

@ -55,14 +55,14 @@ struct NameIOAlg {
Interface iface; Interface iface;
}; };
typedef multimap<string, NameIOAlg> NameIOMap_t; using NameIOMap_t = multimap<string, NameIOAlg>;
static NameIOMap_t *gNameIOMap = 0; static NameIOMap_t *gNameIOMap = nullptr;
list<NameIO::Algorithm> NameIO::GetAlgorithmList(bool includeHidden) { list<NameIO::Algorithm> NameIO::GetAlgorithmList(bool includeHidden) {
AddSymbolReferences(); AddSymbolReferences();
list<Algorithm> result; list<Algorithm> result;
if (gNameIOMap) { if (gNameIOMap != nullptr) {
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) {
@ -83,7 +83,9 @@ list<NameIO::Algorithm> NameIO::GetAlgorithmList(bool includeHidden) {
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 == nullptr) {
gNameIOMap = new NameIOMap_t;
}
NameIOAlg alg; NameIOAlg alg;
alg.hidden = hidden; alg.hidden = hidden;
@ -98,7 +100,7 @@ std::shared_ptr<NameIO> NameIO::New(const string &name,
const std::shared_ptr<Cipher> &cipher, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key) { const CipherKey &key) {
std::shared_ptr<NameIO> result; std::shared_ptr<NameIO> result;
if (gNameIOMap) { if (gNameIOMap != nullptr) {
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; Constructor fn = it->second.constructor;
@ -111,7 +113,7 @@ std::shared_ptr<NameIO> NameIO::New(const Interface &iface,
const std::shared_ptr<Cipher> &cipher, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key) { const CipherKey &key) {
std::shared_ptr<NameIO> result; std::shared_ptr<NameIO> result;
if (gNameIOMap) { if (gNameIOMap != nullptr) {
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) {
@ -127,7 +129,7 @@ std::shared_ptr<NameIO> NameIO::New(const Interface &iface,
NameIO::NameIO() : chainedNameIV(false), reverseEncryption(false) {} NameIO::NameIO() : chainedNameIV(false), reverseEncryption(false) {}
NameIO::~NameIO() {} NameIO::~NameIO() = default;
void NameIO::setChainedNameIV(bool enable) { chainedNameIV = enable; } void NameIO::setChainedNameIV(bool enable) { chainedNameIV = enable; }
@ -143,15 +145,16 @@ std::string NameIO::recodePath(
uint64_t *iv) const { uint64_t *iv) const {
string output; string output;
while (*path) { while (*path != 0) {
if (*path == '/') { if (*path == '/') {
if (!output.empty()) // don't start the string with '/' if (!output.empty()) { // don't start the string with '/'
output += '/'; output += '/';
}
++path; ++path;
} else { } else {
bool isDotFile = (*path == '.'); bool isDotFile = (*path == '.');
const char *next = strchr(path, '/'); const char *next = strchr(path, '/');
int len = next ? next - path : strlen(path); int len = next != nullptr ? next - path : strlen(path);
// at this point we know that len > 0 // at this point we know that len > 0
if (isDotFile && (path[len - 1] == '.') && (len <= 2)) { if (isDotFile && (path[len - 1] == '.') && (len <= 2)) {
@ -162,7 +165,9 @@ std::string NameIO::recodePath(
// figure out buffer sizes // figure out buffer sizes
int approxLen = (this->*_length)(len); int approxLen = (this->*_length)(len);
if (approxLen <= 0) throw Error("Filename too small to decode"); if (approxLen <= 0) {
throw Error("Filename too small to decode");
}
int bufSize = 0; int bufSize = 0;
BUFFER_INIT_S(codeBuf, 32, (unsigned int)approxLen + 1, bufSize) BUFFER_INIT_S(codeBuf, 32, (unsigned int)approxLen + 1, bufSize)
@ -195,14 +200,18 @@ std::string NameIO::decodePath(const char *cipherPath) const {
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) {
iv = nullptr;
}
return recodePath(plaintextPath, &NameIO::maxEncodedNameLen, return recodePath(plaintextPath, &NameIO::maxEncodedNameLen,
&NameIO::encodeName, iv); &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) {
iv = nullptr;
}
return recodePath(cipherPath, &NameIO::maxDecodedNameLen, &NameIO::decodeName, return recodePath(cipherPath, &NameIO::maxDecodedNameLen, &NameIO::decodeName,
iv); iv);
} }
@ -217,12 +226,12 @@ std::string NameIO::decodePath(const char *path, uint64_t *iv) const {
int NameIO::encodeName(const char *input, int length, char *output, int NameIO::encodeName(const char *input, int length, char *output,
int bufferLength) const { int bufferLength) const {
return encodeName(input, length, (uint64_t *)0, output, bufferLength); return encodeName(input, length, (uint64_t *)nullptr, output, bufferLength);
} }
int NameIO::decodeName(const char *input, int length, char *output, int NameIO::decodeName(const char *input, int length, char *output,
int bufferLength) const { int bufferLength) const {
return decodeName(input, length, (uint64_t *)0, output, bufferLength); return decodeName(input, length, (uint64_t *)nullptr, output, bufferLength);
} }
std::string NameIO::_encodeName(const char *plaintextName, int length) const { std::string NameIO::_encodeName(const char *plaintextName, int length) const {
@ -232,7 +241,7 @@ std::string NameIO::_encodeName(const char *plaintextName, int length) const {
BUFFER_INIT_S(codeBuf, 32, (unsigned int)approxLen + 1, bufSize) BUFFER_INIT_S(codeBuf, 32, (unsigned int)approxLen + 1, bufSize)
// code the name // code the name
int codedLen = encodeName(plaintextName, length, 0, codeBuf, bufSize); int codedLen = encodeName(plaintextName, length, nullptr, codeBuf, bufSize);
rAssert(codedLen <= approxLen); rAssert(codedLen <= approxLen);
rAssert(codeBuf[codedLen] == '\0'); rAssert(codeBuf[codedLen] == '\0');
@ -251,7 +260,7 @@ std::string NameIO::_decodeName(const char *encodedName, int length) const {
BUFFER_INIT_S(codeBuf, 32, (unsigned int)approxLen + 1, bufSize) BUFFER_INIT_S(codeBuf, 32, (unsigned int)approxLen + 1, bufSize)
// code the name // code the name
int codedLen = decodeName(encodedName, length, 0, codeBuf, bufSize); int codedLen = decodeName(encodedName, length, nullptr, codeBuf, bufSize);
rAssert(codedLen <= approxLen); rAssert(codedLen <= approxLen);
rAssert(codeBuf[codedLen] == '\0'); rAssert(codeBuf[codedLen] == '\0');

View File

@ -37,7 +37,7 @@ class Cipher;
class NameIO { class NameIO {
public: public:
typedef std::shared_ptr<NameIO> (*Constructor)( using Constructor = std::shared_ptr<NameIO> (*)(
const Interface &iface, const std::shared_ptr<Cipher> &cipher, const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key); const CipherKey &key);
@ -47,7 +47,7 @@ class NameIO {
Interface iface; Interface iface;
}; };
typedef std::list<Algorithm> AlgorithmList; using AlgorithmList = std::list<Algorithm>;
static AlgorithmList GetAlgorithmList(bool includeHidden = false); static AlgorithmList GetAlgorithmList(bool includeHidden = false);
static std::shared_ptr<NameIO> New(const Interface &iface, static std::shared_ptr<NameIO> New(const Interface &iface,
@ -139,7 +139,7 @@ class NameIO {
delete[] Name; \ delete[] Name; \
Name = Name##_Raw; \ Name = Name##_Raw; \
} \ } \
} while (0); } while (false);
} // namespace encfs } // namespace encfs

View File

@ -49,24 +49,24 @@ static bool NullCipher_registered = Cipher::Register(
class NullKey : public AbstractCipherKey { class NullKey : public AbstractCipherKey {
public: public:
NullKey() {} NullKey() = default;
virtual ~NullKey() {} ~NullKey() override = default;
}; };
class NullDestructor { class NullDestructor {
public: public:
NullDestructor() {} NullDestructor() = default;
NullDestructor(const NullDestructor &) {} NullDestructor(const NullDestructor &) = default;
~NullDestructor() {} ~NullDestructor() = default;
NullDestructor &operator=(const NullDestructor &) { return *this; } NullDestructor &operator=(const NullDestructor &) = default;
void operator()(NullKey *&) {} void operator()(NullKey *&) {}
}; };
std::shared_ptr<AbstractCipherKey> gNullKey(new NullKey(), NullDestructor()); std::shared_ptr<AbstractCipherKey> gNullKey(new NullKey(), NullDestructor());
NullCipher::NullCipher(const Interface &iface_) { this->iface = iface_; } NullCipher::NullCipher(const Interface &iface_) { this->iface = iface_; }
NullCipher::~NullCipher() {} NullCipher::~NullCipher() = default;
Interface NullCipher::interface() const { return iface; } Interface NullCipher::interface() const { return iface; }

View File

@ -41,9 +41,9 @@ static Interface NNIOIface("nameio/null", 1, 0, 0);
static bool NullNameIO_registered = static bool NullNameIO_registered =
NameIO::Register("Null", "No encryption of filenames", NNIOIface, NewNNIO); NameIO::Register("Null", "No encryption of filenames", NNIOIface, NewNNIO);
NullNameIO::NullNameIO() {} NullNameIO::NullNameIO() = default;
NullNameIO::~NullNameIO() {} NullNameIO::~NullNameIO() = default;
Interface NullNameIO::interface() const { return NNIOIface; } Interface NullNameIO::interface() const { return NNIOIface; }

View File

@ -23,11 +23,12 @@
#endif #endif
#include "internal/easylogging++.h" #include "internal/easylogging++.h"
#include <cerrno> #include <cerrno>
#include <cinttypes>
#include <cstring> #include <cstring>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <utility>
#include "Error.h" #include "Error.h"
#include "FileIO.h" #include "FileIO.h"
@ -53,8 +54,8 @@ inline void swap(int &x, int &y) {
RawFileIO::RawFileIO() RawFileIO::RawFileIO()
: knownSize(false), fileSize(0), fd(-1), oldfd(-1), canWrite(false) {} : knownSize(false), fileSize(0), fd(-1), oldfd(-1), canWrite(false) {}
RawFileIO::RawFileIO(const std::string &fileName) RawFileIO::RawFileIO(std::string fileName)
: name(fileName), : name(std::move(fileName)),
knownSize(false), knownSize(false),
fileSize(0), fileSize(0),
fd(-1), fd(-1),
@ -68,9 +69,13 @@ RawFileIO::~RawFileIO() {
swap(_fd, fd); swap(_fd, fd);
swap(_oldfd, oldfd); swap(_oldfd, oldfd);
if (_oldfd != -1) close(_oldfd); if (_oldfd != -1) {
close(_oldfd);
}
if (_fd != -1) close(_fd); if (_fd != -1) {
close(_fd);
}
} }
Interface RawFileIO::interface() const { return RawFileIO_iface; } Interface RawFileIO::interface() const { return RawFileIO_iface; }
@ -112,7 +117,7 @@ static int open_readonly_workaround(const char *path, int flags) {
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) != 0) || ((flags & O_WRONLY) != 0));
VLOG(1) << "open call, requestWrite = " << requestWrite; VLOG(1) << "open call, requestWrite = " << requestWrite;
int result = 0; int result = 0;
@ -125,7 +130,9 @@ int RawFileIO::open(int flags) {
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) finalFlags |= O_LARGEFILE; if ((flags & O_LARGEFILE) != 0) {
finalFlags |= O_LARGEFILE;
}
#else #else
#warning O_LARGEFILE not supported #warning O_LARGEFILE not supported
#endif #endif
@ -184,13 +191,11 @@ off_t RawFileIO::getSize() const {
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 {
RLOG(ERROR) << "getSize on " << name << " failed: " << strerror(errno);
return -1;
} }
} else { RLOG(ERROR) << "getSize on " << name << " failed: " << strerror(errno);
return fileSize; return -1;
} }
return fileSize;
} }
ssize_t RawFileIO::read(const IORequest &req) const { ssize_t RawFileIO::read(const IORequest &req) const {
@ -208,14 +213,14 @@ ssize_t RawFileIO::read(const IORequest &req) const {
bool RawFileIO::write(const IORequest &req) { bool RawFileIO::write(const IORequest &req) {
rAssert(fd >= 0); rAssert(fd >= 0);
rAssert(true == canWrite); rAssert(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 != 0) && retrys > 0) {
ssize_t writeSize = ::pwrite(fd, buf, bytes, offset); ssize_t writeSize = ::pwrite(fd, buf, bytes, offset);
if (writeSize < 0) { if (writeSize < 0) {
@ -236,14 +241,15 @@ bool RawFileIO::write(const IORequest &req) {
<< req.dataLen << ", max retries reached"; << req.dataLen << ", max retries reached";
knownSize = false; knownSize = false;
return false; return false;
} else {
if (knownSize) {
off_t last = req.offset + req.dataLen;
if (last > fileSize) fileSize = last;
}
return true;
} }
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) {
@ -254,8 +260,9 @@ int RawFileIO::truncate(off_t 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;

View File

@ -32,7 +32,7 @@ namespace encfs {
class RawFileIO : public FileIO { class RawFileIO : public FileIO {
public: public:
RawFileIO(); RawFileIO();
RawFileIO(const std::string &fileName); RawFileIO(std::string fileName);
virtual ~RawFileIO(); virtual ~RawFileIO();
virtual Interface interface() const; virtual Interface interface() const;

View File

@ -36,8 +36,8 @@
#include "Interface.h" #include "Interface.h"
#include "Mutex.h" #include "Mutex.h"
#include "Range.h" #include "Range.h"
#include "SSL_Compat.h"
#include "SSL_Cipher.h" #include "SSL_Cipher.h"
#include "SSL_Compat.h"
#include "intl/gettext.h" #include "intl/gettext.h"
using namespace std; using namespace std;
@ -66,46 +66,51 @@ inline int MIN(int a, int b) { return (a < b) ? a : b; }
int BytesToKey(int keyLen, int ivLen, const EVP_MD *md, int BytesToKey(int keyLen, int ivLen, const EVP_MD *md,
const unsigned char *data, int dataLen, unsigned int rounds, const unsigned char *data, int dataLen, unsigned int rounds,
unsigned char *key, unsigned char *iv) { unsigned char *key, unsigned char *iv) {
if (data == NULL || dataLen == 0) if (data == nullptr || dataLen == 0) {
return 0; // OpenSSL returns nkey here, but why? It is a failure.. return 0; // OpenSSL returns nkey here, but why? It is a failure..
}
unsigned char mdBuf[EVP_MAX_MD_SIZE]; unsigned char mdBuf[EVP_MAX_MD_SIZE];
unsigned int mds = 0; unsigned int mds = 0;
int addmd = 0; int addmd = 0;
int nkey = key ? keyLen : 0; int nkey = key != nullptr ? keyLen : 0;
int niv = iv ? ivLen : 0; int niv = iv != nullptr ? ivLen : 0;
EVP_MD_CTX *cx = EVP_MD_CTX_new(); EVP_MD_CTX *cx = EVP_MD_CTX_new();
EVP_MD_CTX_init(cx); EVP_MD_CTX_init(cx);
for (;;) { for (;;) {
EVP_DigestInit_ex(cx, md, NULL); EVP_DigestInit_ex(cx, md, nullptr);
if (addmd++) EVP_DigestUpdate(cx, mdBuf, mds); if ((addmd++) != 0) {
EVP_DigestUpdate(cx, mdBuf, mds);
}
EVP_DigestUpdate(cx, data, dataLen); EVP_DigestUpdate(cx, data, dataLen);
EVP_DigestFinal_ex(cx, mdBuf, &mds); EVP_DigestFinal_ex(cx, mdBuf, &mds);
for (unsigned int i = 1; i < rounds; ++i) { for (unsigned int i = 1; i < rounds; ++i) {
EVP_DigestInit_ex(cx, md, NULL); EVP_DigestInit_ex(cx, md, nullptr);
EVP_DigestUpdate(cx, mdBuf, mds); EVP_DigestUpdate(cx, mdBuf, mds);
EVP_DigestFinal_ex(cx, mdBuf, &mds); EVP_DigestFinal_ex(cx, mdBuf, &mds);
} }
int offset = 0; int offset = 0;
int toCopy = MIN(nkey, mds - offset); int toCopy = MIN(nkey, mds - offset);
if (toCopy) { if (toCopy != 0) {
memcpy(key, mdBuf + offset, toCopy); memcpy(key, mdBuf + offset, toCopy);
key += toCopy; key += toCopy;
nkey -= toCopy; nkey -= toCopy;
offset += toCopy; offset += toCopy;
} }
toCopy = MIN(niv, mds - offset); toCopy = MIN(niv, mds - offset);
if (toCopy) { if (toCopy != 0) {
memcpy(iv, mdBuf + offset, toCopy); memcpy(iv, mdBuf + offset, toCopy);
iv += toCopy; iv += toCopy;
niv -= toCopy; niv -= toCopy;
offset += toCopy; offset += toCopy;
} }
if ((nkey == 0) && (niv == 0)) break; if ((nkey == 0) && (niv == 0)) {
break;
}
} }
EVP_MD_CTX_free(cx); EVP_MD_CTX_free(cx);
OPENSSL_cleanse(mdBuf, sizeof(mdBuf)); OPENSSL_cleanse(mdBuf, sizeof(mdBuf));
@ -125,13 +130,15 @@ int TimedPBKDF2(const char *pass, int passlen, const unsigned char *salt,
timeval start, end; timeval start, end;
for (;;) { for (;;) {
gettimeofday(&start, 0); gettimeofday(&start, nullptr);
int res = int res =
PKCS5_PBKDF2_HMAC_SHA1(pass, passlen, const_cast<unsigned char *>(salt), PKCS5_PBKDF2_HMAC_SHA1(pass, passlen, const_cast<unsigned char *>(salt),
saltlen, iter, keylen, out); saltlen, iter, keylen, out);
if (res != 1) return -1; if (res != 1) {
return -1;
}
gettimeofday(&end, 0); gettimeofday(&end, nullptr);
long delta = time_diff(end, start); long delta = time_diff(end, start);
if (delta < desiredPDFTime / 8) { if (delta < desiredPDFTime / 8) {
@ -139,8 +146,9 @@ int TimedPBKDF2(const char *pass, int passlen, const unsigned char *salt,
} else if (delta < (5 * desiredPDFTime / 6)) { } else if (delta < (5 * desiredPDFTime / 6)) {
// estimate number of iterations to get close to desired time // estimate number of iterations to get close to desired time
iter = (int)((double)iter * (double)desiredPDFTime / (double)delta); iter = (int)((double)iter * (double)desiredPDFTime / (double)delta);
} else } else {
return iter; return iter;
}
} }
} }
@ -160,7 +168,9 @@ static Range BFKeyRange(128, 256, 32);
static Range BFBlockRange(64, 4096, 8); static Range BFBlockRange(64, 4096, 8);
static std::shared_ptr<Cipher> NewBFCipher(const Interface &iface, int keyLen) { static std::shared_ptr<Cipher> NewBFCipher(const Interface &iface, int keyLen) {
if (keyLen <= 0) keyLen = 160; if (keyLen <= 0) {
keyLen = 160;
}
keyLen = BFKeyRange.closest(keyLen); keyLen = BFKeyRange.closest(keyLen);
@ -185,12 +195,14 @@ static Range AESBlockRange(64, 4096, 16);
static std::shared_ptr<Cipher> NewAESCipher(const Interface &iface, static std::shared_ptr<Cipher> NewAESCipher(const Interface &iface,
int keyLen) { int keyLen) {
if (keyLen <= 0) keyLen = 192; if (keyLen <= 0) {
keyLen = 192;
}
keyLen = AESKeyRange.closest(keyLen); keyLen = AESKeyRange.closest(keyLen);
const EVP_CIPHER *blockCipher = 0; const EVP_CIPHER *blockCipher = nullptr;
const EVP_CIPHER *streamCipher = 0; const EVP_CIPHER *streamCipher = nullptr;
switch (keyLen) { switch (keyLen) {
case 128: case 128:
@ -238,13 +250,13 @@ class SSLKey : public AbstractCipherKey {
HMAC_CTX *mac_ctx; HMAC_CTX *mac_ctx;
SSLKey(int keySize, int ivLength); SSLKey(int keySize, int ivLength);
~SSLKey(); ~SSLKey() override;
}; };
SSLKey::SSLKey(int keySize_, int ivLength_) { SSLKey::SSLKey(int keySize_, int ivLength_) {
this->keySize = keySize_; this->keySize = keySize_;
this->ivLength = ivLength_; this->ivLength = ivLength_;
pthread_mutex_init(&mutex, 0); pthread_mutex_init(&mutex, nullptr);
buffer = (unsigned char *)OPENSSL_malloc(keySize + ivLength); buffer = (unsigned char *)OPENSSL_malloc(keySize + ivLength);
memset(buffer, 0, keySize + ivLength); memset(buffer, 0, keySize + ivLength);
@ -272,7 +284,7 @@ SSLKey::~SSLKey() {
keySize = 0; keySize = 0;
ivLength = 0; ivLength = 0;
buffer = 0; buffer = nullptr;
EVP_CIPHER_CTX_free(block_enc); EVP_CIPHER_CTX_free(block_enc);
EVP_CIPHER_CTX_free(block_dec); EVP_CIPHER_CTX_free(block_dec);
@ -295,10 +307,10 @@ void initKey(const std::shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher,
Lock lock(key->mutex); Lock lock(key->mutex);
// initialize the cipher context once so that we don't have to do it for // initialize the cipher context once so that we don't have to do it for
// every block.. // every block..
EVP_EncryptInit_ex(key->block_enc, _blockCipher, NULL, NULL, NULL); EVP_EncryptInit_ex(key->block_enc, _blockCipher, nullptr, nullptr, nullptr);
EVP_DecryptInit_ex(key->block_dec, _blockCipher, NULL, NULL, NULL); EVP_DecryptInit_ex(key->block_dec, _blockCipher, nullptr, nullptr, nullptr);
EVP_EncryptInit_ex(key->stream_enc, _streamCipher, NULL, NULL, NULL); EVP_EncryptInit_ex(key->stream_enc, _streamCipher, nullptr, nullptr, nullptr);
EVP_DecryptInit_ex(key->stream_dec, _streamCipher, NULL, NULL, NULL); EVP_DecryptInit_ex(key->stream_dec, _streamCipher, nullptr, nullptr, nullptr);
EVP_CIPHER_CTX_set_key_length(key->block_enc, _keySize); EVP_CIPHER_CTX_set_key_length(key->block_enc, _keySize);
EVP_CIPHER_CTX_set_key_length(key->block_dec, _keySize); EVP_CIPHER_CTX_set_key_length(key->block_dec, _keySize);
@ -310,12 +322,12 @@ void initKey(const std::shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher,
EVP_CIPHER_CTX_set_padding(key->stream_enc, 0); EVP_CIPHER_CTX_set_padding(key->stream_enc, 0);
EVP_CIPHER_CTX_set_padding(key->stream_dec, 0); EVP_CIPHER_CTX_set_padding(key->stream_dec, 0);
EVP_EncryptInit_ex(key->block_enc, NULL, NULL, KeyData(key), NULL); EVP_EncryptInit_ex(key->block_enc, nullptr, nullptr, KeyData(key), nullptr);
EVP_DecryptInit_ex(key->block_dec, NULL, NULL, KeyData(key), NULL); EVP_DecryptInit_ex(key->block_dec, nullptr, nullptr, KeyData(key), nullptr);
EVP_EncryptInit_ex(key->stream_enc, NULL, NULL, KeyData(key), NULL); EVP_EncryptInit_ex(key->stream_enc, nullptr, nullptr, KeyData(key), nullptr);
EVP_DecryptInit_ex(key->stream_dec, NULL, NULL, KeyData(key), NULL); EVP_DecryptInit_ex(key->stream_dec, nullptr, nullptr, KeyData(key), nullptr);
HMAC_Init_ex(key->mac_ctx, KeyData(key), _keySize, EVP_sha1(), 0); HMAC_Init_ex(key->mac_ctx, KeyData(key), _keySize, EVP_sha1(), nullptr);
} }
SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_, SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_,
@ -342,7 +354,7 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_,
} }
} }
SSL_Cipher::~SSL_Cipher() {} SSL_Cipher::~SSL_Cipher() = default;
Interface SSL_Cipher::interface() const { return realIface; } Interface SSL_Cipher::interface() const { return realIface; }
@ -366,8 +378,9 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
if (res <= 0) { if (res <= 0) {
RLOG(WARNING) << "openssl error, PBKDF2 failed"; RLOG(WARNING) << "openssl error, PBKDF2 failed";
return CipherKey(); return CipherKey();
} else }
iterationCount = res; iterationCount = res;
} else { } else {
// known iteration length // known iteration length
if (PKCS5_PBKDF2_HMAC_SHA1( if (PKCS5_PBKDF2_HMAC_SHA1(
@ -401,9 +414,8 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength) {
} }
} else { } else {
// for backward compatibility with filesystems created with 1:0 // for backward compatibility with filesystems created with 1:0
bytes = EVP_BytesToKey(_blockCipher, EVP_sha1(), NULL, EVP_BytesToKey(_blockCipher, EVP_sha1(), nullptr, (unsigned char *)password,
(unsigned char *)password, passwdLength, 16, passwdLength, 16, KeyData(key), IVData(key));
KeyData(key), IVData(key));
} }
initKey(key, _blockCipher, _streamCipher, _keySize); initKey(key, _blockCipher, _streamCipher, _keySize);
@ -425,8 +437,9 @@ CipherKey SSL_Cipher::newRandomKey() {
int saltLen = 20; int saltLen = 20;
unsigned char saltBuf[saltLen]; unsigned char saltBuf[saltLen];
if (!randomize(tmpBuf, bufLen, true) || !randomize(saltBuf, saltLen, true)) if (!randomize(tmpBuf, bufLen, true) || !randomize(saltBuf, saltLen, true)) {
return CipherKey(); return CipherKey();
}
std::shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength)); std::shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength));
@ -456,9 +469,9 @@ static uint64_t _checksum_64(SSLKey *key, const unsigned char *data,
unsigned char md[EVP_MAX_MD_SIZE]; unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdLen = EVP_MAX_MD_SIZE; unsigned int mdLen = EVP_MAX_MD_SIZE;
HMAC_Init_ex(key->mac_ctx, 0, 0, 0, 0); HMAC_Init_ex(key->mac_ctx, nullptr, 0, nullptr, nullptr);
HMAC_Update(key->mac_ctx, data, dataLen); HMAC_Update(key->mac_ctx, data, dataLen);
if (chainedIV) { if (chainedIV != nullptr) {
// toss in the chained IV as well // toss in the chained IV as well
uint64_t tmp = *chainedIV; uint64_t tmp = *chainedIV;
unsigned char h[8]; unsigned char h[8];
@ -476,11 +489,14 @@ static uint64_t _checksum_64(SSLKey *key, const unsigned char *data,
// chop this down to a 64bit value.. // chop this down to a 64bit value..
unsigned char h[8] = {0, 0, 0, 0, 0, 0, 0, 0}; unsigned char h[8] = {0, 0, 0, 0, 0, 0, 0, 0};
for (unsigned int i = 0; i < (mdLen - 1); ++i) for (unsigned int i = 0; i < (mdLen - 1); ++i) {
h[i % 8] ^= (unsigned char)(md[i]); h[i % 8] ^= (unsigned char)(md[i]);
}
uint64_t value = (uint64_t)h[0]; auto value = (uint64_t)h[0];
for (int i = 1; i < 8; ++i) value = (value << 8) | (uint64_t)h[i]; for (int i = 1; i < 8; ++i) {
value = (value << 8) | (uint64_t)h[i];
}
return value; return value;
} }
@ -505,9 +521,8 @@ bool SSL_Cipher::randomize(unsigned char *buf, int len,
} }
return false; return false;
} else {
return true;
} }
return true;
} }
uint64_t SSL_Cipher::MAC_64(const unsigned char *data, int len, uint64_t SSL_Cipher::MAC_64(const unsigned char *data, int len,
@ -515,7 +530,9 @@ uint64_t SSL_Cipher::MAC_64(const unsigned char *data, int len,
std::shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(key); std::shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(key);
uint64_t tmp = _checksum_64(mk.get(), data, len, chainedIV); uint64_t tmp = _checksum_64(mk.get(), data, len, chainedIV);
if (chainedIV) *chainedIV = tmp; if (chainedIV != nullptr) {
*chainedIV = tmp;
}
return tmp; return tmp;
} }
@ -529,8 +546,9 @@ CipherKey SSL_Cipher::readKey(const unsigned char *data,
// First N bytes are checksum bytes. // First N bytes are checksum bytes.
unsigned int checksum = 0; unsigned int checksum = 0;
for (int i = 0; i < KEY_CHECKSUM_BYTES; ++i) for (int i = 0; i < KEY_CHECKSUM_BYTES; ++i) {
checksum = (checksum << 8) | (unsigned int)data[i]; checksum = (checksum << 8) | (unsigned int)data[i];
}
memcpy(tmpBuf, data + KEY_CHECKSUM_BYTES, _keySize + _ivLength); memcpy(tmpBuf, data + KEY_CHECKSUM_BYTES, _keySize + _ivLength);
streamDecode(tmpBuf, _keySize + _ivLength, checksum, masterKey); streamDecode(tmpBuf, _keySize + _ivLength, checksum, masterKey);
@ -591,10 +609,7 @@ bool SSL_Cipher::compareKey(const CipherKey &A, const CipherKey &B) const {
rAssert(key1->keySize == _keySize); rAssert(key1->keySize == _keySize);
rAssert(key2->keySize == _keySize); rAssert(key2->keySize == _keySize);
if (memcmp(key1->buffer, key2->buffer, _keySize + _ivLength) != 0) return memcmp(key1->buffer, key2->buffer, _keySize + _ivLength) == 0;
return false;
else
return true;
} }
int SSL_Cipher::encodedKeySize() const { int SSL_Cipher::encodedKeySize() const {
@ -637,7 +652,7 @@ void SSL_Cipher::setIVec(unsigned char *ivec, uint64_t seed,
} }
// combine ivec and seed with HMAC // combine ivec and seed with HMAC
HMAC_Init_ex(key->mac_ctx, 0, 0, 0, 0); HMAC_Init_ex(key->mac_ctx, nullptr, 0, nullptr, nullptr);
HMAC_Update(key->mac_ctx, ivec, _ivLength); HMAC_Update(key->mac_ctx, ivec, _ivLength);
HMAC_Update(key->mac_ctx, md, 8); HMAC_Update(key->mac_ctx, md, 8);
HMAC_Final(key->mac_ctx, md, &mdLen); HMAC_Final(key->mac_ctx, md, &mdLen);
@ -694,10 +709,12 @@ static void flipBytes(unsigned char *buf, int size) {
unsigned char revBuf[64]; unsigned char revBuf[64];
int bytesLeft = size; int bytesLeft = size;
while (bytesLeft) { while (bytesLeft != 0) {
int toFlip = MIN(sizeof(revBuf), bytesLeft); int toFlip = MIN(sizeof(revBuf), bytesLeft);
for (int i = 0; i < toFlip; ++i) revBuf[i] = buf[toFlip - (i + 1)]; for (int i = 0; i < toFlip; ++i) {
revBuf[i] = buf[toFlip - (i + 1)];
}
memcpy(buf, revBuf, toFlip); memcpy(buf, revBuf, toFlip);
bytesLeft -= toFlip; bytesLeft -= toFlip;
@ -707,11 +724,15 @@ static void flipBytes(unsigned char *buf, int size) {
} }
static void shuffleBytes(unsigned char *buf, int size) { static void shuffleBytes(unsigned char *buf, int size) {
for (int i = 0; i < size - 1; ++i) buf[i + 1] ^= buf[i]; for (int i = 0; i < size - 1; ++i) {
buf[i + 1] ^= buf[i];
}
} }
static void unshuffleBytes(unsigned char *buf, int size) { static void unshuffleBytes(unsigned char *buf, int size) {
for (int i = size - 1; i; --i) buf[i] ^= buf[i - 1]; for (int i = size - 1; i != 0; --i) {
buf[i] ^= buf[i - 1];
}
} }
/** Partial blocks are encoded with a stream cipher. We make multiple passes on /** Partial blocks are encoded with a stream cipher. We make multiple passes on
@ -732,7 +753,7 @@ bool SSL_Cipher::streamEncode(unsigned char *buf, int size, uint64_t iv64,
shuffleBytes(buf, size); shuffleBytes(buf, size);
setIVec(ivec, iv64, key); setIVec(ivec, iv64, key);
EVP_EncryptInit_ex(key->stream_enc, NULL, NULL, NULL, ivec); EVP_EncryptInit_ex(key->stream_enc, nullptr, nullptr, nullptr, ivec);
EVP_EncryptUpdate(key->stream_enc, buf, &dstLen, buf, size); EVP_EncryptUpdate(key->stream_enc, buf, &dstLen, buf, size);
EVP_EncryptFinal_ex(key->stream_enc, buf + dstLen, &tmpLen); EVP_EncryptFinal_ex(key->stream_enc, buf + dstLen, &tmpLen);
@ -740,7 +761,7 @@ bool SSL_Cipher::streamEncode(unsigned char *buf, int size, uint64_t iv64,
shuffleBytes(buf, size); shuffleBytes(buf, size);
setIVec(ivec, iv64 + 1, key); setIVec(ivec, iv64 + 1, key);
EVP_EncryptInit_ex(key->stream_enc, NULL, NULL, NULL, ivec); EVP_EncryptInit_ex(key->stream_enc, nullptr, nullptr, nullptr, ivec);
EVP_EncryptUpdate(key->stream_enc, buf, &dstLen, buf, size); EVP_EncryptUpdate(key->stream_enc, buf, &dstLen, buf, size);
EVP_EncryptFinal_ex(key->stream_enc, buf + dstLen, &tmpLen); EVP_EncryptFinal_ex(key->stream_enc, buf + dstLen, &tmpLen);
@ -766,7 +787,7 @@ bool SSL_Cipher::streamDecode(unsigned char *buf, int size, uint64_t iv64,
int dstLen = 0, tmpLen = 0; int dstLen = 0, tmpLen = 0;
setIVec(ivec, iv64 + 1, key); setIVec(ivec, iv64 + 1, key);
EVP_DecryptInit_ex(key->stream_dec, NULL, NULL, NULL, ivec); EVP_DecryptInit_ex(key->stream_dec, nullptr, nullptr, nullptr, ivec);
EVP_DecryptUpdate(key->stream_dec, buf, &dstLen, buf, size); EVP_DecryptUpdate(key->stream_dec, buf, &dstLen, buf, size);
EVP_DecryptFinal_ex(key->stream_dec, buf + dstLen, &tmpLen); EVP_DecryptFinal_ex(key->stream_dec, buf + dstLen, &tmpLen);
@ -774,7 +795,7 @@ bool SSL_Cipher::streamDecode(unsigned char *buf, int size, uint64_t iv64,
flipBytes(buf, size); flipBytes(buf, size);
setIVec(ivec, iv64, key); setIVec(ivec, iv64, key);
EVP_DecryptInit_ex(key->stream_dec, NULL, NULL, NULL, ivec); EVP_DecryptInit_ex(key->stream_dec, nullptr, nullptr, nullptr, ivec);
EVP_DecryptUpdate(key->stream_dec, buf, &dstLen, buf, size); EVP_DecryptUpdate(key->stream_dec, buf, &dstLen, buf, size);
EVP_DecryptFinal_ex(key->stream_dec, buf + dstLen, &tmpLen); EVP_DecryptFinal_ex(key->stream_dec, buf + dstLen, &tmpLen);
@ -798,8 +819,9 @@ bool SSL_Cipher::blockEncode(unsigned char *buf, int size, uint64_t iv64,
// data must be integer number of blocks // data must be integer number of blocks
const int blockMod = size % EVP_CIPHER_CTX_block_size(key->block_enc); const int blockMod = size % EVP_CIPHER_CTX_block_size(key->block_enc);
if (blockMod != 0) if (blockMod != 0) {
throw Error("Invalid data size, not multiple of block size"); throw Error("Invalid data size, not multiple of block size");
}
Lock lock(key->mutex); Lock lock(key->mutex);
@ -808,7 +830,7 @@ bool SSL_Cipher::blockEncode(unsigned char *buf, int size, uint64_t iv64,
int dstLen = 0, tmpLen = 0; int dstLen = 0, tmpLen = 0;
setIVec(ivec, iv64, key); setIVec(ivec, iv64, key);
EVP_EncryptInit_ex(key->block_enc, NULL, NULL, NULL, ivec); EVP_EncryptInit_ex(key->block_enc, nullptr, nullptr, nullptr, ivec);
EVP_EncryptUpdate(key->block_enc, buf, &dstLen, buf, size); EVP_EncryptUpdate(key->block_enc, buf, &dstLen, buf, size);
EVP_EncryptFinal_ex(key->block_enc, buf + dstLen, &tmpLen); EVP_EncryptFinal_ex(key->block_enc, buf + dstLen, &tmpLen);
dstLen += tmpLen; dstLen += tmpLen;
@ -830,8 +852,9 @@ bool SSL_Cipher::blockDecode(unsigned char *buf, int size, uint64_t iv64,
// data must be integer number of blocks // data must be integer number of blocks
const int blockMod = size % EVP_CIPHER_CTX_block_size(key->block_dec); const int blockMod = size % EVP_CIPHER_CTX_block_size(key->block_dec);
if (blockMod != 0) if (blockMod != 0) {
throw Error("Invalid data size, not multiple of block size"); throw Error("Invalid data size, not multiple of block size");
}
Lock lock(key->mutex); Lock lock(key->mutex);
@ -840,7 +863,7 @@ bool SSL_Cipher::blockDecode(unsigned char *buf, int size, uint64_t iv64,
int dstLen = 0, tmpLen = 0; int dstLen = 0, tmpLen = 0;
setIVec(ivec, iv64, key); setIVec(ivec, iv64, key);
EVP_DecryptInit_ex(key->block_dec, NULL, NULL, NULL, ivec); EVP_DecryptInit_ex(key->block_dec, nullptr, nullptr, nullptr, ivec);
EVP_DecryptUpdate(key->block_dec, buf, &dstLen, buf, size); EVP_DecryptUpdate(key->block_dec, buf, &dstLen, buf, size);
EVP_DecryptFinal_ex(key->block_dec, buf + dstLen, &tmpLen); EVP_DecryptFinal_ex(key->block_dec, buf + dstLen, &tmpLen);
dstLen += tmpLen; dstLen += tmpLen;

View File

@ -31,7 +31,7 @@
#ifndef EVP_CIPHER #ifndef EVP_CIPHER
struct evp_cipher_st; struct evp_cipher_st;
typedef struct evp_cipher_st EVP_CIPHER; using EVP_CIPHER = struct evp_cipher_st;
#endif #endif
namespace encfs { namespace encfs {

View File

@ -30,8 +30,7 @@
#define HMAC_CTX_reset HMAC_CTX_cleanup #define HMAC_CTX_reset HMAC_CTX_cleanup
// Missing methods (based on 1.1.0 versions) // Missing methods (based on 1.1.0 versions)
HMAC_CTX *HMAC_CTX_new(void) HMAC_CTX *HMAC_CTX_new(void) {
{
HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX)); HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX));
if (ctx != NULL) { if (ctx != NULL) {
memset(ctx, 0, sizeof(HMAC_CTX)); memset(ctx, 0, sizeof(HMAC_CTX));
@ -40,8 +39,7 @@ HMAC_CTX *HMAC_CTX_new(void)
return ctx; return ctx;
} }
void HMAC_CTX_free(HMAC_CTX *ctx) void HMAC_CTX_free(HMAC_CTX *ctx) {
{
if (ctx != NULL) { if (ctx != NULL) {
HMAC_CTX_cleanup(ctx); HMAC_CTX_cleanup(ctx);
OPENSSL_free(ctx); OPENSSL_free(ctx);

View File

@ -22,6 +22,7 @@
#include "internal/easylogging++.h" #include "internal/easylogging++.h"
#include <cstring> #include <cstring>
#include <utility>
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
@ -72,11 +73,12 @@ Interface StreamNameIO::CurrentInterface() {
} }
StreamNameIO::StreamNameIO(const Interface &iface, StreamNameIO::StreamNameIO(const Interface &iface,
const std::shared_ptr<Cipher> &cipher, std::shared_ptr<Cipher> cipher, CipherKey key)
const CipherKey &key) : _interface(iface.current()),
: _interface(iface.current()), _cipher(cipher), _key(key) {} _cipher(std::move(cipher)),
_key(std::move(key)) {}
StreamNameIO::~StreamNameIO() {} StreamNameIO::~StreamNameIO() = default;
Interface StreamNameIO::interface() const { return CurrentInterface(); } Interface StreamNameIO::interface() const { return CurrentInterface(); }
@ -94,7 +96,9 @@ int StreamNameIO::encodeName(const char *plaintextName, int length,
uint64_t *iv, char *encodedName, uint64_t *iv, char *encodedName,
int bufferLength) const { int bufferLength) const {
uint64_t tmpIV = 0; uint64_t tmpIV = 0;
if (iv && _interface >= 2) tmpIV = *iv; if ((iv != nullptr) && _interface >= 2) {
tmpIV = *iv;
}
unsigned int mac = unsigned int mac =
_cipher->MAC_16((const unsigned char *)plaintextName, length, _key, iv); _cipher->MAC_16((const unsigned char *)plaintextName, length, _key, iv);
@ -135,7 +139,9 @@ int StreamNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
int decodedStreamLen = decLen256 - 2; int decodedStreamLen = decLen256 - 2;
rAssert(decodedStreamLen <= bufferLength); rAssert(decodedStreamLen <= bufferLength);
if (decodedStreamLen <= 0) throw Error("Filename too small to decode"); if (decodedStreamLen <= 0) {
throw Error("Filename too small to decode");
}
BUFFER_INIT(tmpBuf, 32, (unsigned int)length); BUFFER_INIT(tmpBuf, 32, (unsigned int)length);
@ -153,7 +159,9 @@ int StreamNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
((unsigned int)((unsigned char)tmpBuf[1])); ((unsigned int)((unsigned char)tmpBuf[1]));
// version 2 adds support for IV chaining.. // version 2 adds support for IV chaining..
if (iv && _interface >= 2) tmpIV = *iv; if ((iv != nullptr) && _interface >= 2) {
tmpIV = *iv;
}
memcpy(plaintextName, tmpBuf + 2, decodedStreamLen); memcpy(plaintextName, tmpBuf + 2, decodedStreamLen);
} else { } else {

View File

@ -36,8 +36,8 @@ class StreamNameIO : public NameIO {
public: public:
static Interface CurrentInterface(); static Interface CurrentInterface();
StreamNameIO(const Interface &iface, const std::shared_ptr<Cipher> &cipher, StreamNameIO(const Interface &iface, std::shared_ptr<Cipher> cipher,
const CipherKey &key); CipherKey key);
virtual ~StreamNameIO(); virtual ~StreamNameIO();
virtual Interface interface() const; virtual Interface interface() const;

View File

@ -22,8 +22,8 @@
#include <algorithm> // for remove_if #include <algorithm> // for remove_if
#include <cstring> // for NULL #include <cstring> // for NULL
#include <memory> // for shared_ptr
#include <fstream> // for ifstream #include <fstream> // for ifstream
#include <memory> // for shared_ptr
#include <sstream> // for ostringstream #include <sstream> // for ostringstream
#include <tinyxml2.h> // for XMLElement, XMLNode, XMLDocument (ptr only) #include <tinyxml2.h> // for XMLElement, XMLNode, XMLDocument (ptr only)
@ -34,7 +34,7 @@
namespace encfs { namespace encfs {
XmlValue::~XmlValue() {} XmlValue::~XmlValue() = default;
XmlValuePtr XmlValue::operator[](const char *path) const { return find(path); } XmlValuePtr XmlValue::operator[](const char *path) const { return find(path); }
@ -46,7 +46,9 @@ XmlValuePtr XmlValue::find(const char *path) const {
bool XmlValue::read(const char *path, std::string *out) const { bool XmlValue::read(const char *path, std::string *out) const {
XmlValuePtr value = find(path); XmlValuePtr value = find(path);
if (!value) return false; if (!value) {
return false;
}
*out = value->text(); *out = value->text();
return true; return true;
@ -54,7 +56,9 @@ bool XmlValue::read(const char *path, std::string *out) const {
bool XmlValue::read(const char *path, int *out) const { bool XmlValue::read(const char *path, int *out) const {
XmlValuePtr value = find(path); XmlValuePtr value = find(path);
if (!value) return false; if (!value) {
return false;
}
*out = atoi(value->text().c_str()); *out = atoi(value->text().c_str());
return true; return true;
@ -62,7 +66,9 @@ bool XmlValue::read(const char *path, int *out) const {
bool XmlValue::read(const char *path, long *out) const { bool XmlValue::read(const char *path, long *out) const {
XmlValuePtr value = find(path); XmlValuePtr value = find(path);
if (!value) return false; if (!value) {
return false;
}
*out = atol(value->text().c_str()); *out = atol(value->text().c_str());
return true; return true;
@ -70,7 +76,9 @@ bool XmlValue::read(const char *path, long *out) const {
bool XmlValue::read(const char *path, double *out) const { bool XmlValue::read(const char *path, double *out) const {
XmlValuePtr value = find(path); XmlValuePtr value = find(path);
if (!value) return false; if (!value) {
return false;
}
*out = atof(value->text().c_str()); *out = atof(value->text().c_str());
return true; return true;
@ -78,16 +86,20 @@ bool XmlValue::read(const char *path, double *out) const {
bool XmlValue::read(const char *path, bool *out) const { bool XmlValue::read(const char *path, bool *out) const {
XmlValuePtr value = find(path); XmlValuePtr value = find(path);
if (!value) return false; if (!value) {
return false;
}
*out = atoi(value->text().c_str()); *out = (atoi(value->text().c_str()) != 0);
return true; return true;
} }
bool XmlValue::readB64(const char *path, unsigned char *data, bool XmlValue::readB64(const char *path, unsigned char *data,
int length) const { int length) const {
XmlValuePtr value = find(path); XmlValuePtr value = find(path);
if (!value) return false; if (!value) {
return false;
}
std::string s = value->text(); std::string s = value->text();
s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end()); s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
@ -101,7 +113,7 @@ bool XmlValue::readB64(const char *path, unsigned char *data,
return false; return false;
} }
if (!B64StandardDecode(data, (unsigned char *)s.data(), s.size())) { if (!B64StandardDecode(data, (unsigned char *)s.data(), s.size())) {
RLOG(ERROR) << "B64 decode failure on \"" << s << "\""; RLOG(ERROR) << R"(B64 decode failure on ")" << s << R"(")";
return false; return false;
} }
@ -110,7 +122,9 @@ bool XmlValue::readB64(const char *path, unsigned char *data,
bool XmlValue::read(const char *path, Interface *out) const { bool XmlValue::read(const char *path, Interface *out) const {
XmlValuePtr node = find(path); XmlValuePtr node = find(path);
if (!node) return false; if (!node) {
return false;
}
bool ok = node->read("name", &out->name()) && bool ok = node->read("name", &out->name()) &&
node->read("major", &out->current()) && node->read("major", &out->current()) &&
@ -121,12 +135,16 @@ bool XmlValue::read(const char *path, Interface *out) const {
std::string safeValueForNode(const tinyxml2::XMLElement *element) { std::string safeValueForNode(const tinyxml2::XMLElement *element) {
std::string value; std::string value;
if (element == NULL) return value; if (element == nullptr) {
return value;
}
const tinyxml2::XMLNode *child = element->FirstChild(); const tinyxml2::XMLNode *child = element->FirstChild();
if (child) { if (child != nullptr) {
const tinyxml2::XMLText *childText = child->ToText(); const tinyxml2::XMLText *childText = child->ToText();
if (childText) value = childText->Value(); if (childText != nullptr) {
value = childText->Value();
}
} }
return value; return value;
@ -139,22 +157,21 @@ class XmlNode : virtual public XmlValue {
XmlNode(const tinyxml2::XMLElement *element_) XmlNode(const tinyxml2::XMLElement *element_)
: XmlValue(safeValueForNode(element_)), element(element_) {} : XmlValue(safeValueForNode(element_)), element(element_) {}
virtual ~XmlNode() {} ~XmlNode() override = default;
virtual XmlValuePtr find(const char *name) const { XmlValuePtr find(const char *name) const override {
if (name[0] == '@') { if (name[0] == '@') {
const char *value = element->Attribute(name + 1); const char *value = element->Attribute(name + 1);
if (value) if (value != nullptr) {
return XmlValuePtr(new XmlValue(value)); return std::make_shared<encfs::XmlValue>(value);
else }
return XmlValuePtr(); return XmlValuePtr();
} else {
const tinyxml2::XMLElement *el = element->FirstChildElement(name);
if (el)
return XmlValuePtr(new XmlNode(el));
else
return XmlValuePtr();
} }
const tinyxml2::XMLElement *el = element->FirstChildElement(name);
if (el != nullptr) {
return XmlValuePtr(new XmlNode(el));
}
return XmlValuePtr();
} }
}; };
@ -164,13 +181,15 @@ struct XmlReader::XmlReaderData {
XmlReader::XmlReader() : pd(new XmlReaderData()) {} XmlReader::XmlReader() : pd(new XmlReaderData()) {}
XmlReader::~XmlReader() {} XmlReader::~XmlReader() = default;
bool XmlReader::load(const char *fileName) { bool XmlReader::load(const char *fileName) {
pd->doc.reset(new tinyxml2::XMLDocument()); pd->doc.reset(new tinyxml2::XMLDocument());
std::ifstream in(fileName); std::ifstream in(fileName);
if (!in) return false; if (!in) {
return false;
}
std::ostringstream fileContent; std::ostringstream fileContent;
fileContent << in.rdbuf(); fileContent << in.rdbuf();
@ -180,15 +199,15 @@ bool XmlReader::load(const char *fileName) {
XmlValuePtr XmlReader::operator[](const char *name) const { XmlValuePtr XmlReader::operator[](const char *name) const {
tinyxml2::XMLNode *node = pd->doc->FirstChildElement(name); tinyxml2::XMLNode *node = pd->doc->FirstChildElement(name);
if (node == NULL) { if (node == nullptr) {
RLOG(ERROR) << "Xml node " << name << " not found"; RLOG(ERROR) << "Xml node " << name << " not found";
return XmlValuePtr(new XmlValue()); return std::make_shared<encfs::XmlValue>();
} }
tinyxml2::XMLElement *element = node->ToElement(); tinyxml2::XMLElement *element = node->ToElement();
if (element == NULL) { if (element == nullptr) {
RLOG(ERROR) << "Xml node " << name << " not element"; RLOG(ERROR) << "Xml node " << name << " not element";
return XmlValuePtr(new XmlValue()); return std::make_shared<encfs::XmlValue>();
} }
return XmlValuePtr(new XmlNode(element)); return XmlValuePtr(new XmlNode(element));

View File

@ -29,7 +29,7 @@
namespace encfs { namespace encfs {
class XmlValue; class XmlValue;
typedef std::shared_ptr<XmlValue> XmlValuePtr; using XmlValuePtr = std::shared_ptr<XmlValue>;
class XmlValue { class XmlValue {
std::string value; std::string value;

View File

@ -27,10 +27,10 @@
/* Specification. */ /* Specification. */
#include "autosprintf.h" #include "autosprintf.h"
#include <stdarg.h> // for va_list #include <cstdarg> // for va_list
#include <stdio.h> // for NULL, vasprintf #include <cstdio> // for NULL, vasprintf
#include <stdlib.h> // for free #include <cstdlib> // for free
#include <string.h> // for strdup #include <cstring> // for strdup
namespace gnu { namespace gnu {
@ -38,13 +38,15 @@ namespace gnu {
autosprintf::autosprintf(const char *format, ...) { autosprintf::autosprintf(const char *format, ...) {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
if (vasprintf(&str, format, args) < 0) str = NULL; if (vasprintf(&str, format, args) < 0) {
str = nullptr;
}
va_end(args); va_end(args);
} }
/* Copy constructor. Necessary because the destructor is nontrivial. */ /* Copy constructor. Necessary because the destructor is nontrivial. */
autosprintf::autosprintf(const autosprintf &src) { autosprintf::autosprintf(const autosprintf &src) {
str = (src.str != NULL ? strdup(src.str) : NULL); str = (src.str != nullptr ? strdup(src.str) : nullptr);
} }
/* Destructor: frees the temporarily allocated string. */ /* Destructor: frees the temporarily allocated string. */
@ -52,15 +54,15 @@ autosprintf::~autosprintf() { free(str); }
/* Conversion to string. */ /* Conversion to string. */
autosprintf::operator char *() const { autosprintf::operator char *() const {
if (str != NULL) { if (str != nullptr) {
size_t length = strlen(str) + 1; size_t length = strlen(str) + 1;
char *copy = new char[length]; auto *copy = new char[length];
memcpy(copy, str, length); memcpy(copy, str, length);
return copy; return copy;
} else }
return NULL; return nullptr;
} }
autosprintf::operator std::string() const { autosprintf::operator std::string() const {
return std::string(str ? str : "(error in autosprintf)"); return std::string(str != nullptr ? str : "(error in autosprintf)");
}
} }
} // namespace gnu

View File

@ -20,7 +20,7 @@
#include "base64.h" #include "base64.h"
#include <ctype.h> // for toupper #include <cctype> // for toupper
#include "Error.h" #include "Error.h"
@ -52,7 +52,9 @@ void changeBase2(unsigned char *src, int srcLen, int src2Pow,
} }
// 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)) *dst++ = work & mask; if ((workBits != 0) && ((dst - origDst) < dstLen)) {
*dst++ = work & mask;
}
} }
/* /*
@ -67,11 +69,13 @@ static void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow,
unsigned long work, int workBits, unsigned long work, int workBits,
unsigned char *outLoc) { unsigned char *outLoc) {
const int mask = (1 << dst2Pow) - 1; const int mask = (1 << dst2Pow) - 1;
if (!outLoc) outLoc = src; if (outLoc == nullptr) {
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 != 0) && workBits < dst2Pow) {
work |= ((unsigned long)(*src++)) << workBits; work |= ((unsigned long)(*src++)) << workBits;
workBits += src2Pow; workBits += src2Pow;
--srcLen; --srcLen;
@ -82,7 +86,7 @@ static void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow,
work >>= dst2Pow; work >>= dst2Pow;
workBits -= dst2Pow; workBits -= dst2Pow;
if (srcLen) { if (srcLen != 0) {
// more input left, so recurse // more input left, so recurse
changeBase2Inline(src, srcLen, src2Pow, dst2Pow, outputPartialLastByte, changeBase2Inline(src, srcLen, src2Pow, dst2Pow, outputPartialLastByte,
work, workBits, outLoc + 1); work, workBits, outLoc + 1);
@ -105,7 +109,7 @@ static void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow,
void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow, int dst2Pow, void changeBase2Inline(unsigned char *src, int srcLen, int src2Pow, int dst2Pow,
bool outputPartialLastByte) { bool outputPartialLastByte) {
changeBase2Inline(src, srcLen, src2Pow, dst2Pow, outputPartialLastByte, 0, 0, changeBase2Inline(src, srcLen, src2Pow, dst2Pow, outputPartialLastByte, 0, 0,
0); nullptr);
} }
// character set for ascii b64: // character set for ascii b64:
@ -119,12 +123,14 @@ 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]; int ch = in[offset];
if (ch > 11) { if (ch > 11) {
if (ch > 37) if (ch > 37) {
ch += 'a' - 38; ch += 'a' - 38;
else } else {
ch += 'A' - 12; ch += 'A' - 12;
} else }
} else {
ch = B642AsciiTable[ch]; ch = B642AsciiTable[ch];
}
in[offset] = ch; in[offset] = ch;
} }
@ -139,16 +145,17 @@ void AsciiToB64(unsigned char *in, int 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--) != 0) {
unsigned char ch = *in++; unsigned char ch = *in++;
if (ch >= 'A') { if (ch >= 'A') {
if (ch >= 'a') if (ch >= 'a') {
ch += 38 - 'a'; ch += 38 - 'a';
else } else {
ch += 12 - 'A'; ch += 12 - 'A';
} else }
} else {
ch = Ascii2B64Table[ch] - '0'; ch = Ascii2B64Table[ch] - '0';
}
*out++ = ch; *out++ = ch;
} }
} }
@ -156,10 +163,11 @@ void AsciiToB64(unsigned char *out, const unsigned char *in, int length) {
void B32ToAscii(unsigned char *buf, int len) { void B32ToAscii(unsigned char *buf, int len) {
for (int offset = 0; offset < len; ++offset) { for (int offset = 0; offset < len; ++offset) {
int ch = buf[offset]; int ch = buf[offset];
if (ch >= 0 && ch < 26) if (ch >= 0 && ch < 26) {
ch += 'A'; ch += 'A';
else } else {
ch += '2' - 26; ch += '2' - 26;
}
buf[offset] = ch; buf[offset] = ch;
} }
@ -170,14 +178,14 @@ void AsciiToB32(unsigned char *in, int 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--) != 0) {
unsigned char ch = *in++; unsigned char ch = *in++;
int lch = toupper(ch); int lch = toupper(ch);
if (lch >= 'A') if (lch >= 'A') {
lch -= 'A'; lch -= 'A';
else } else {
lch += 26 - '2'; lch += 26 - '2';
}
*out++ = (unsigned char)lch; *out++ = (unsigned char)lch;
} }
} }
@ -221,7 +229,7 @@ bool B64StandardDecode(unsigned char *out, const unsigned char *in, int inLen) {
buf = buf << 6 | c; buf = buf << 6 | c;
/* If the buffer is full, split it into bytes */ /* If the buffer is full, split it into bytes */
if (buf & 0x1000000) { if ((buf & 0x1000000) != 0u) {
*out++ = buf >> 16; *out++ = buf >> 16;
*out++ = buf >> 8; *out++ = buf >> 8;
*out++ = buf; *out++ = buf;
@ -230,10 +238,10 @@ bool B64StandardDecode(unsigned char *out, const unsigned char *in, int inLen) {
} }
} }
if (buf & 0x40000) { if ((buf & 0x40000) != 0u) {
*out++ = buf >> 10; *out++ = buf >> 10;
*out++ = buf >> 2; *out++ = buf >> 2;
} else if (buf & 0x1000) { } else if ((buf & 0x1000) != 0u) {
*out++ = buf >> 4; *out++ = buf >> 4;
} }
@ -248,7 +256,7 @@ std::string B64StandardEncode(std::vector<unsigned char> inputBuffer) {
std::string encodedString; std::string encodedString;
encodedString.reserve(B256ToB64Bytes(inputBuffer.size())); encodedString.reserve(B256ToB64Bytes(inputBuffer.size()));
long temp; long temp;
std::vector<unsigned char>::iterator cursor = inputBuffer.begin(); auto cursor = inputBuffer.begin();
for (size_t idx = 0; idx < inputBuffer.size() / 3; idx++) { for (size_t idx = 0; idx < inputBuffer.size() / 3; idx++) {
temp = (*cursor++) << 16; // Convert to big endian temp = (*cursor++) << 16; // Convert to big endian
temp += (*cursor++) << 8; temp += (*cursor++) << 8;

View File

@ -18,17 +18,17 @@
#include "encfs.h" #include "encfs.h"
#include <cerrno> #include <cerrno>
#include <cinttypes>
#include <cstddef> #include <cstddef>
#include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <ctime>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h>
#include <memory> #include <memory>
#include <stdint.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <sys/time.h> #include <sys/time.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include <utime.h> #include <utime.h>
#ifdef linux #ifdef linux
@ -76,7 +76,9 @@ static EncFS_Context *context() {
* if the argument is NULL. * if the argument is NULL.
*/ */
static bool isReadOnly(EncFS_Context *ctx) { static bool isReadOnly(EncFS_Context *ctx) {
if (ctx == NULL) ctx = (EncFS_Context *)fuse_get_context()->private_data; if (ctx == nullptr) {
ctx = (EncFS_Context *)fuse_get_context()->private_data;
}
return ctx->opts->readOnly; return ctx->opts->readOnly;
} }
@ -89,7 +91,9 @@ static int withCipherPath(const char *opName, const char *path,
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
string cyName = FSRoot->cipherPath(path); string cyName = FSRoot->cipherPath(path);
@ -112,20 +116,22 @@ static int withCipherPath(const char *opName, const char *path,
} }
static void checkCanary(std::shared_ptr<FileNode> fnode) { static void checkCanary(std::shared_ptr<FileNode> fnode) {
if(fnode->canary == CANARY_OK) { if (fnode->canary == CANARY_OK) {
return; return;
} }
if(fnode->canary == CANARY_RELEASED) { if (fnode->canary == CANARY_RELEASED) {
// "fnode" may have been released after it was retrieved by // "fnode" may have been released after it was retrieved by
// lookupFuseFh. This is not an error. std::shared_ptr will release // lookupFuseFh. This is not an error. std::shared_ptr will release
// the memory only when all operations on the FileNode have been // the memory only when all operations on the FileNode have been
// completed. // completed.
return; return;
} }
if(fnode->canary == CANARY_DESTROYED) { if (fnode->canary == CANARY_DESTROYED) {
RLOG(ERROR) << "canary=CANARY_DESTROYED. FileNode accessed after it was destroyed."; RLOG(ERROR)
<< "canary=CANARY_DESTROYED. FileNode accessed after it was destroyed.";
} else { } else {
RLOG(ERROR) << "canary=0x" << std::hex << fnode->canary << ". Memory corruption?"; RLOG(ERROR) << "canary=0x" << std::hex << fnode->canary
<< ". Memory corruption?";
} }
throw Error("dead canary"); throw Error("dead canary");
} }
@ -138,7 +144,9 @@ static int withFileNode(const char *opName, const char *path,
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
@ -214,7 +222,7 @@ int _do_getattr(FileNode *fnode, struct stat *stbuf) {
} }
int encfs_getattr(const char *path, struct stat *stbuf) { int encfs_getattr(const char *path, struct stat *stbuf) {
return withFileNode("getattr", path, NULL, bind(_do_getattr, _1, stbuf)); return withFileNode("getattr", path, nullptr, bind(_do_getattr, _1, stbuf));
} }
int encfs_fgetattr(const char *path, struct stat *stbuf, int encfs_fgetattr(const char *path, struct stat *stbuf,
@ -228,7 +236,9 @@ int encfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
int res = ESUCCESS; int res = ESUCCESS;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
@ -250,7 +260,9 @@ int encfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
#if defined(fuse_fill_dir_flags) #if defined(fuse_fill_dir_flags)
if (filler(buf, name.c_str(), &st, 0, 0)) break; if (filler(buf, name.c_str(), &st, 0, 0)) break;
#else #else
if (filler(buf, name.c_str(), &st, 0)) break; if (filler(buf, name.c_str(), &st, 0) != 0) {
break;
}
#endif #endif
name = dt.nextPlaintextName(&fileType, &inode); name = dt.nextPlaintextName(&fileType, &inode);
@ -269,11 +281,15 @@ int encfs_readdir(const char *path, void *buf, fuse_fill_dir_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) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) {
return -EROFS;
}
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
std::shared_ptr<FileNode> fnode = FSRoot->lookupNode(path, "mknod"); std::shared_ptr<FileNode> fnode = FSRoot->lookupNode(path, "mknod");
@ -298,8 +314,9 @@ int encfs_mknod(const char *path, mode_t mode, dev_t rdev) {
FSRoot->lookupNode(parent.c_str(), "mknod"); FSRoot->lookupNode(parent.c_str(), "mknod");
struct stat st; struct stat st;
if (dnode->getAttr(&st) == 0) if (dnode->getAttr(&st) == 0) {
res = fnode->mknod(mode, rdev, uid, st.st_gid); res = fnode->mknod(mode, rdev, uid, st.st_gid);
}
} }
} catch (encfs::Error &err) { } catch (encfs::Error &err) {
RLOG(ERROR) << "error caught in mknod: " << err.what(); RLOG(ERROR) << "error caught in mknod: " << err.what();
@ -311,11 +328,15 @@ int encfs_mkdir(const char *path, mode_t mode) {
fuse_context *fctx = fuse_get_context(); fuse_context *fctx = fuse_get_context();
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) {
return -EROFS;
}
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
uid_t uid = 0; uid_t uid = 0;
@ -333,8 +354,9 @@ int encfs_mkdir(const char *path, mode_t mode) {
FSRoot->lookupNode(parent.c_str(), "mkdir"); FSRoot->lookupNode(parent.c_str(), "mkdir");
struct stat st; struct stat st;
if (dnode->getAttr(&st) == 0) if (dnode->getAttr(&st) == 0) {
res = FSRoot->mkdir(path, mode, uid, st.st_gid); res = FSRoot->mkdir(path, mode, uid, st.st_gid);
}
} }
} catch (encfs::Error &err) { } catch (encfs::Error &err) {
RLOG(ERROR) << "error caught in mkdir: " << err.what(); RLOG(ERROR) << "error caught in mkdir: " << err.what();
@ -345,11 +367,15 @@ int encfs_mkdir(const char *path, mode_t mode) {
int encfs_unlink(const char *path) { int encfs_unlink(const char *path) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) {
return -EROFS;
}
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
// let DirNode handle it atomically so that it can handle race // let DirNode handle it atomically so that it can handle race
@ -366,7 +392,9 @@ int _do_rmdir(EncFS_Context *, const string &cipherPath) {
} }
int encfs_rmdir(const char *path) { int encfs_rmdir(const char *path) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withCipherPath("rmdir", path, bind(_do_rmdir, _1, _2)); return withCipherPath("rmdir", path, bind(_do_rmdir, _1, _2));
} }
@ -374,11 +402,15 @@ int _do_readlink(EncFS_Context *ctx, const string &cyName, char *buf,
size_t size) { size_t size) {
int res = ESUCCESS; int res = ESUCCESS;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
res = ::readlink(cyName.c_str(), buf, size - 1); res = ::readlink(cyName.c_str(), buf, size - 1);
if (res == -1) return -errno; if (res == -1) {
return -errno;
}
buf[res] = '\0'; // ensure null termination buf[res] = '\0'; // ensure null termination
string decodedName; string decodedName;
@ -393,10 +425,9 @@ int _do_readlink(EncFS_Context *ctx, const string &cyName, char *buf,
buf[size - 1] = '\0'; buf[size - 1] = '\0';
return ESUCCESS; return ESUCCESS;
} else {
RLOG(WARNING) << "Error decoding link";
return -1;
} }
RLOG(WARNING) << "Error decoding link";
return -1;
} }
int encfs_readlink(const char *path, char *buf, size_t size) { int encfs_readlink(const char *path, char *buf, size_t size) {
@ -410,11 +441,15 @@ int encfs_readlink(const char *path, char *buf, size_t size) {
int encfs_symlink(const char *to, const char *from) { int encfs_symlink(const char *to, const char *from) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) {
return -EROFS;
}
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
string fromCName = FSRoot->cipherPath(from); string fromCName = FSRoot->cipherPath(from);
@ -433,13 +468,18 @@ int encfs_symlink(const char *to, const char *from) {
oldgid = setfsgid(context->gid); oldgid = setfsgid(context->gid);
} }
res = ::symlink(toCName.c_str(), fromCName.c_str()); res = ::symlink(toCName.c_str(), fromCName.c_str());
if (olduid >= 0) setfsuid(olduid); if (olduid >= 0) {
if (oldgid >= 0) setfsgid(oldgid); setfsuid(olduid);
}
if (oldgid >= 0) {
setfsgid(oldgid);
}
if (res == -1) if (res == -1) {
res = -errno; res = -errno;
else } else {
res = ESUCCESS; res = ESUCCESS;
}
} catch (encfs::Error &err) { } catch (encfs::Error &err) {
RLOG(ERROR) << "error caught in symlink: " << err.what(); RLOG(ERROR) << "error caught in symlink: " << err.what();
} }
@ -449,11 +489,15 @@ int encfs_symlink(const char *to, const char *from) {
int encfs_link(const char *from, const char *to) { int encfs_link(const char *from, const char *to) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) {
return -EROFS;
}
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
res = FSRoot->link(from, to); res = FSRoot->link(from, to);
@ -466,11 +510,15 @@ int encfs_link(const char *from, const char *to) {
int encfs_rename(const char *from, const char *to) { int encfs_rename(const char *from, const char *to) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) {
return -EROFS;
}
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
res = FSRoot->rename(from, to); res = FSRoot->rename(from, to);
@ -485,7 +533,9 @@ int _do_chmod(EncFS_Context *, const string &cipherPath, mode_t mode) {
} }
int encfs_chmod(const char *path, mode_t mode) { int encfs_chmod(const char *path, mode_t mode) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withCipherPath("chmod", path, bind(_do_chmod, _1, _2, mode)); return withCipherPath("chmod", path, bind(_do_chmod, _1, _2, mode));
} }
@ -495,19 +545,25 @@ int _do_chown(EncFS_Context *, const string &cyName, uid_t u, gid_t g) {
} }
int encfs_chown(const char *path, uid_t uid, gid_t gid) { int encfs_chown(const char *path, uid_t uid, gid_t gid) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withCipherPath("chown", path, bind(_do_chown, _1, _2, uid, gid)); return withCipherPath("chown", path, bind(_do_chown, _1, _2, uid, gid));
} }
int _do_truncate(FileNode *fnode, off_t size) { return fnode->truncate(size); } int _do_truncate(FileNode *fnode, off_t size) { return fnode->truncate(size); }
int encfs_truncate(const char *path, off_t size) { int encfs_truncate(const char *path, off_t size) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return withFileNode("truncate", path, NULL, bind(_do_truncate, _1, size)); return -EROFS;
}
return withFileNode("truncate", path, nullptr, bind(_do_truncate, _1, size));
} }
int encfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) { int encfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withFileNode("ftruncate", path, fi, bind(_do_truncate, _1, size)); return withFileNode("ftruncate", path, fi, bind(_do_truncate, _1, size));
} }
@ -517,7 +573,9 @@ int _do_utime(EncFS_Context *, const string &cyName, struct utimbuf *buf) {
} }
int encfs_utime(const char *path, struct utimbuf *buf) { int encfs_utime(const char *path, struct utimbuf *buf) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withCipherPath("utime", path, bind(_do_utime, _1, _2, buf)); return withCipherPath("utime", path, bind(_do_utime, _1, _2, buf));
} }
@ -538,19 +596,25 @@ int _do_utimens(EncFS_Context *, const string &cyName,
} }
int encfs_utimens(const char *path, const struct timespec ts[2]) { int encfs_utimens(const char *path, const struct timespec ts[2]) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withCipherPath("utimens", path, bind(_do_utimens, _1, _2, ts)); return withCipherPath("utimens", path, bind(_do_utimens, _1, _2, ts));
} }
int encfs_open(const char *path, struct fuse_file_info *file) { int encfs_open(const char *path, struct fuse_file_info *file) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
if (isReadOnly(ctx) && (file->flags & O_WRONLY || file->flags & O_RDWR)) if (isReadOnly(ctx) &&
(((file->flags & O_WRONLY) != 0) || ((file->flags & O_RDWR) != 0))) {
return -EROFS; return -EROFS;
}
int res = -EIO; int res = -EIO;
std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (!FSRoot) return res; if (!FSRoot) {
return res;
}
try { try {
std::shared_ptr<FileNode> fnode = std::shared_ptr<FileNode> fnode =
@ -575,7 +639,7 @@ int encfs_open(const char *path, struct fuse_file_info *file) {
int encfs_create(const char *path, mode_t mode, struct fuse_file_info *file) { int encfs_create(const char *path, mode_t mode, struct fuse_file_info *file) {
int res = encfs_mknod(path, mode, 0); int res = encfs_mknod(path, mode, 0);
if (res) { if (res != 0) {
return res; return res;
} }
@ -641,20 +705,24 @@ int _do_fsync(FileNode *fnode, int dataSync) {
} }
int encfs_fsync(const char *path, int dataSync, struct fuse_file_info *file) { int encfs_fsync(const char *path, int dataSync, struct fuse_file_info *file) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withFileNode("fsync", path, file, bind(_do_fsync, _1, dataSync)); return withFileNode("fsync", path, file, bind(_do_fsync, _1, dataSync));
} }
int _do_write(FileNode *fnode, unsigned char *ptr, size_t size, off_t offset) { int _do_write(FileNode *fnode, unsigned char *ptr, size_t size, off_t offset) {
if (fnode->write(offset, ptr, size)) if (fnode->write(offset, ptr, size)) {
return size; return size;
else }
return -EIO; return -EIO;
} }
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 *file) { struct fuse_file_info *file) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withFileNode("write", path, file, return withFileNode("write", path, file,
bind(_do_write, _1, (unsigned char *)buf, size, offset)); bind(_do_write, _1, (unsigned char *)buf, size, offset));
} }
@ -666,16 +734,18 @@ int encfs_statfs(const char *path, struct statvfs *st) {
int res = -EIO; int res = -EIO;
try { try {
(void)path; // path should always be '/' for now.. (void)path; // path should always be '/' for now..
rAssert(st != NULL); rAssert(st != nullptr);
string cyName = ctx->rootCipherDir; string cyName = ctx->rootCipherDir;
VLOG(1) << "doing statfs of " << cyName; VLOG(1) << "doing statfs of " << cyName;
res = statvfs(cyName.c_str(), st); res = statvfs(cyName.c_str(), st);
if (!res) { if (res == 0) {
// adjust maximum name length.. // adjust maximum name length..
st->f_namemax = 6 * (st->f_namemax - 2) / 8; // approx.. st->f_namemax = 6 * (st->f_namemax - 2) / 8; // approx..
} }
if (res == -1) res = -errno; if (res == -1) {
res = -errno;
}
} catch (encfs::Error &err) { } catch (encfs::Error &err) {
RLOG(ERROR) << "error caught in statfs: " << err.what(); RLOG(ERROR) << "error caught in statfs: " << err.what();
} }
@ -704,7 +774,9 @@ int _do_setxattr(EncFS_Context *, const string &cyName, const char *name,
} }
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) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withCipherPath("setxattr", path, return withCipherPath("setxattr", path,
bind(_do_setxattr, _1, _2, name, value, size, flags)); bind(_do_setxattr, _1, _2, name, value, size, flags));
} }
@ -762,7 +834,9 @@ int _do_removexattr(EncFS_Context *, const string &cyName, const char *name) {
} }
int encfs_removexattr(const char *path, const char *name) { int encfs_removexattr(const char *path, const char *name) {
if (isReadOnly(NULL)) return -EROFS; if (isReadOnly(nullptr)) {
return -EROFS;
}
return withCipherPath("removexattr", path, return withCipherPath("removexattr", path,
bind(_do_removexattr, _1, _2, name)); bind(_do_removexattr, _1, _2, name));

View File

@ -18,18 +18,18 @@
#include <cerrno> #include <cerrno>
#include <cstdio> #include <cstdio>
#include <cstdlib>
#include <cstring> #include <cstring>
#include <ctime>
#include <exception> #include <exception>
#include <getopt.h> #include <getopt.h>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <pthread.h> #include <pthread.h>
#include <sstream> #include <sstream>
#include <stdlib.h>
#include <string> #include <string>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include "Context.h" #include "Context.h"
@ -85,17 +85,36 @@ struct EncFS_Args {
ostringstream ss; ostringstream ss;
ss << (isDaemon ? "(daemon) " : "(fg) "); ss << (isDaemon ? "(daemon) " : "(fg) ");
ss << (isThreaded ? "(threaded) " : "(UP) "); ss << (isThreaded ? "(threaded) " : "(UP) ");
if (idleTimeout > 0) ss << "(timeout " << idleTimeout << ") "; if (idleTimeout > 0) {
if (opts->checkKey) ss << "(keyCheck) "; ss << "(timeout " << idleTimeout << ") ";
if (opts->forceDecode) ss << "(forceDecode) "; }
if (opts->ownerCreate) ss << "(ownerCreate) "; if (opts->checkKey) {
if (opts->useStdin) ss << "(useStdin) "; ss << "(keyCheck) ";
if (opts->annotate) ss << "(annotate) "; }
if (opts->reverseEncryption) ss << "(reverseEncryption) "; if (opts->forceDecode) {
if (opts->mountOnDemand) ss << "(mountOnDemand) "; ss << "(forceDecode) ";
if (opts->delayMount) ss << "(delayMount) "; }
for (int i = 0; i < fuseArgc; ++i) ss << fuseArgv[i] << ' '; if (opts->ownerCreate) {
ss << "(ownerCreate) ";
}
if (opts->useStdin) {
ss << "(useStdin) ";
}
if (opts->annotate) {
ss << "(annotate) ";
}
if (opts->reverseEncryption) {
ss << "(reverseEncryption) ";
}
if (opts->mountOnDemand) {
ss << "(mountOnDemand) ";
}
if (opts->delayMount) {
ss << "(delayMount) ";
}
for (int i = 0; i < fuseArgc; ++i) {
ss << fuseArgv[i] << ' ';
}
return ss.str(); return ss.str();
} }
@ -161,18 +180,21 @@ static void FuseUsage() {
int argc = 2; int argc = 2;
const char *argv[] = {"...", "-h"}; const char *argv[] = {"...", "-h"};
fuse_main(argc, const_cast<char **>(argv), (fuse_operations *)NULL, NULL); fuse_main(argc, const_cast<char **>(argv), (fuse_operations *)nullptr,
nullptr);
} }
#define PUSHARG(ARG) \ #define PUSHARG(ARG) \
do { \ do { \
rAssert(out->fuseArgc < MaxFuseArgs); \ rAssert(out->fuseArgc < MaxFuseArgs); \
out->fuseArgv[out->fuseArgc++] = (ARG); \ out->fuseArgv[out->fuseArgc++] = (ARG); \
} while (0) } while (false)
static string slashTerminate(const string &src) { static string slashTerminate(const string &src) {
string result = src; string result = src;
if (result[result.length() - 1] != '/') result.append("/"); if (result[result.length() - 1] != '/') {
result.append("/");
}
return result; return result;
} }
@ -202,37 +224,37 @@ static bool processArgs(int argc, char *argv[],
// leave a space for mount point, as FUSE expects the mount point before // leave a space for mount point, as FUSE expects the mount point before
// any flags // any flags
out->fuseArgv[1] = NULL; out->fuseArgv[1] = nullptr;
++out->fuseArgc; ++out->fuseArgc;
// TODO: can flags be internationalized? // TODO: can flags be internationalized?
static struct option long_options[] = { static struct option long_options[] = {
{"fuse-debug", 0, 0, 'd'}, // Fuse debug mode {"fuse-debug", 0, nullptr, 'd'}, // Fuse debug mode
{"forcedecode", 0, 0, 'D'}, // force decode {"forcedecode", 0, nullptr, 'D'}, // force decode
// {"foreground", 0, 0, 'f'}, // foreground mode (no daemon) // {"foreground", 0, 0, 'f'}, // foreground mode (no daemon)
{"fuse-help", 0, 0, 'H'}, // fuse_mount usage {"fuse-help", 0, nullptr, 'H'}, // fuse_mount usage
{"idle", 1, 0, 'i'}, // idle timeout {"idle", 1, nullptr, 'i'}, // idle timeout
{"anykey", 0, 0, 'k'}, // skip key checks {"anykey", 0, nullptr, 'k'}, // skip key checks
{"no-default-flags", 0, 0, 'N'}, // don't use default fuse flags {"no-default-flags", 0, nullptr, 'N'}, // don't use default fuse flags
{"ondemand", 0, 0, 'm'}, // mount on-demand {"ondemand", 0, nullptr, 'm'}, // mount on-demand
{"delaymount", 0, 0, 'M'}, // delay initial mount until use {"delaymount", 0, nullptr, 'M'}, // delay initial mount until use
{"public", 0, 0, 'P'}, // public mode {"public", 0, nullptr, 'P'}, // public mode
{"extpass", 1, 0, 'p'}, // external password program {"extpass", 1, nullptr, 'p'}, // external password program
// {"single-thread", 0, 0, 's'}, // single-threaded mode // {"single-thread", 0, 0, 's'}, // single-threaded mode
{"stdinpass", 0, 0, 'S'}, // read password from stdin {"stdinpass", 0, nullptr, 'S'}, // read password from stdin
{"syslogtag", 1, 0, 't'}, // syslog tag {"syslogtag", 1, nullptr, 't'}, // syslog tag
{"annotate", 0, 0, {"annotate", 0, nullptr,
LONG_OPT_ANNOTATE}, // Print annotation lines to stderr LONG_OPT_ANNOTATE}, // Print annotation lines to stderr
{"nocache", 0, 0, LONG_OPT_NOCACHE}, // disable caching {"nocache", 0, nullptr, LONG_OPT_NOCACHE}, // disable caching
{"verbose", 0, 0, 'v'}, // verbose mode {"verbose", 0, nullptr, 'v'}, // verbose mode
{"version", 0, 0, 'V'}, // version {"version", 0, nullptr, 'V'}, // version
{"reverse", 0, 0, 'r'}, // reverse encryption {"reverse", 0, nullptr, 'r'}, // reverse encryption
{"standard", 0, 0, '1'}, // standard configuration {"standard", 0, nullptr, '1'}, // standard configuration
{"paranoia", 0, 0, '2'}, // standard configuration {"paranoia", 0, nullptr, '2'}, // standard configuration
{"require-macs", 0, 0, LONG_OPT_REQUIRE_MAC}, // require MACs {"require-macs", 0, nullptr, LONG_OPT_REQUIRE_MAC}, // require MACs
{0, 0, 0, 0}}; {nullptr, 0, nullptr, 0}};
while (1) { while (true) {
int option_index = 0; int option_index = 0;
// 's' : single-threaded mode // 's' : single-threaded mode
@ -247,7 +269,9 @@ static bool processArgs(int argc, char *argv[],
int res = int res =
getopt_long(argc, argv, "HsSfvdmi:o:t:", long_options, &option_index); getopt_long(argc, argv, "HsSfvdmi:o:t:", long_options, &option_index);
if (res == -1) break; if (res == -1) {
break;
}
switch (res) { switch (res) {
case '1': case '1':
@ -283,7 +307,7 @@ static bool processArgs(int argc, char *argv[],
PUSHARG("-d"); PUSHARG("-d");
break; break;
case 'i': case 'i':
out->idleTimeout = strtol(optarg, (char **)NULL, 10); out->idleTimeout = strtol(optarg, (char **)nullptr, 10);
out->opts->idleTracking = true; out->opts->idleTracking = true;
break; break;
case 'k': case 'k':
@ -342,9 +366,9 @@ static bool processArgs(int argc, char *argv[],
out->opts->passwordProgram.assign(optarg); out->opts->passwordProgram.assign(optarg);
break; break;
case 'P': case 'P':
if (geteuid() != 0) if (geteuid() != 0) {
RLOG(WARNING) << "option '--public' ignored for non-root user"; RLOG(WARNING) << "option '--public' ignored for non-root user";
else { } else {
out->opts->ownerCreate = true; out->opts->ownerCreate = true;
// add 'allow_other' option // add 'allow_other' option
// add 'default_permissions' option (default) // add 'default_permissions' option (default)
@ -358,7 +382,7 @@ static bool processArgs(int argc, char *argv[],
#if defined(HAVE_XATTR) #if defined(HAVE_XATTR)
// "--verbose" has to be passed before "--version" for this to work. // "--verbose" has to be passed before "--version" for this to work.
if (out->isVerbose) { if (out->isVerbose) {
cerr << "Compiled with : HAVE_XATTR" << endl; cerr << "Compiled with : HAVE_XATTR" << endl;
} }
#endif #endif
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
@ -379,7 +403,9 @@ static bool processArgs(int argc, char *argv[],
} }
} }
if (!out->isThreaded) PUSHARG("-s"); if (!out->isThreaded) {
PUSHARG("-s");
}
// we should have at least 2 arguments left over - the source directory and // we should have at least 2 arguments left over - the source directory and
// the mount point. // the mount point.
@ -492,10 +518,10 @@ static bool processArgs(int argc, char *argv[],
static void *idleMonitor(void *); static void *idleMonitor(void *);
void *encfs_init(fuse_conn_info *conn) { void *encfs_init(fuse_conn_info *conn) {
EncFS_Context *ctx = (EncFS_Context *)fuse_get_context()->private_data; auto *ctx = (EncFS_Context *)fuse_get_context()->private_data;
// set fuse connection options // set fuse connection options
conn->async_read = true; conn->async_read = 1u;
// if an idle timeout is specified, then setup a thread to monitor the // if an idle timeout is specified, then setup a thread to monitor the
// filesystem. // filesystem.
@ -503,7 +529,8 @@ void *encfs_init(fuse_conn_info *conn) {
VLOG(1) << "starting idle monitoring thread"; VLOG(1) << "starting idle monitoring thread";
ctx->running = true; ctx->running = true;
int res = pthread_create(&ctx->monitorThread, 0, idleMonitor, (void *)ctx); int res =
pthread_create(&ctx->monitorThread, nullptr, idleMonitor, (void *)ctx);
if (res != 0) { if (res != 0) {
RLOG(ERROR) << "error starting idle monitor thread, " RLOG(ERROR) << "error starting idle monitor thread, "
"res = " "res = "
@ -532,8 +559,9 @@ int main(int argc, char *argv[]) {
// anything that comes from the user should be considered tainted until // anything that comes from the user should be considered tainted until
// we've processed it and only allowed through what we support. // we've processed it and only allowed through what we support.
std::shared_ptr<EncFS_Args> encfsArgs(new EncFS_Args); std::shared_ptr<EncFS_Args> encfsArgs(new EncFS_Args);
for (int i = 0; i < MaxFuseArgs; ++i) for (int i = 0; i < MaxFuseArgs; ++i) {
encfsArgs->fuseArgv[i] = NULL; // libfuse expects null args.. encfsArgs->fuseArgv[i] = nullptr; // libfuse expects null args..
}
if (argc == 1 || !processArgs(argc, argv, encfsArgs)) { if (argc == 1 || !processArgs(argc, argv, encfsArgs)) {
usage(argv[0]); usage(argv[0]);
@ -597,7 +625,7 @@ int main(int argc, char *argv[]) {
// context is not a smart pointer because it will live for the life of // context is not a smart pointer because it will live for the life of
// the filesystem. // the filesystem.
auto ctx = std::shared_ptr<EncFS_Context>(new EncFS_Context); auto ctx = std::make_shared<EncFS_Context>();
ctx->publicFilesystem = encfsArgs->opts->ownerCreate; ctx->publicFilesystem = encfsArgs->opts->ownerCreate;
RootPtr rootInfo = initFS(ctx.get(), encfsArgs->opts); RootPtr rootInfo = initFS(ctx.get(), encfsArgs->opts);
@ -614,7 +642,7 @@ int main(int argc, char *argv[]) {
ctx->args = encfsArgs; ctx->args = encfsArgs;
ctx->opts = encfsArgs->opts; ctx->opts = encfsArgs->opts;
if (encfsArgs->isThreaded == false && encfsArgs->idleTimeout > 0) { if (!encfsArgs->isThreaded && encfsArgs->idleTimeout > 0) {
// xgroup(usage) // xgroup(usage)
cerr << _("Note: requested single-threaded mode, but an idle\n" cerr << _("Note: requested single-threaded mode, but an idle\n"
"timeout was specified. The filesystem will operate\n" "timeout was specified. The filesystem will operate\n"
@ -636,7 +664,9 @@ int main(int argc, char *argv[]) {
try { try {
time_t startTime, endTime; time_t startTime, endTime;
if (encfsArgs->opts->annotate) cerr << "$STATUS$ fuse_main_start" << endl; if (encfsArgs->opts->annotate) {
cerr << "$STATUS$ fuse_main_start" << endl;
}
// FIXME: workaround for fuse_main returning an error on normal // FIXME: workaround for fuse_main returning an error on normal
// exit. Only print information if fuse_main returned // exit. Only print information if fuse_main returned
@ -650,9 +680,13 @@ int main(int argc, char *argv[]) {
time(&endTime); time(&endTime);
if (encfsArgs->opts->annotate) cerr << "$STATUS$ fuse_main_end" << endl; if (encfsArgs->opts->annotate) {
cerr << "$STATUS$ fuse_main_end" << endl;
}
if (res == 0) returnCode = EXIT_SUCCESS; if (res == 0) {
returnCode = EXIT_SUCCESS;
}
if (res != 0 && encfsArgs->isDaemon && (oldStderr >= 0) && if (res != 0 && encfsArgs->isDaemon && (oldStderr >= 0) &&
(endTime - startTime <= 1)) { (endTime - startTime <= 1)) {
@ -681,7 +715,7 @@ int main(int argc, char *argv[]) {
pthread_cond_signal(&ctx->wakeupCond); pthread_cond_signal(&ctx->wakeupCond);
pthread_mutex_unlock(&ctx->wakeupMutex); pthread_mutex_unlock(&ctx->wakeupMutex);
VLOG(1) << "joining with idle monitoring thread"; VLOG(1) << "joining with idle monitoring thread";
pthread_join(ctx->monitorThread, 0); pthread_join(ctx->monitorThread, nullptr);
VLOG(1) << "join done"; VLOG(1) << "join done";
} }
} }
@ -707,7 +741,7 @@ const int ActivityCheckInterval = 10;
static bool unmountFS(EncFS_Context *ctx); static bool unmountFS(EncFS_Context *ctx);
static void *idleMonitor(void *_arg) { static void *idleMonitor(void *_arg) {
EncFS_Context *ctx = (EncFS_Context *)_arg; auto *ctx = (EncFS_Context *)_arg;
std::shared_ptr<EncFS_Args> arg = ctx->args; std::shared_ptr<EncFS_Args> arg = ctx->args;
const int timeoutCycles = 60 * arg->idleTimeout / ActivityCheckInterval; const int timeoutCycles = 60 * arg->idleTimeout / ActivityCheckInterval;
@ -715,7 +749,8 @@ static void *idleMonitor(void *_arg) {
bool unmountres = false; bool unmountres = false;
// We will notify when FS will be unmounted, so notify that it has just been mounted // We will notify when FS will be unmounted, so notify that it has just been
// mounted
RLOG(INFO) << "Filesystem mounted: " << arg->opts->mountPoint; RLOG(INFO) << "Filesystem mounted: " << arg->opts->mountPoint;
pthread_mutex_lock(&ctx->wakeupMutex); pthread_mutex_lock(&ctx->wakeupMutex);
@ -724,12 +759,13 @@ static void *idleMonitor(void *_arg) {
int usage, openCount; int usage, openCount;
ctx->getAndResetUsageCounter(&usage, &openCount); ctx->getAndResetUsageCounter(&usage, &openCount);
if (usage == 0 && ctx->isMounted()) if (usage == 0 && ctx->isMounted()) {
++idleCycles; ++idleCycles;
else { } else {
if (idleCycles >= timeoutCycles) if (idleCycles >= timeoutCycles) {
RLOG(INFO) << "Filesystem no longer inactive: " RLOG(INFO) << "Filesystem no longer inactive: "
<< arg->opts->mountPoint; << arg->opts->mountPoint;
}
idleCycles = 0; idleCycles = 0;
} }
@ -751,7 +787,7 @@ static void *idleMonitor(void *_arg) {
<< timeoutCycles; << timeoutCycles;
struct timeval currentTime; struct timeval currentTime;
gettimeofday(&currentTime, 0); gettimeofday(&currentTime, nullptr);
struct timespec wakeupTime; struct timespec wakeupTime;
wakeupTime.tv_sec = currentTime.tv_sec + ActivityCheckInterval; wakeupTime.tv_sec = currentTime.tv_sec + ActivityCheckInterval;
wakeupTime.tv_nsec = currentTime.tv_usec * 1000; wakeupTime.tv_nsec = currentTime.tv_usec * 1000;
@ -760,13 +796,15 @@ static void *idleMonitor(void *_arg) {
pthread_mutex_unlock(&ctx->wakeupMutex); pthread_mutex_unlock(&ctx->wakeupMutex);
// If we are here FS has been unmounted, so if we did not unmount ourselves (manual, kill...), notify // If we are here FS has been unmounted, so if we did not unmount ourselves
if (!unmountres) // (manual, kill...), notify
if (!unmountres) {
RLOG(INFO) << "Filesystem unmounted: " << arg->opts->mountPoint; RLOG(INFO) << "Filesystem unmounted: " << arg->opts->mountPoint;
}
VLOG(1) << "Idle monitoring thread exiting"; VLOG(1) << "Idle monitoring thread exiting";
return 0; return nullptr;
} }
static bool unmountFS(EncFS_Context *ctx) { static bool unmountFS(EncFS_Context *ctx) {
@ -777,15 +815,14 @@ static bool unmountFS(EncFS_Context *ctx) {
ctx->setRoot(std::shared_ptr<DirNode>()); ctx->setRoot(std::shared_ptr<DirNode>());
return false; return false;
} else {
// Time to unmount!
#if FUSE_USE_VERSION < 30
fuse_unmount(arg->opts->mountPoint.c_str(), NULL);
#else
fuse_unmount(fuse_get_context()->fuse);
#endif
// fuse_unmount succeeds and returns void
RLOG(INFO) << "Filesystem inactive, unmounted: " << arg->opts->mountPoint;
return true;
} }
// Time to unmount!
#if FUSE_USE_VERSION < 30
fuse_unmount(arg->opts->mountPoint.c_str(), nullptr);
#else
fuse_unmount(fuse_get_context()->fuse);
#endif
// fuse_unmount succeeds and returns void
RLOG(INFO) << "Filesystem inactive, unmounted: " << arg->opts->mountPoint;
return true;
} }

View File

@ -20,9 +20,9 @@
#include "openssl.h" #include "openssl.h"
#include <cstdlib>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <pthread.h> #include <pthread.h>
#include <stdlib.h>
#define NO_DES #define NO_DES
#include <openssl/rand.h> #include <openssl/rand.h>
@ -37,20 +37,21 @@ namespace encfs {
unsigned long pthreads_thread_id() { return (unsigned long)pthread_self(); } unsigned long pthreads_thread_id() { return (unsigned long)pthread_self(); }
static pthread_mutex_t *crypto_locks = NULL; static pthread_mutex_t *crypto_locks = nullptr;
void pthreads_locking_callback(int mode, int n, const char *caller_file, void pthreads_locking_callback(int mode, int n, 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 == nullptr) {
VLOG(1) << "Allocating " << CRYPTO_num_locks() << " locks for OpenSSL"; VLOG(1) << "Allocating " << CRYPTO_num_locks() << " locks for OpenSSL";
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, nullptr);
}
} }
if (mode & CRYPTO_LOCK) { if ((mode & CRYPTO_LOCK) != 0) {
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);
@ -58,11 +59,12 @@ void pthreads_locking_callback(int mode, int n, const char *caller_file,
} }
void pthreads_locking_cleanup() { void pthreads_locking_cleanup() {
if (crypto_locks) { if (crypto_locks != nullptr) {
for (int i = 0; i < CRYPTO_num_locks(); ++i) for (int i = 0; i < CRYPTO_num_locks(); ++i) {
pthread_mutex_destroy(crypto_locks + i); pthread_mutex_destroy(crypto_locks + i);
}
delete[] crypto_locks; delete[] crypto_locks;
crypto_locks = NULL; crypto_locks = nullptr;
} }
} }
@ -95,7 +97,9 @@ void openssl_shutdown(bool threaded) {
ENGINE_cleanup(); ENGINE_cleanup();
#endif #endif
if (threaded) pthreads_locking_cleanup(); if (threaded) {
pthreads_locking_cleanup();
}
} }
} // namespace encfs } // namespace encfs

View File

@ -76,7 +76,7 @@ char *readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) {
/* 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 (nullptr);
} }
restart: restart:
@ -85,9 +85,9 @@ restart:
* 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) != 0) {
errno = ENOTTY; errno = ENOTTY;
return (NULL); return (nullptr);
} }
input = STDIN_FILENO; input = STDIN_FILENO;
output = STDERR_FILENO; output = STDERR_FILENO;
@ -112,7 +112,9 @@ restart:
/* 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)) term.c_lflag &= ~(ECHO | ECHONL); if ((flags & RPP_ECHO_ON) == 0) {
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;
@ -127,35 +129,46 @@ restart:
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)) ch &= 0x7f; if ((flags & RPP_SEVENBIT) != 0) {
if (isalpha(ch)) { ch &= 0x7f;
if ((flags & RPP_FORCELOWER)) ch = tolower(ch); }
if ((flags & RPP_FORCEUPPER)) ch = toupper(ch); if (isalpha(ch) != 0) {
if ((flags & RPP_FORCELOWER) != 0) {
ch = tolower(ch);
}
if ((flags & RPP_FORCEUPPER) != 0) {
ch = toupper(ch);
}
} }
*p++ = ch; *p++ = ch;
} }
} }
*p = '\0'; *p = '\0';
save_errno = errno; save_errno = errno;
if (!(term.c_lflag & ECHO)) (void)write(output, "\n", 1); if ((term.c_lflag & ECHO) == 0u) {
(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(SIGHUP, &savehup, NULL); (void)sigaction(SIGINT, &saveint, nullptr);
(void)sigaction(SIGQUIT, &savequit, NULL); (void)sigaction(SIGHUP, &savehup, nullptr);
(void)sigaction(SIGTERM, &saveterm, NULL); (void)sigaction(SIGQUIT, &savequit, nullptr);
(void)sigaction(SIGTSTP, &savetstp, NULL); (void)sigaction(SIGTERM, &saveterm, nullptr);
(void)sigaction(SIGTTIN, &savettin, NULL); (void)sigaction(SIGTSTP, &savetstp, nullptr);
(void)sigaction(SIGTTOU, &savettou, NULL); (void)sigaction(SIGTTIN, &savettin, nullptr);
if (input != STDIN_FILENO) (void)close(input); (void)sigaction(SIGTTOU, &savettou, nullptr);
if (input != STDIN_FILENO) {
(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 != 0) {
kill(getpid(), signo); kill(getpid(), signo);
switch (signo) { switch (signo) {
case SIGTSTP: case SIGTSTP:
@ -167,7 +180,7 @@ restart:
} }
errno = save_errno; errno = save_errno;
return (nr == -1 ? NULL : buf); return (nr == -1 ? nullptr : buf);
} }
#endif /* HAVE_READPASSPHRASE */ #endif /* HAVE_READPASSPHRASE */

View File

@ -173,11 +173,12 @@ bool runTests(const std::shared_ptr<Cipher> &cipher, bool verbose) {
cfg.assignKeyData(keyBuf, encodedKeySize); cfg.assignKeyData(keyBuf, encodedKeySize);
// save config // save config
//Creation of a temporary file should be more platform independent. On c++17 we could use std::filesystem. // Creation of a temporary file should be more platform independent. On
// c++17 we could use std::filesystem.
string name = "/tmp/encfstestXXXXXX"; string name = "/tmp/encfstestXXXXXX";
int tmpFd = mkstemp(&name[0]); int tmpFd = mkstemp(&name[0]);
rAssert(-1 != tmpFd); rAssert(-1 != tmpFd);
//mkstemp opens the temporary file, but we only need its name -> close it // mkstemp opens the temporary file, but we only need its name -> close it
rAssert(0 == close(tmpFd)); rAssert(0 == close(tmpFd));
{ {
auto ok = writeV6Config(name.c_str(), &cfg); auto ok = writeV6Config(name.c_str(), &cfg);
@ -190,9 +191,9 @@ bool runTests(const std::shared_ptr<Cipher> &cipher, bool verbose) {
auto ok = readV6Config(name.c_str(), &cfg2, nullptr); auto ok = readV6Config(name.c_str(), &cfg2, nullptr);
rAssert(ok == true); rAssert(ok == true);
} }
//delete the temporary file where we stored the config // delete the temporary file where we stored the config
rAssert(0 == unlink(name.c_str())); rAssert(0 == unlink(name.c_str()));
// check.. // check..
rAssert(cfg.cipherIface.implements(cfg2.cipherIface)); rAssert(cfg.cipherIface.implements(cfg2.cipherIface));
rAssert(cfg.keySize == cfg2.keySize); rAssert(cfg.keySize == cfg2.keySize);