replace rlog with easylogging++

This commit is contained in:
Valient Gough 2015-06-17 20:33:57 -07:00
parent f345450abd
commit 46a5c9f4f9
No known key found for this signature in database
GPG Key ID: B515DCEB95967051
70 changed files with 7911 additions and 1129 deletions

View File

@ -9,6 +9,8 @@ set (ENCFS_VERSION "${ENCFS_MAJOR}.${ENCFS_MINOR}.${ENCFS_PATCH}")
set (ENCFS_SOVERSION "1.9") set (ENCFS_SOVERSION "1.9")
set (ENCFS_NAME "Encrypted Filesystem") set (ENCFS_NAME "Encrypted Filesystem")
option(IWYU "Build with IWYU analyais." OFF)
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_SOURCE_DIR}/cmake") "${CMAKE_SOURCE_DIR}/cmake")
@ -62,10 +64,6 @@ else ()
include_directories (${TINYXML_INCLUDE_DIR}) include_directories (${TINYXML_INCLUDE_DIR})
endif () endif ()
find_package (RLog REQUIRED)
add_definitions (-DRLOG_COMPONENT="encfs")
include_directories (${RLOG_INCLUDE_DIR})
find_program (POD2MAN pod2man) find_program (POD2MAN pod2man)
include (FindGettext) include (FindGettext)
@ -95,6 +93,14 @@ check_function_exists_glibc (lchmod HAVE_LCHMOD)
set (CMAKE_THREAD_PREFER_PTHREAD) set (CMAKE_THREAD_PREFER_PTHREAD)
find_package (Threads REQUIRED) find_package (Threads REQUIRED)
# Logging.
add_definitions (-DELPP_THREAD_SAFE -DELPP_DISABLE_DEFAULT_CRASH_HANDLING)
check_include_file_cxx (syslog.h HAVE_SYSLOG_H)
if (HAVE_SYSLOG_H)
message ("-- Enabled syslog logging support")
add_definitions(-DELPP_SYSLOG)
endif (HAVE_SYSLOG_H)
# Packaging config. # Packaging config.
set (CPACK_PACKAGE_NAME "encfs") set (CPACK_PACKAGE_NAME "encfs")
set (CPACK_PACKAGE_VERSION_MAJOR ${ENCFS_MAJOR}) set (CPACK_PACKAGE_VERSION_MAJOR ${ENCFS_MAJOR})
@ -124,6 +130,7 @@ set(SOURCE_FILES
encfs/Context.cpp encfs/Context.cpp
encfs/DirNode.cpp encfs/DirNode.cpp
encfs/encfs.cpp encfs/encfs.cpp
encfs/Error.cpp
encfs/FileIO.cpp encfs/FileIO.cpp
encfs/FileNode.cpp encfs/FileNode.cpp
encfs/FileUtils.cpp encfs/FileUtils.cpp
@ -148,11 +155,21 @@ target_link_libraries(encfs
${FUSE_LIBRARIES} ${FUSE_LIBRARIES}
${OPENSSL_LIBRARIES} ${OPENSSL_LIBRARIES}
${TINYXML_LIBRARIES} ${TINYXML_LIBRARIES}
${RLOG_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
) )
install (TARGETS encfs DESTINATION lib) install (TARGETS encfs DESTINATION lib)
if (IWYU)
if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.2)
find_program(iwyu_path NAMES include-what-you-use iwyu)
if (iwyu_path)
message ("-- Enabled IWYU")
set_property(TARGET encfs PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${iwyu_path})
endif()
endif()
endif()
# Set RPATH to library install path. # Set RPATH to library install path.
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

View File

@ -41,13 +41,16 @@ Dependencies
EncFS depends on a number of libraries: EncFS depends on a number of libraries:
openssl fuse tinyxml2 gettext libintl librlog * fuse : the userspace filesystem layer
* openssl : used for cryptographic primitives
* tinyxml2 : for reading and writing XML configuration files
* gettext : internationalization support
* libintl : internationalization support
Compiling on Debian and Ubuntu Compiling on Debian and Ubuntu
============================== ==============================
We use separate [Drone.io](https://drone.io/) and [CircleCi](https://circleci.com/) builds to automatically See the automated build static in README.md for current build status on Ubuntu systems.
test every commit. See the README.md file for current build status.
The build configuration files (.drone.yml and circle.yml) therefore The build configuration files (.drone.yml and circle.yml) always contains up-to-date
always contains up-to-date instructions to build EncFS on Ubuntu distributions. instructions to build EncFS on Ubuntu distributions.

View File

@ -2,4 +2,4 @@ set -x
set -e set -e
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_INSTALL_PREFIX:PATH=/tmp/encfs -DCMAKE_BUILD_TYPE=Debug .. cmake -DCMAKE_INSTALL_PREFIX:PATH=/tmp/encfs -DCMAKE_BUILD_TYPE=Debug -DMINIGLOG=ON ..

View File

@ -4,7 +4,7 @@ machine:
dependencies: dependencies:
pre: pre:
- sudo apt-get install cmake libfuse-dev librlog-dev libgettextpo-dev - sudo apt-get install cmake libfuse-dev libgettextpo-dev
- bash ./ci/install-gcc.sh - bash ./ci/install-gcc.sh
test: test:

View File

@ -1,28 +0,0 @@
# FindRLog
# --------
#
# Find RLog
#
# Find the RLog logging library. This module defines
#
# ::
#
# RLOG_INCLUDE_DIR, where to find rlog.h, etc.
# RLOG_LIBRARIES, the libraries needed to use RLog.
# RLOG_FOUND, If false, do not try to use RLog.
find_path(RLOG_INCLUDE_DIR rlog/rlog.h)
set(RLOG_NAMES ${RLOG_NAMES} rlog librlog)
find_library(RLOG_LIBRARY NAMES ${RLOG_NAMES} )
# handle the QUIETLY and REQUIRED arguments and set RLOG_FOUND to TRUE if
# all listed variables are TRUE
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(RLOG DEFAULT_MSG RLOG_LIBRARY RLOG_INCLUDE_DIR)
if(RLOG_FOUND)
set(RLOG_LIBRARIES ${RLOG_LIBRARY})
endif()
mark_as_advanced(RLOG_LIBRARY RLOG_INCLUDE_DIR )

View File

@ -32,7 +32,6 @@ RUN apt-get -y upgrade \
git \ git \
libfuse-dev \ libfuse-dev \
libssl-dev \ libssl-dev \
librlog-dev \
gettext \ gettext \
libgettextpo-dev \ libgettextpo-dev \
&& apt-get clean && apt-get clean

View File

@ -20,16 +20,15 @@
#include "BlockFileIO.h" #include "BlockFileIO.h"
#include <inttypes.h> #include <cstring> // for memset, memcpy, NULL
#include <rlog/rlog.h>
#include <cstring>
#include <memory>
#include "FSConfig.h" #include "Error.h"
#include "FileIO.h" #include "FSConfig.h" // for FSConfigPtr
#include "FileUtils.h" #include "FileIO.h" // for IORequest, FileIO
#include "MemoryPool.h" #include "FileUtils.h" // for EncFS_Opts
#include "i18n.h" #include "MemoryPool.h" // for MemBlock, release, allocation
namespace encfs {
template <typename Type> template <typename Type>
inline Type min(Type A, Type B) { inline Type min(Type A, Type B) {
@ -43,7 +42,7 @@ static void clearCache(IORequest &req, int blockSize) {
BlockFileIO::BlockFileIO(int blockSize, const FSConfigPtr &cfg) BlockFileIO::BlockFileIO(int blockSize, const FSConfigPtr &cfg)
: _blockSize(blockSize), _allowHoles(cfg->config->allowHoles) { : _blockSize(blockSize), _allowHoles(cfg->config->allowHoles) {
rAssert(_blockSize > 1); CHECK(_blockSize > 1);
_cache.data = new unsigned char[_blockSize]; _cache.data = new unsigned char[_blockSize];
_noCache = cfg->opts->noCache; _noCache = cfg->opts->noCache;
} }
@ -60,9 +59,8 @@ BlockFileIO::~BlockFileIO() {
* returned data as neccessary. * returned data as neccessary.
*/ */
ssize_t BlockFileIO::cacheReadOneBlock(const IORequest &req) const { ssize_t BlockFileIO::cacheReadOneBlock(const IORequest &req) const {
CHECK(req.dataLen <= _blockSize);
rAssert(req.dataLen <= _blockSize); CHECK(req.offset % _blockSize == 0);
rAssert(req.offset % _blockSize == 0);
/* we can satisfy the request even if _cache.dataLen is too short, because /* we can satisfy the request even if _cache.dataLen is too short, because
* we always request a full block during reads. This just means we are * we always request a full block during reads. This just means we are
@ -115,7 +113,7 @@ bool BlockFileIO::cacheWriteOneBlock(const IORequest &req) {
* lower layer. * lower layer.
*/ */
ssize_t BlockFileIO::read(const IORequest &req) const { ssize_t BlockFileIO::read(const IORequest &req) const {
rAssert(_blockSize != 0); CHECK(_blockSize != 0);
int partialOffset = req.offset % _blockSize; int partialOffset = req.offset % _blockSize;
off_t blockNum = req.offset / _blockSize; off_t blockNum = req.offset / _blockSize;
@ -149,11 +147,10 @@ ssize_t BlockFileIO::read(const IORequest &req) const {
} }
ssize_t readSize = cacheReadOneBlock(blockReq); ssize_t readSize = cacheReadOneBlock(blockReq);
if (unlikely(readSize <= partialOffset)) if (readSize <= partialOffset) break; // didn't get enough bytes
break; // didn't get enough bytes
int cpySize = min((size_t)(readSize - partialOffset), size); int cpySize = min((size_t)(readSize - partialOffset), size);
rAssert(cpySize <= readSize); CHECK(cpySize <= readSize);
// if we read to a temporary buffer, then move the data // if we read to a temporary buffer, then move the data
if (blockReq.data != out) if (blockReq.data != out)
@ -165,7 +162,7 @@ ssize_t BlockFileIO::read(const IORequest &req) const {
++blockNum; ++blockNum;
partialOffset = 0; partialOffset = 0;
if (unlikely(readSize < _blockSize)) break; if (readSize < _blockSize) break;
} }
if (mb.data) MemoryPool::release(mb); if (mb.data) MemoryPool::release(mb);
@ -175,11 +172,10 @@ ssize_t BlockFileIO::read(const IORequest &req) const {
} }
bool BlockFileIO::write(const IORequest &req) { bool BlockFileIO::write(const IORequest &req) {
rAssert(_blockSize != 0); CHECK(_blockSize != 0);
off_t fileSize = getSize(); off_t fileSize = getSize();
if (fileSize < 0) if (fileSize < 0) return false;
return false;
// where write request begins // where write request begins
off_t blockNum = req.offset / _blockSize; off_t blockNum = req.offset / _blockSize;
@ -301,7 +297,7 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
cacheWriteOneBlock(req); cacheWriteOneBlock(req);
} }
} else } else
rDebug("optimization: not padding last block"); VLOG(1) << "optimization: not padding last block";
} else { } else {
mb = MemoryPool::allocate(_blockSize); mb = MemoryPool::allocate(_blockSize);
req.data = mb.data; req.data = mb.data;
@ -315,7 +311,7 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
// 1. req.dataLen == 0, iff oldSize was already a multiple of blocksize // 1. req.dataLen == 0, iff oldSize was already a multiple of blocksize
if (req.dataLen != 0) { if (req.dataLen != 0) {
rDebug("padding block %" PRIi64, oldLastBlock); VLOG(1) << "padding block " << oldLastBlock;
memset(mb.data, 0, _blockSize); memset(mb.data, 0, _blockSize);
cacheReadOneBlock(req); cacheReadOneBlock(req);
req.dataLen = _blockSize; // expand to full block size req.dataLen = _blockSize; // expand to full block size
@ -326,7 +322,7 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
// 2, pad zero blocks unless holes are allowed // 2, pad zero blocks unless holes are allowed
if (!_allowHoles) { if (!_allowHoles) {
for (; oldLastBlock != newLastBlock; ++oldLastBlock) { for (; oldLastBlock != newLastBlock; ++oldLastBlock) {
rDebug("padding block %" PRIi64, oldLastBlock); VLOG(1) << "padding block " << oldLastBlock;
req.offset = oldLastBlock * _blockSize; req.offset = oldLastBlock * _blockSize;
req.dataLen = _blockSize; req.dataLen = _blockSize;
memset(mb.data, 0, req.dataLen); memset(mb.data, 0, req.dataLen);
@ -386,8 +382,8 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
if ((rdSz < 0) || (!wrRes)) { if ((rdSz < 0) || (!wrRes)) {
// rwarning - unlikely to ever occur.. // rwarning - unlikely to ever occur..
rWarning(_("truncate failure: read %i bytes, partial block of %i"), RLOG(WARNING) << "truncate failure: read " << rdSz
(int)rdSz, partialBlock); << " bytes, partial block of " << partialBlock;
} }
MemoryPool::release(mb); MemoryPool::release(mb);
@ -399,3 +395,5 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
return res; return res;
} }
} // namespace encfs

View File

@ -26,6 +26,8 @@
#include "FSConfig.h" #include "FSConfig.h"
#include "FileIO.h" #include "FileIO.h"
namespace encfs {
/* /*
Implements block scatter / gather interface. Requires derived classes to Implements block scatter / gather interface. Requires derived classes to
implement readOneBlock() / writeOneBlock() at a minimum. implement readOneBlock() / writeOneBlock() at a minimum.
@ -65,4 +67,6 @@ class BlockFileIO : public FileIO {
mutable IORequest _cache; mutable IORequest _cache;
}; };
} // namespace encfs
#endif #endif

View File

@ -20,42 +20,37 @@
#include "BlockNameIO.h" #include "BlockNameIO.h"
#include <rlog/Error.h>
#include <rlog/rlog.h>
#include <cstring> #include <cstring>
#include <memory>
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "Error.h"
#include "Interface.h"
#include "NameIO.h" #include "NameIO.h"
#include "base64.h" #include "base64.h"
#include "internal/easylogging++.h"
#include "intl/gettext.h" #include "intl/gettext.h"
namespace rlog { namespace encfs {
class RLogChannel;
} // namespace rlog
using namespace rlog; static std::shared_ptr<NameIO> NewBlockNameIO(
using namespace rel; const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key) {
static RLogChannel *Info = DEF_CHANNEL("info/nameio", Log_Info);
static shared_ptr<NameIO> NewBlockNameIO(const Interface &iface,
const shared_ptr<Cipher> &cipher,
const CipherKey &key) {
int blockSize = 8; int blockSize = 8;
if (cipher) blockSize = cipher->cipherBlockSize(); if (cipher) blockSize = cipher->cipherBlockSize();
return shared_ptr<NameIO>( return std::shared_ptr<NameIO>(
new BlockNameIO(iface, cipher, key, blockSize, false)); new BlockNameIO(iface, cipher, key, blockSize, false));
} }
static shared_ptr<NameIO> NewBlockNameIO32(const Interface &iface, static std::shared_ptr<NameIO> NewBlockNameIO32(
const 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 shared_ptr<NameIO>( return std::shared_ptr<NameIO>(
new BlockNameIO(iface, cipher, key, blockSize, true)); new BlockNameIO(iface, cipher, key, blockSize, true));
} }
@ -99,9 +94,10 @@ Interface BlockNameIO::CurrentInterface(bool caseInsensitive) {
return Interface("nameio/block", 4, 0, 2); return Interface("nameio/block", 4, 0, 2);
} }
BlockNameIO::BlockNameIO(const rel::Interface &iface, BlockNameIO::BlockNameIO(const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key, const std::shared_ptr<Cipher> &cipher,
int blockSize, bool caseInsensitiveEncoding) const CipherKey &key, int blockSize,
bool caseInsensitiveEncoding)
: _interface(iface.current()), : _interface(iface.current()),
_bs(blockSize), _bs(blockSize),
_cipher(cipher), _cipher(cipher),
@ -191,8 +187,8 @@ int BlockNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
// don't bother trying to decode files which are too small // don't bother trying to decode files which are too small
if (decodedStreamLen < _bs) { if (decodedStreamLen < _bs) {
rDebug("Rejecting filename '%s'", encodedName); VLOG(1) << "Rejecting filename " << encodedName;
throw ERROR("Filename too small to decode"); throw Error("Filename too small to decode");
} }
BUFFER_INIT(tmpBuf, 32, (unsigned int)length); BUFFER_INIT(tmpBuf, 32, (unsigned int)length);
@ -222,8 +218,9 @@ int BlockNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
// might happen if there is an error decoding.. // might happen if there is an error decoding..
if (padding > _bs || finalSize < 0) { if (padding > _bs || finalSize < 0) {
rDebug("padding, _bx, finalSize = %i, %i, %i", padding, _bs, finalSize); VLOG(1) << "padding, _bx, finalSize = " << padding << ", " << _bs << ", "
throw ERROR("invalid padding size"); << finalSize;
throw Error("invalid padding size");
} }
// copy out the result.. // copy out the result..
@ -238,12 +235,14 @@ int BlockNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
BUFFER_RESET(tmpBuf); BUFFER_RESET(tmpBuf);
if (mac2 != mac) { if (mac2 != mac) {
rDebug("checksum mismatch: expected %u, got %u", mac, mac2); VLOG(1) << "checksum mismatch: expected " << mac << ", got " << mac2
rDebug("on decode of %i bytes", finalSize); << " on decode of " << finalSize << " bytes";
throw ERROR("checksum mismatch in filename decode"); throw Error("checksum mismatch in filename decode");
} }
return finalSize; return finalSize;
} }
bool BlockNameIO::Enabled() { return true; } bool BlockNameIO::Enabled() { return true; }
} // namespace encfs

View File

@ -21,13 +21,14 @@
#ifndef _BlockNameIO_incl_ #ifndef _BlockNameIO_incl_
#define _BlockNameIO_incl_ #define _BlockNameIO_incl_
#include <stdint.h>
#include <memory> #include <memory>
#include <stdint.h> // for uint64_t
#include "CipherKey.h" #include "CipherKey.h" // for CipherKey
#include "Interface.h" #include "Interface.h" // for Interface
#include "NameIO.h" #include "NameIO.h" // for NameIO
#include "shared_ptr.h"
namespace encfs {
class Cipher; class Cipher;
@ -38,14 +39,14 @@ class Cipher;
*/ */
class BlockNameIO : public NameIO { class BlockNameIO : public NameIO {
public: public:
static rel::Interface CurrentInterface(bool caseInsensitive = false); static Interface CurrentInterface(bool caseInsensitive = false);
BlockNameIO(const rel::Interface &iface, const shared_ptr<Cipher> &cipher, BlockNameIO(const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize, const CipherKey &key, int blockSize,
bool caseInsensitiveEncoding = false); bool caseInsensitiveEncoding = false);
virtual ~BlockNameIO(); virtual ~BlockNameIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual int maxEncodedNameLen(int plaintextNameLen) const; virtual int maxEncodedNameLen(int plaintextNameLen) const;
virtual int maxDecodedNameLen(int encodedNameLen) const; virtual int maxDecodedNameLen(int encodedNameLen) const;
@ -62,9 +63,11 @@ class BlockNameIO : public NameIO {
private: private:
int _interface; int _interface;
int _bs; int _bs;
shared_ptr<Cipher> _cipher; std::shared_ptr<Cipher> _cipher;
CipherKey _key; CipherKey _key;
bool _caseInsensitive; bool _caseInsensitive;
}; };
} // namespace encfs
#endif #endif

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 <stddef.h>
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <map> #include <map>
#include <stddef.h>
#include <string> #include <string>
#include <utility> #include <utility>
@ -36,7 +36,8 @@
#include "base64.h" #include "base64.h"
using namespace std; using namespace std;
using namespace rel;
namespace encfs {
#define REF_MODULE(TYPE) \ #define REF_MODULE(TYPE) \
if (!TYPE::Enabled()) cerr << "referenceModule: should never happen\n"; if (!TYPE::Enabled()) cerr << "referenceModule: should never happen\n";
@ -110,9 +111,8 @@ bool Cipher::Register(const char *name, const char *description,
gCipherMap->insert(make_pair(string(name), ca)); gCipherMap->insert(make_pair(string(name), ca));
return true; return true;
} }
std::shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) { std::shared_ptr<Cipher> result;
shared_ptr<Cipher> result;
if (gCipherMap) { if (gCipherMap) {
CipherMap_t::const_iterator it = gCipherMap->find(name); CipherMap_t::const_iterator it = gCipherMap->find(name);
@ -125,9 +125,8 @@ shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
return result; return result;
} }
std::shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) {
shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) { std::shared_ptr<Cipher> result;
shared_ptr<Cipher> result;
if (gCipherMap) { if (gCipherMap) {
CipherMap_t::const_iterator it; CipherMap_t::const_iterator it;
CipherMap_t::const_iterator mapEnd = gCipherMap->end(); CipherMap_t::const_iterator mapEnd = gCipherMap->end();
@ -199,3 +198,5 @@ string Cipher::encodeAsString(const CipherKey &key,
return string((const char *)b64Key); return string((const char *)b64Key);
} }
} // namespace encfs

View File

@ -22,9 +22,9 @@
#define _Cipher_incl_ #define _Cipher_incl_
#include <inttypes.h> #include <inttypes.h>
#include <stdint.h>
#include <list> #include <list>
#include <memory> #include <memory>
#include <stdint.h>
#include <string> #include <string>
#include "CipherKey.h" #include "CipherKey.h"
@ -32,6 +32,8 @@
#include "Range.h" #include "Range.h"
#include "encfs.h" #include "encfs.h"
namespace encfs {
/* /*
Mostly pure virtual interface defining operations on a cipher. Mostly pure virtual interface defining operations on a cipher.
@ -42,13 +44,13 @@ class Cipher {
public: public:
// if no key length was indicated when cipher was registered, then keyLen // if no key length was indicated when cipher was registered, then keyLen
// <= 0 will be used. // <= 0 will be used.
typedef shared_ptr<Cipher>(*CipherConstructor)(const rel::Interface &iface, typedef std::shared_ptr<Cipher> (*CipherConstructor)(const Interface &iface,
int keyLenBits); int keyLenBits);
struct CipherAlgorithm { struct CipherAlgorithm {
std::string name; std::string name;
std::string description; std::string description;
rel::Interface iface; Interface iface;
Range keyLength; Range keyLength;
Range blockSize; Range blockSize;
}; };
@ -56,21 +58,22 @@ class Cipher {
typedef std::list<CipherAlgorithm> AlgorithmList; typedef std::list<CipherAlgorithm> AlgorithmList;
static AlgorithmList GetAlgorithmList(bool includeHidden = false); static AlgorithmList GetAlgorithmList(bool includeHidden = false);
static shared_ptr<Cipher> New(const rel::Interface &iface, int keyLen = -1); static std::shared_ptr<Cipher> New(const Interface &iface, int keyLen = -1);
static shared_ptr<Cipher> New(const std::string &cipherName, int keyLen = -1); static std::shared_ptr<Cipher> New(const std::string &cipherName,
int keyLen = -1);
static bool Register(const char *cipherName, const char *description, static bool Register(const char *cipherName, const char *description,
const rel::Interface &iface, const Interface &iface, CipherConstructor constructor,
CipherConstructor constructor, bool hidden = false); bool hidden = false);
static bool Register(const char *cipherName, const char *description, static bool Register(const char *cipherName, const char *description,
const rel::Interface &iface, const Range &keyLength, const Interface &iface, const Range &keyLength,
const Range &blockSize, CipherConstructor constructor, const Range &blockSize, CipherConstructor constructor,
bool hidden = false); bool hidden = false);
Cipher(); Cipher();
virtual ~Cipher(); virtual ~Cipher();
virtual rel::Interface interface() const = 0; virtual Interface interface() const = 0;
// create a new key based on a password // create a new key based on a password
// if iterationCount == 0, then iteration count will be determined // if iterationCount == 0, then iteration count will be determined
@ -150,4 +153,6 @@ class Cipher {
const CipherKey &key) const = 0; const CipherKey &key) const = 0;
}; };
} // namespace encfs
#endif #endif

View File

@ -20,40 +20,34 @@
#include "CipherFileIO.h" #include "CipherFileIO.h"
#include "internal/easylogging++.h"
#include <cerrno>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h> #include <inttypes.h>
#include <memory>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <rlog/Error.h>
#include <rlog/rlog.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <cerrno>
#include "BlockFileIO.h" #include "BlockFileIO.h"
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "Error.h"
#include "FileIO.h" #include "FileIO.h"
namespace encfs {
/* /*
- Version 2:0 adds support for a per-file initialization vector with a - Version 2:0 adds support for a per-file initialization vector with a
fixed 8 byte header. The headers are enabled globally within a fixed 8 byte header. The headers are enabled globally within a
filesystem at the filesystem configuration level. filesystem at the filesystem configuration level.
When headers are disabled, 2:0 is compatible with version 1:0. When headers are disabled, 2:0 is compatible with version 1:0.
*/ */
static rel::Interface CipherFileIO_iface("FileIO/Cipher", 2, 0, 1); static Interface CipherFileIO_iface("FileIO/Cipher", 2, 0, 1);
const int HEADER_SIZE = 8; // 64 bit initialization vector.. const int HEADER_SIZE = 8; // 64 bit initialization vector..
static bool checkSize(int fsBlockSize, int cipherBlockSize) { CipherFileIO::CipherFileIO(const std::shared_ptr<FileIO> &_base,
int blockBoundary = fsBlockSize % cipherBlockSize;
if (blockBoundary != 0) {
rError("CipherFileIO: blocks should be multiple of cipher block size");
return true;
} else
return false;
}
CipherFileIO::CipherFileIO(const shared_ptr<FileIO> &_base,
const FSConfigPtr &cfg) const FSConfigPtr &cfg)
: BlockFileIO(cfg->config->blockSize, cfg), : BlockFileIO(cfg->config->blockSize, cfg),
base(_base), base(_base),
@ -65,16 +59,13 @@ CipherFileIO::CipherFileIO(const shared_ptr<FileIO> &_base,
cipher = cfg->cipher; cipher = cfg->cipher;
key = cfg->key; key = cfg->key;
static bool warnOnce = false; CHECK_EQ(fsConfig->config->blockSize % fsConfig->cipher->cipherBlockSize(), 0)
<< "FS block size must be multiple of cipher block size";
if (!warnOnce)
warnOnce = checkSize(fsConfig->config->blockSize,
fsConfig->cipher->cipherBlockSize());
} }
CipherFileIO::~CipherFileIO() {} CipherFileIO::~CipherFileIO() {}
rel::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);
@ -91,17 +82,16 @@ void CipherFileIO::setFileName(const char *fileName) {
const char *CipherFileIO::getFileName() const { return base->getFileName(); } const char *CipherFileIO::getFileName() const { return base->getFileName(); }
bool CipherFileIO::setIV(uint64_t iv) { bool CipherFileIO::setIV(uint64_t iv) {
rDebug("in setIV, current IV = %" PRIu64 ", new IV = %" PRIu64 VLOG(1) << "in setIV, current IV = " << externalIV << ", new IV = " << iv
", fileIV = %" PRIu64, << ", fileIV = " << fileIV;
externalIV, iv, fileIV);
if (externalIV == 0) { if (externalIV == 0) {
// we're just being told about which IV to use. since we haven't // we're just being told about which IV to use. since we haven't
// initialized the fileIV, there is no need to just yet.. // initialized the fileIV, there is no need to just yet..
externalIV = iv; externalIV = iv;
if (fileIV != 0) if (fileIV != 0) {
rWarning("fileIV initialized before externalIV! (%" PRIu64 ", %" PRIu64 RLOG(WARNING) << "fileIV initialized before externalIV: " << fileIV
")", << ", " << externalIV;
fileIV, externalIV); }
} else if (haveHeader) { } else if (haveHeader) {
// we have an old IV, and now a new IV, so we need to update the fileIV // we have an old IV, and now a new IV, so we need to update the fileIV
// on disk. // on disk.
@ -115,7 +105,7 @@ bool CipherFileIO::setIV(uint64_t iv) {
externalIV = iv; externalIV = iv;
return base->setIV(iv); return base->setIV(iv);
} else { } else {
rDebug("writeHeader failed to re-open for write"); VLOG(1) << "writeHeader failed to re-open for write";
return false; return false;
} }
} }
@ -185,7 +175,7 @@ void CipherFileIO::initHeader() {
// create one. // create one.
off_t rawSize = base->getSize(); off_t rawSize = base->getSize();
if (rawSize >= HEADER_SIZE) { if (rawSize >= HEADER_SIZE) {
rDebug("reading existing header, rawSize = %" PRIi64, rawSize); VLOG(1) << "reading existing header, rawSize = " << rawSize;
// has a header.. read it // has a header.. read it
unsigned char buf[8] = {0}; unsigned char buf[8] = {0};
@ -202,18 +192,18 @@ void CipherFileIO::initHeader() {
rAssert(fileIV != 0); // 0 is never used.. rAssert(fileIV != 0); // 0 is never used..
} else { } else {
rDebug("creating new file IV header"); VLOG(1) << "creating new file IV header";
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)
rWarning("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()) {
@ -225,10 +215,11 @@ void CipherFileIO::initHeader() {
req.dataLen = 8; req.dataLen = 8;
base->write(req); base->write(req);
} else } else {
rDebug("base not writable, IV not written.."); VLOG(1) << "base not writable, IV not written..";
}
} }
rDebug("initHeader finished, fileIV = %" PRIu64, fileIV); VLOG(1) << "initHeader finished, fileIV = " << fileIV;
} }
bool CipherFileIO::writeHeader() { bool CipherFileIO::writeHeader() {
@ -236,13 +227,15 @@ bool CipherFileIO::writeHeader() {
// 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) {
rDebug("writeHeader failed to re-open for write"); VLOG(1) << "writeHeader failed to re-open for write";
return false; return false;
} }
} }
if (fileIV == 0) rError("Internal error: fileIV == 0 in writeHeader!!!"); if (fileIV == 0) {
rDebug("writing fileIV %" PRIu64, fileIV); RLOG(ERROR) << "Internal error: fileIV == 0 in writeHeader!!!";
}
VLOG(1) << "writing fileIV " << fileIV;
unsigned char buf[8] = {0}; unsigned char buf[8] = {0};
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
@ -282,7 +275,7 @@ void CipherFileIO::generateReverseHeader(unsigned char *headerBuf) {
ino_t ino = stbuf.st_ino; ino_t ino = stbuf.st_ino;
rAssert(ino != 0); rAssert(ino != 0);
rDebug("generating reverse file IV header from ino=%lu", (unsigned long)ino); VLOG(1) << "generating reverse file IV header from ino=" << ino;
// Serialize the inode number into inoBuf // Serialize the inode number into inoBuf
unsigned char inoBuf[sizeof(ino_t)]; unsigned char inoBuf[sizeof(ino_t)];
@ -305,7 +298,7 @@ void CipherFileIO::generateReverseHeader(unsigned char *headerBuf) {
fileIV = (fileIV << 8) | (uint64_t)headerBuf[i]; fileIV = (fileIV << 8) | (uint64_t)headerBuf[i];
} }
rDebug("fileIV=%" PRIx64, fileIV); VLOG(1) << "fileIV=" << fileIV;
// Encrypt externally-visible header // Encrypt externally-visible header
cipher->streamEncode(headerBuf, HEADER_SIZE, externalIV, key); cipher->streamEncode(headerBuf, HEADER_SIZE, externalIV, key);
@ -335,19 +328,20 @@ ssize_t CipherFileIO::readOneBlock(const IORequest &req) const {
const_cast<CipherFileIO *>(this)->initHeader(); const_cast<CipherFileIO *>(this)->initHeader();
if (readSize != bs) { if (readSize != bs) {
rDebug("streamRead(data, %d, IV)", (int)readSize); VLOG(1) << "streamRead(data, " << readSize << ", IV)";
ok = streamRead(tmpReq.data, (int)readSize, blockNum ^ fileIV); ok = streamRead(tmpReq.data, (int)readSize, blockNum ^ fileIV);
} else { } else {
ok = blockRead(tmpReq.data, (int)readSize, blockNum ^ fileIV); ok = blockRead(tmpReq.data, (int)readSize, blockNum ^ fileIV);
} }
if (!ok) { if (!ok) {
rDebug("decodeBlock failed for block %" PRIi64 ", size %i", blockNum, VLOG(1) << "decodeBlock failed for block " << blockNum << ", size "
(int)readSize); << readSize;
readSize = -1; readSize = -1;
} }
} else } else {
rDebug("readSize zero for offset %" PRIi64, req.offset); VLOG(1) << "readSize zero for offset " << req.offset;
}
return readSize; return readSize;
} }
@ -355,7 +349,8 @@ ssize_t CipherFileIO::readOneBlock(const IORequest &req) const {
bool CipherFileIO::writeOneBlock(const IORequest &req) { bool CipherFileIO::writeOneBlock(const IORequest &req) {
if (haveHeader && fsConfig->reverseEncryption) { if (haveHeader && fsConfig->reverseEncryption) {
rDebug("writing to a reverse mount with per-file IVs is not implemented"); VLOG(1)
<< "writing to a reverse mount with per-file IVs is not implemented";
return false; return false;
} }
@ -379,8 +374,8 @@ bool CipherFileIO::writeOneBlock(const IORequest &req) {
} else } else
ok = base->write(req); ok = base->write(req);
} else { } else {
rDebug("encodeBlock failed for block %" PRIi64 ", size %i", blockNum, VLOG(1) << "encodeBlock failed for block " << blockNum << ", size "
req.dataLen); << req.dataLen;
ok = false; ok = false;
} }
return ok; return ok;
@ -388,7 +383,7 @@ 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 {
rDebug("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 else
@ -397,7 +392,7 @@ bool CipherFileIO::blockWrite(unsigned char *buf, int size,
bool CipherFileIO::streamWrite(unsigned char *buf, int size, bool CipherFileIO::streamWrite(unsigned char *buf, int size,
uint64_t _iv64) const { uint64_t _iv64) const {
rDebug("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 else
@ -439,7 +434,7 @@ int CipherFileIO::truncate(off_t size) {
// 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)
rDebug("writeHeader failed to re-open for write"); VLOG(1) << "writeHeader failed to re-open for write";
} }
initHeader(); initHeader();
} }
@ -461,13 +456,13 @@ ssize_t CipherFileIO::read(const IORequest &origReq) const {
/* if reverse mode is not active with uniqueIV, /* if reverse mode is not active with uniqueIV,
* the read request is handled by the base class */ * the read request is handled by the base class */
if (!(fsConfig->reverseEncryption && haveHeader)) { if (!(fsConfig->reverseEncryption && haveHeader)) {
rDebug("relaying request to base class: offset=%d, dataLen=%d", VLOG(1) << "relaying request to base class: offset=" << origReq.offset
origReq.offset, origReq.dataLen); << ", dataLen=" << origReq.dataLen;
return BlockFileIO::read(origReq); return BlockFileIO::read(origReq);
} }
rDebug("handling reverse unique IV read: offset=%d, dataLen=%d", VLOG(1) << "handling reverse unique IV read: offset=" << origReq.offset
origReq.offset, origReq.dataLen); << ", dataLen=" << origReq.dataLen;
// generate the file IV header // generate the file IV header
// this is needed in any case - without IV the file cannot be decoded // this is needed in any case - without IV the file cannot be decoded
@ -489,7 +484,7 @@ ssize_t CipherFileIO::read(const IORequest &origReq) const {
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
rDebug("Adding %d header bytes", headerBytes); VLOG(1) << "Adding " << headerBytes << " header bytes";
// copy the header bytes into the data // copy the header bytes into the data
int headerOffset = HEADER_SIZE - headerBytes; int headerOffset = HEADER_SIZE - headerBytes;
@ -509,14 +504,16 @@ 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);
rDebug("read %ld bytes from backing file", (long)readBytes); 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 { else {
ssize_t sum = headerBytes + readBytes; ssize_t sum = headerBytes + readBytes;
rDebug("returning sum=%ld", (long)sum); VLOG(1) << "returning sum=" << sum;
return sum; return sum;
} }
} }
bool CipherFileIO::isWritable() const { return base->isWritable(); } bool CipherFileIO::isWritable() const { return base->isWritable(); }
} // namespace encfs

View File

@ -22,9 +22,9 @@
#define _CipherFileIO_incl_ #define _CipherFileIO_incl_
#include <inttypes.h> #include <inttypes.h>
#include <memory>
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <memory>
#include "BlockFileIO.h" #include "BlockFileIO.h"
#include "CipherKey.h" #include "CipherKey.h"
@ -32,6 +32,8 @@
#include "FileUtils.h" #include "FileUtils.h"
#include "Interface.h" #include "Interface.h"
namespace encfs {
class Cipher; class Cipher;
class FileIO; class FileIO;
struct IORequest; struct IORequest;
@ -43,10 +45,10 @@ struct IORequest;
*/ */
class CipherFileIO : public BlockFileIO { class CipherFileIO : public BlockFileIO {
public: public:
CipherFileIO(const shared_ptr<FileIO> &base, const FSConfigPtr &cfg); CipherFileIO(const std::shared_ptr<FileIO> &base, const FSConfigPtr &cfg);
virtual ~CipherFileIO(); virtual ~CipherFileIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual void setFileName(const char *fileName); virtual void setFileName(const char *fileName);
virtual const char *getFileName() const; virtual const char *getFileName() const;
@ -75,7 +77,7 @@ class CipherFileIO : public BlockFileIO {
ssize_t read(const IORequest &req) const; ssize_t read(const IORequest &req) const;
shared_ptr<FileIO> base; std::shared_ptr<FileIO> base;
FSConfigPtr fsConfig; FSConfigPtr fsConfig;
@ -86,8 +88,10 @@ class CipherFileIO : public BlockFileIO {
uint64_t fileIV; uint64_t fileIV;
int lastFlags; int lastFlags;
shared_ptr<Cipher> cipher; std::shared_ptr<Cipher> cipher;
CipherKey key; CipherKey key;
}; };
} // namespace encfs
#endif #endif

View File

@ -20,6 +20,10 @@
#include "CipherKey.h" #include "CipherKey.h"
namespace encfs {
AbstractCipherKey::AbstractCipherKey() {} AbstractCipherKey::AbstractCipherKey() {}
AbstractCipherKey::~AbstractCipherKey() {} AbstractCipherKey::~AbstractCipherKey() {}
} // namespace encfs

View File

@ -23,7 +23,7 @@
#include <memory> #include <memory>
#include "shared_ptr.h" namespace encfs {
class AbstractCipherKey { class AbstractCipherKey {
public: public:
@ -31,6 +31,8 @@ class AbstractCipherKey {
virtual ~AbstractCipherKey(); virtual ~AbstractCipherKey();
}; };
typedef shared_ptr<AbstractCipherKey> CipherKey; typedef std::shared_ptr<AbstractCipherKey> CipherKey;
} // namespace encfs
#endif #endif

View File

@ -20,17 +20,18 @@
#include "ConfigReader.h" #include "ConfigReader.h"
#include <cstring>
#include <fcntl.h> #include <fcntl.h>
#include <rlog/rlog.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <cstring>
#include <utility> #include <utility>
#include "ConfigVar.h" #include "ConfigVar.h"
#include "Error.h"
using namespace std; using namespace std;
using namespace rlog;
namespace encfs {
ConfigReader::ConfigReader() {} ConfigReader::ConfigReader() {}
@ -54,8 +55,8 @@ bool ConfigReader::load(const char *fileName) {
close(fd); close(fd);
if (res != size) { if (res != size) {
rWarning("Partial read of config file, expecting %i bytes, got %i", size, RLOG(WARNING) << "Partial read of config file, expecting " << size
res); << " bytes, got " << res;
delete[] buf; delete[] buf;
return false; return false;
} }
@ -78,7 +79,7 @@ bool ConfigReader::loadFromVar(ConfigVar &in) {
in >> key >> value; in >> key >> value;
if (key.length() == 0) { if (key.length() == 0) {
rError("Invalid key encoding in buffer"); RLOG(ERROR) << "Invalid key encoding in buffer";
return false; return false;
} }
ConfigVar newVar(value); ConfigVar newVar(value);
@ -97,11 +98,11 @@ bool ConfigReader::save(const char *fileName) const {
int retVal = ::write(fd, out.buffer(), out.size()); int retVal = ::write(fd, out.buffer(), out.size());
close(fd); close(fd);
if (retVal != out.size()) { if (retVal != out.size()) {
rError("Error writing to config file %s", fileName); RLOG(ERROR) << "Error writing to config file " << fileName;
return false; return false;
} }
} else { } else {
rError("Unable to open or create file %s", fileName); RLOG(ERROR) << "Unable to open or create file " << fileName;
return false; return false;
} }
@ -135,3 +136,5 @@ ConfigVar ConfigReader::operator[](const std::string &varName) const {
ConfigVar &ConfigReader::operator[](const std::string &varName) { ConfigVar &ConfigReader::operator[](const std::string &varName) {
return vars[varName]; return vars[varName];
} }
} // namespace encfs

View File

@ -21,11 +21,13 @@
#ifndef _ConfigReader_incl_ #ifndef _ConfigReader_incl_
#define _ConfigReader_incl_ #define _ConfigReader_incl_
#include <string>
#include <map> #include <map>
#include <string>
#include "ConfigVar.h" #include "ConfigVar.h"
namespace encfs {
/* /*
handles Configuration load / store for Encfs filesystems. handles Configuration load / store for Encfs filesystems.
@ -61,4 +63,6 @@ class ConfigReader {
std::map<std::string, ConfigVar> vars; std::map<std::string, ConfigVar> vars;
}; };
} // namespace encfs
#endif #endif

View File

@ -20,10 +20,12 @@
#include "ConfigVar.h" #include "ConfigVar.h"
#include <rlog/rlog.h> #include "internal/easylogging++.h"
#include <cstring> #include <cstring>
using namespace rlog; #include "Error.h"
namespace encfs {
#ifndef MIN #ifndef MIN
inline int MIN(int a, int b) { return (a < b) ? a : b; } inline int MIN(int a, int b) { return (a < b) ? a : b; }
@ -192,9 +194,12 @@ const ConfigVar &operator>>(const ConfigVar &src, std::string &result) {
} }
if (readLen != length) { if (readLen != length) {
rDebug("string encoded as size %i bytes, read %i", length, readLen); VLOG(1) << "string encoded as size " << length << " bytes, read "
<< readLen;
} }
rAssert(readLen == length); rAssert(readLen == length);
return src; return src;
} }
} // namespace encfs

View File

@ -24,7 +24,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "shared_ptr.h" namespace encfs {
class ConfigVar { class ConfigVar {
struct ConfigVarData { struct ConfigVarData {
@ -32,7 +32,7 @@ class ConfigVar {
int offset; int offset;
}; };
shared_ptr<ConfigVarData> pd; std::shared_ptr<ConfigVarData> pd;
public: public:
ConfigVar(); ConfigVar();
@ -77,4 +77,6 @@ const ConfigVar &operator>>(const ConfigVar &, bool &);
const ConfigVar &operator>>(const ConfigVar &, int &); const ConfigVar &operator>>(const ConfigVar &, int &);
const ConfigVar &operator>>(const ConfigVar &, std::string &str); const ConfigVar &operator>>(const ConfigVar &, std::string &str);
} // namespace encfs
#endif #endif

View File

@ -18,15 +18,15 @@
* 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 <rlog/rlog.h> #include "internal/easylogging++.h"
#include <utility> #include <utility>
#include "Context.h" #include "Context.h"
#include "DirNode.h" #include "DirNode.h"
#include "Error.h"
#include "Mutex.h" #include "Mutex.h"
using namespace rel; namespace encfs {
using namespace rlog;
EncFS_Context::EncFS_Context() { EncFS_Context::EncFS_Context() {
pthread_cond_init(&wakeupCond, 0); pthread_cond_init(&wakeupCond, 0);
@ -44,9 +44,8 @@ EncFS_Context::~EncFS_Context() {
// release all entries from map // release all entries from map
openFiles.clear(); openFiles.clear();
} }
std::shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode) {
shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode) { std::shared_ptr<DirNode> ret;
shared_ptr<DirNode> ret;
do { do {
{ {
Lock lock(contextMutex); Lock lock(contextMutex);
@ -66,7 +65,7 @@ shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode) {
return ret; return ret;
} }
void EncFS_Context::setRoot(const shared_ptr<DirNode> &r) { void EncFS_Context::setRoot(const std::shared_ptr<DirNode> &r) {
Lock lock(contextMutex); Lock lock(contextMutex);
root = r; root = r;
@ -89,8 +88,7 @@ int EncFS_Context::openFileCount() const {
return openFiles.size(); return openFiles.size();
} }
std::shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
Lock lock(contextMutex); Lock lock(contextMutex);
FileMap::iterator it = openFiles.find(std::string(path)); FileMap::iterator it = openFiles.find(std::string(path));
@ -99,7 +97,7 @@ shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
// first // first
return (*it->second.begin())->node; return (*it->second.begin())->node;
} else { } else {
return shared_ptr<FileNode>(); return std::shared_ptr<FileNode>();
} }
} }
@ -113,14 +111,13 @@ void EncFS_Context::renameNode(const char *from, const char *to) {
openFiles[std::string(to)] = val; openFiles[std::string(to)] = val;
} }
} }
std::shared_ptr<FileNode> EncFS_Context::getNode(void *pl) {
shared_ptr<FileNode> EncFS_Context::getNode(void *pl) {
Placeholder *ph = (Placeholder *)pl; Placeholder *ph = (Placeholder *)pl;
return ph->node; return ph->node;
} }
void *EncFS_Context::putNode(const char *path, void *EncFS_Context::putNode(const char *path,
const shared_ptr<FileNode> &node) { const std::shared_ptr<FileNode> &node) {
Lock lock(contextMutex); Lock lock(contextMutex);
Placeholder *pl = new Placeholder(node); Placeholder *pl = new Placeholder(node);
openFiles[std::string(path)].insert(pl); openFiles[std::string(path)].insert(pl);
@ -151,3 +148,5 @@ void EncFS_Context::eraseNode(const char *path, void *pl) {
delete ph; delete ph;
} }
} // namespace encfs

View File

@ -21,15 +21,16 @@
#ifndef _Context_incl_ #ifndef _Context_incl_
#define _Context_incl_ #define _Context_incl_
#include <pthread.h>
#include <memory> #include <memory>
#include <pthread.h>
#include <set> #include <set>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "encfs.h" #include "encfs.h"
#include "shared_ptr.h"
namespace encfs {
class DirNode; class DirNode;
class FileNode; class FileNode;
@ -41,24 +42,24 @@ class EncFS_Context {
EncFS_Context(); EncFS_Context();
~EncFS_Context(); ~EncFS_Context();
shared_ptr<FileNode> getNode(void *ptr); std::shared_ptr<FileNode> getNode(void *ptr);
shared_ptr<FileNode> lookupNode(const char *path); std::shared_ptr<FileNode> lookupNode(const char *path);
int getAndResetUsageCounter(); int getAndResetUsageCounter();
int openFileCount() const; int openFileCount() const;
void *putNode(const char *path, const shared_ptr<FileNode> &node); void *putNode(const char *path, const std::shared_ptr<FileNode> &node);
void eraseNode(const char *path, void *placeholder); void eraseNode(const char *path, void *placeholder);
void renameNode(const char *oldName, const char *newName); void renameNode(const char *oldName, const char *newName);
void setRoot(const shared_ptr<DirNode> &root); void setRoot(const std::shared_ptr<DirNode> &root);
shared_ptr<DirNode> getRoot(int *err); std::shared_ptr<DirNode> getRoot(int *err);
bool isMounted(); bool isMounted();
shared_ptr<EncFS_Args> args; std::shared_ptr<EncFS_Args> args;
shared_ptr<EncFS_Opts> opts; std::shared_ptr<EncFS_Opts> opts;
bool publicFilesystem; bool publicFilesystem;
// root path to cipher dir // root path to cipher dir
@ -77,13 +78,13 @@ class EncFS_Context {
* A FileNode may be opened many times, but only one FileNode instance per * A FileNode may be opened many times, but only one FileNode instance per
* file is kept. Rather then doing reference counting in FileNode, we * file is kept. Rather then doing reference counting in FileNode, we
* store a unique Placeholder for each open() until the corresponding * store a unique Placeholder for each open() until the corresponding
* release() is called. shared_ptr then does our reference counting for * release() is called. std::shared_ptr then does our reference counting for
* us. * us.
*/ */
struct Placeholder { struct Placeholder {
shared_ptr<FileNode> node; std::shared_ptr<FileNode> node;
Placeholder(const shared_ptr<FileNode> &ptr) : node(ptr) {} Placeholder(const std::shared_ptr<FileNode> &ptr) : node(ptr) {}
}; };
typedef std::unordered_map<std::string, std::set<Placeholder *> > FileMap; typedef std::unordered_map<std::string, std::set<Placeholder *> > FileMap;
@ -92,9 +93,11 @@ class EncFS_Context {
FileMap openFiles; FileMap openFiles;
int usageCount; int usageCount;
shared_ptr<DirNode> root; std::shared_ptr<DirNode> root;
}; };
int remountFS(EncFS_Context *ctx); int remountFS(EncFS_Context *ctx);
} // namespace encfs
#endif #endif

View File

@ -18,13 +18,13 @@
* 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 <cerrno>
#include <cstdio>
#include <pthread.h> #include <pthread.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <utime.h> #include <utime.h>
#include <cerrno>
#include <cstdio>
#include "DirNode.h" #include "DirNode.h"
#include "FSConfig.h" #include "FSConfig.h"
@ -35,30 +35,24 @@
#include <sys/fsuid.h> #include <sys/fsuid.h>
#endif #endif
#include <rlog/Error.h> #include "internal/easylogging++.h"
#include <rlog/rlog.h>
#include <cstring> #include <cstring>
#include "Context.h" #include "Context.h"
#include "Error.h"
#include "Mutex.h" #include "Mutex.h"
namespace rlog {
class RLogChannel;
} // namespace rlog
using namespace std; using namespace std;
using namespace rel;
using namespace rlog;
static RLogChannel *Info = DEF_CHANNEL("info/DirNode", Log_Info); namespace encfs {
class DirDeleter { class DirDeleter {
public: public:
void operator()(DIR *d) { ::closedir(d); } void operator()(DIR *d) { ::closedir(d); }
}; };
DirTraverse::DirTraverse(const shared_ptr<DIR> &_dirPtr, uint64_t _iv, DirTraverse::DirTraverse(const std::shared_ptr<DIR> &_dirPtr, uint64_t _iv,
const shared_ptr<NameIO> &_naming) const std::shared_ptr<NameIO> &_naming)
: dir(_dirPtr), iv(_iv), naming(_naming) {} : dir(_dirPtr), iv(_iv), naming(_naming) {}
DirTraverse::DirTraverse(const DirTraverse &src) DirTraverse::DirTraverse(const DirTraverse &src)
@ -78,7 +72,7 @@ DirTraverse::~DirTraverse() {
naming.reset(); naming.reset();
} }
static bool _nextName(struct dirent *&de, const shared_ptr<DIR> &dir, 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());
@ -105,9 +99,9 @@ std::string DirTraverse::nextPlaintextName(int *fileType, ino_t *inode) {
try { try {
uint64_t localIv = iv; uint64_t localIv = iv;
return naming->decodePath(de->d_name, &localIv); return naming->decodePath(de->d_name, &localIv);
} catch (rlog::Error &ex) { } catch (encfs::Error &ex) {
// .. .problem decoding, ignore it and continue on to next name.. // .. .problem decoding, ignore it and continue on to next name..
rDebug("error decoding filename: %s", de->d_name); VLOG(1) << "error decoding filename: " << de->d_name;
} }
} }
@ -122,7 +116,7 @@ std::string DirTraverse::nextInvalid() {
uint64_t localIv = iv; uint64_t localIv = iv;
naming->decodePath(de->d_name, &localIv); naming->decodePath(de->d_name, &localIv);
continue; continue;
} catch (rlog::Error &ex) { } catch (encfs::Error &ex) {
return string(de->d_name); return string(de->d_name);
} }
} }
@ -145,11 +139,11 @@ struct RenameEl {
class RenameOp { class RenameOp {
private: private:
DirNode *dn; DirNode *dn;
shared_ptr<list<RenameEl> > renameList; std::shared_ptr<list<RenameEl> > renameList;
list<RenameEl>::const_iterator last; list<RenameEl>::const_iterator last;
public: public:
RenameOp(DirNode *_dn, const shared_ptr<list<RenameEl> > &_renameList) RenameOp(DirNode *_dn, const std::shared_ptr<list<RenameEl> > &_renameList)
: dn(_dn), renameList(_renameList) { : dn(_dn), renameList(_renameList) {
last = renameList->begin(); last = renameList->begin();
} }
@ -181,8 +175,7 @@ bool RenameOp::apply() {
try { try {
while (last != renameList->end()) { while (last != renameList->end()) {
// backing store rename. // backing store rename.
rDebug("renaming %s -> %s", last->oldCName.c_str(), VLOG(1) << "renaming " << last->oldCName << " -> " << last->newCName;
last->newCName.c_str());
struct stat st; struct stat st;
bool preserve_mtime = ::stat(last->oldCName.c_str(), &st) == 0; bool preserve_mtime = ::stat(last->oldCName.c_str(), &st) == 0;
@ -192,8 +185,8 @@ bool RenameOp::apply() {
// rename on disk.. // rename on disk..
if (::rename(last->oldCName.c_str(), last->newCName.c_str()) == -1) { if (::rename(last->oldCName.c_str(), last->newCName.c_str()) == -1) {
rWarning("Error renaming %s: %s", last->oldCName.c_str(), RLOG(WARNING) << "Error renaming " << last->oldCName << ": "
strerror(errno)); << strerror(errno);
dn->renameNode(last->newPName.c_str(), last->oldPName.c_str(), false); dn->renameNode(last->newPName.c_str(), last->oldPName.c_str(), false);
return false; return false;
} }
@ -209,17 +202,17 @@ bool RenameOp::apply() {
} }
return true; return true;
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
err.log(_RLWarningChannel); RLOG(WARNING) << err.what();
return false; return false;
} }
} }
void RenameOp::undo() { void RenameOp::undo() {
rDebug("in undoRename"); VLOG(1) << "in undoRename";
if (last == renameList->begin()) { if (last == renameList->begin()) {
rDebug("nothing to undo"); VLOG(1) << "nothing to undo";
return; // nothing to undo return; // nothing to undo
} }
@ -231,20 +224,19 @@ void RenameOp::undo() {
while (it != renameList->begin()) { while (it != renameList->begin()) {
--it; --it;
rDebug("undo: renaming %s -> %s", it->newCName.c_str(), VLOG(1) << "undo: renaming " << it->newCName << " -> " << it->oldCName;
it->oldCName.c_str());
::rename(it->newCName.c_str(), it->oldCName.c_str()); ::rename(it->newCName.c_str(), it->oldCName.c_str());
try { try {
dn->renameNode(it->newPName.c_str(), it->oldPName.c_str(), false); dn->renameNode(it->newPName.c_str(), it->oldPName.c_str(), false);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
err.log(_RLWarningChannel); RLOG(WARNING) << err.what();
// continue on anyway... // continue on anyway...
} }
++undoCount; ++undoCount;
}; };
rWarning("Undo rename count: %i", undoCount); RLOG(WARNING) << "Undo rename count: " << undoCount;
} }
DirNode::DirNode(EncFS_Context *_ctx, const string &sourceDir, DirNode::DirNode(EncFS_Context *_ctx, const string &sourceDir,
@ -254,7 +246,7 @@ DirNode::DirNode(EncFS_Context *_ctx, const string &sourceDir,
Lock _lock(mutex); Lock _lock(mutex);
ctx = _ctx; ctx = _ctx;
rootDir = sourceDir; // .. and fsConfig->opts->mountPoint have trailing slash rootDir = sourceDir; // .. and fsConfig->opts->mountPoint have trailing slash
fsConfig = _config; fsConfig = _config;
naming = fsConfig->nameCoding; naming = fsConfig->nameCoding;
@ -273,7 +265,7 @@ string DirNode::rootDirectory() {
return string(rootDir, 0, rootDir.length() - 1); return string(rootDir, 0, rootDir.length() - 1);
} }
bool DirNode::touchesMountpoint( const char *realPath ) const { bool DirNode::touchesMountpoint(const char *realPath) const {
const string &mountPoint = fsConfig->opts->mountPoint; const string &mountPoint = fsConfig->opts->mountPoint;
// compare mountPoint up to the leading slash. // compare mountPoint up to the leading slash.
// examples: // examples:
@ -336,10 +328,8 @@ string DirNode::plainPath(const char *cipherPath_) {
// Default. // Default.
return naming->decodePath(cipherPath_); return naming->decodePath(cipherPath_);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("decode err: %s", err.message()); RLOG(ERROR) << "decode err: " << err.what();
err.log(_RLWarningChannel);
return string(); return string();
} }
} }
@ -354,33 +344,29 @@ string DirNode::relativeCipherPath(const char *plaintextPath) {
} }
return naming->encodePath(plaintextPath); return naming->encodePath(plaintextPath);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("encode err: %s", err.message()); RLOG(ERROR) << "encode err: " << err.what();
err.log(_RLWarningChannel);
return string(); return string();
} }
} }
DirTraverse DirNode::openDir(const char *plaintextPath) { DirTraverse DirNode::openDir(const char *plaintextPath) {
string cyName = rootDir + naming->encodePath(plaintextPath); string cyName = rootDir + naming->encodePath(plaintextPath);
// rDebug("openDir on %s", cyName.c_str() );
DIR *dir = ::opendir(cyName.c_str()); DIR *dir = ::opendir(cyName.c_str());
if (dir == NULL) { if (dir == NULL) {
rDebug("opendir error %s", strerror(errno)); VLOG(1) << "opendir error " << strerror(errno);
return DirTraverse(shared_ptr<DIR>(), 0, shared_ptr<NameIO>()); return DirTraverse(shared_ptr<DIR>(), 0, std::shared_ptr<NameIO>());
} else { } else {
shared_ptr<DIR> dp(dir, DirDeleter()); std::shared_ptr<DIR> dp(dir, DirDeleter());
uint64_t iv = 0; uint64_t iv = 0;
// if we're using chained IV mode, then compute the IV at this // if we're using chained IV mode, then compute the IV at this
// directory level.. // directory level..
try { try {
if (naming->getChainedNameIV()) naming->encodePath(plaintextPath, &iv); if (naming->getChainedNameIV()) naming->encodePath(plaintextPath, &iv);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("encode err: %s", err.message()); RLOG(ERROR) << "encode err: " << err.what();
err.log(_RLWarningChannel);
} }
return DirTraverse(dp, iv, naming); return DirTraverse(dp, iv, naming);
} }
@ -401,9 +387,9 @@ bool DirNode::genRenameList(list<RenameEl> &renameList, const char *fromP,
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..
rDebug("opendir %s", sourcePath.c_str()); VLOG(1) << "opendir " << sourcePath;
shared_ptr<DIR> dir = std::shared_ptr<DIR> dir =
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 = NULL;
@ -421,7 +407,7 @@ bool DirNode::genRenameList(list<RenameEl> &renameList, const char *fromP,
try { try {
plainName = naming->decodePath(de->d_name, &localIV); plainName = naming->decodePath(de->d_name, &localIV);
} catch (rlog::Error &ex) { } catch (encfs::Error &ex) {
// if filename can't be decoded, then ignore it.. // if filename can't be decoded, then ignore it..
continue; continue;
} }
@ -463,15 +449,15 @@ bool DirNode::genRenameList(list<RenameEl> &renameList, const char *fromP,
} }
} }
rDebug("adding file %s to rename list", oldFull.c_str()); VLOG(1) << "adding file " << oldFull << " to rename list";
renameList.push_back(ren); renameList.push_back(ren);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
// We can't convert this name, because we don't have a valid IV for // We can't convert this name, because we don't have a valid IV for
// it (or perhaps a valid key).. It will be inaccessible.. // it (or perhaps a valid key).. It will be inaccessible..
rWarning("Aborting rename: error on file: %s", RLOG(WARNING) << "Aborting rename: error on file: "
fromCPart.append(1, '/').append(de->d_name).c_str()); << fromCPart.append(1, '/').append(de->d_name);
err.log(_RLDebugChannel); RLOG(WARNING) << err.what();
// abort.. Err on the side of safety and disallow rename, rather // abort.. Err on the side of safety and disallow rename, rather
// then loosing files.. // then loosing files..
@ -489,16 +475,16 @@ 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,
shared_ptr<RenameOp> DirNode::newRenameOp(const char *fromP, const char *toP) { 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!
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)) {
rWarning("Error during generation of recursive rename list"); RLOG(WARNING) << "Error during generation of recursive rename list";
return shared_ptr<RenameOp>(); return std::shared_ptr<RenameOp>();
} else } else
return shared_ptr<RenameOp>(new RenameOp(this, renameList)); return std::shared_ptr<RenameOp>(new 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,
@ -506,7 +492,7 @@ int DirNode::mkdir(const char *plaintextPath, mode_t mode, uid_t uid,
string cyName = rootDir + naming->encodePath(plaintextPath); string cyName = rootDir + naming->encodePath(plaintextPath);
rAssert(!cyName.empty()); rAssert(!cyName.empty());
rLog(Info, "mkdir on %s", cyName.c_str()); VLOG(1) << "mkdir on " << cyName;
// 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;
@ -521,8 +507,8 @@ int DirNode::mkdir(const char *plaintextPath, mode_t mode, uid_t uid,
if (res == -1) { if (res == -1) {
int eno = errno; int eno = errno;
rWarning("mkdir error on %s mode %i: %s", cyName.c_str(), mode, RLOG(WARNING) << "mkdir error on " << cyName << " mode " << mode << ": "
strerror(eno)); << strerror(eno);
res = -eno; res = -eno;
} else } else
res = 0; res = 0;
@ -538,22 +524,22 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
rAssert(!fromCName.empty()); rAssert(!fromCName.empty());
rAssert(!toCName.empty()); rAssert(!toCName.empty());
rLog(Info, "rename %s -> %s", fromCName.c_str(), toCName.c_str()); VLOG(1) << "rename " << fromCName << " -> " << toCName;
shared_ptr<FileNode> toNode = findOrCreate(toPlaintext); std::shared_ptr<FileNode> toNode = findOrCreate(toPlaintext);
shared_ptr<RenameOp> renameOp; std::shared_ptr<RenameOp> renameOp;
if (hasDirectoryNameDependency() && isDirectory(fromCName.c_str())) { if (hasDirectoryNameDependency() && isDirectory(fromCName.c_str())) {
rLog(Info, "recursive rename begin"); VLOG(1) << "recursive rename begin";
renameOp = newRenameOp(fromPlaintext, toPlaintext); renameOp = newRenameOp(fromPlaintext, toPlaintext);
if (!renameOp || !renameOp->apply()) { if (!renameOp || !renameOp->apply()) {
if (renameOp) renameOp->undo(); if (renameOp) renameOp->undo();
rWarning("rename aborted"); RLOG(WARNING) << "rename aborted";
return -EACCES; return -EACCES;
} }
rLog(Info, "recursive rename end"); VLOG(1) << "recursive rename end";
} }
int res = 0; int res = 0;
@ -576,14 +562,14 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
ut.modtime = st.st_mtime; ut.modtime = st.st_mtime;
::utime(toCName.c_str(), &ut); ::utime(toCName.c_str(), &ut);
} }
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
// exception from renameNode, just show the error and continue.. // exception from renameNode, just show the error and continue..
err.log(_RLWarningChannel); RLOG(WARNING) << err.what();
res = -EIO; res = -EIO;
} }
if (res != 0) { if (res != 0) {
rLog(Info, "rename failed: %s", strerror(errno)); VLOG(1) << "rename failed: " << strerror(errno);
res = -errno; res = -errno;
} }
@ -599,11 +585,11 @@ int DirNode::link(const char *from, const char *to) {
rAssert(!fromCName.empty()); rAssert(!fromCName.empty());
rAssert(!toCName.empty()); rAssert(!toCName.empty());
rLog(Info, "link %s -> %s", fromCName.c_str(), toCName.c_str()); VLOG(1) << "link " << fromCName << " -> " << toCName;
int res = -EPERM; int res = -EPERM;
if (fsConfig->config->externalIVChaining) { if (fsConfig->config->externalIVChaining) {
rLog(Info, "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)
@ -618,36 +604,34 @@ 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,
shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to) { 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,
shared_ptr<FileNode> DirNode::renameNode(const char *from, const char *to, bool forwardMode) {
bool forwardMode) { std::shared_ptr<FileNode> node = findOrCreate(from);
shared_ptr<FileNode> node = findOrCreate(from);
if (node) { if (node) {
uint64_t newIV = 0; uint64_t newIV = 0;
string cname = rootDir + naming->encodePath(to, &newIV); string cname = rootDir + naming->encodePath(to, &newIV);
rLog(Info, "renaming internal node %s -> %s", node->cipherName(), VLOG(1) << "renaming internal node " << node->cipherName() << " -> "
cname.c_str()); << 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) ctx->renameNode(from, to);
} else { } else {
// rename error! - put it back // rename error! - put it back
rError("renameNode failed"); RLOG(ERROR) << "renameNode failed";
throw ERROR("Internal node name change failed!"); throw Error("Internal node name change failed!");
} }
} }
return node; return node;
} }
std::shared_ptr<FileNode> DirNode::findOrCreate(const char *plainName) {
shared_ptr<FileNode> DirNode::findOrCreate(const char *plainName) { std::shared_ptr<FileNode> node;
shared_ptr<FileNode> node;
if (ctx) node = ctx->lookupNode(plainName); if (ctx) node = ctx->lookupNode(plainName);
if (!node) { if (!node) {
@ -658,18 +642,17 @@ shared_ptr<FileNode> DirNode::findOrCreate(const char *plainName) {
if (fsConfig->config->externalIVChaining) node->setName(0, 0, iv); if (fsConfig->config->externalIVChaining) node->setName(0, 0, iv);
rLog(Info, "created FileNode for %s", node->cipherName()); VLOG(1) << "created FileNode for " << node->cipherName();
} }
return node; return node;
} }
std::shared_ptr<FileNode> DirNode::lookupNode(const char *plainName,
shared_ptr<FileNode> DirNode::lookupNode(const char *plainName, const char *requestor) {
const char *requestor) {
(void)requestor; (void)requestor;
Lock _lock(mutex); Lock _lock(mutex);
shared_ptr<FileNode> node = findOrCreate(plainName); std::shared_ptr<FileNode> node = findOrCreate(plainName);
return node; return node;
} }
@ -678,25 +661,24 @@ shared_ptr<FileNode> DirNode::lookupNode(const char *plainName,
Similar to lookupNode, except that we also call open() and only return a Similar to lookupNode, except that we also call open() and only return a
node on sucess.. This is done in one step to avoid any race conditions node on sucess.. This is done in one step to avoid any race conditions
with the stored state of the file. with the stored state of the file.
*/ */ std::shared_ptr<FileNode> DirNode::openNode(const char *plainName,
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 != NULL);
Lock _lock(mutex); Lock _lock(mutex);
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 else
return shared_ptr<FileNode>(); return std::shared_ptr<FileNode>();
} }
int DirNode::unlink(const char *plaintextName) { int DirNode::unlink(const char *plaintextName) {
string cyName = naming->encodePath(plaintextName); string cyName = naming->encodePath(plaintextName);
rLog(Info, "unlink %s", cyName.c_str()); VLOG(1) << "unlink " << cyName;
Lock _lock(mutex); Lock _lock(mutex);
@ -705,19 +687,20 @@ int DirNode::unlink(const char *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..
rWarning( RLOG(WARNING) << "Refusing to unlink open file: " << cyName
"Refusing to unlink open file: %s, hard_remove option " << ", hard_remove option "
"is probably in effect", "is probably in effect";
cyName.c_str());
res = -EBUSY; res = -EBUSY;
} else { } else {
string fullName = rootDir + cyName; string fullName = rootDir + cyName;
res = ::unlink(fullName.c_str()); res = ::unlink(fullName.c_str());
if (res == -1) { if (res == -1) {
res = -errno; res = -errno;
rDebug("unlink error: %s", strerror(errno)); VLOG(1) << "unlink error: " << strerror(errno);
} }
} }
return res; return res;
} }
} // namespace encfs

View File

@ -23,13 +23,13 @@
#include <dirent.h> #include <dirent.h>
#include <inttypes.h> #include <inttypes.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/types.h>
#include <list> #include <list>
#include <map> #include <map>
#include <memory> #include <memory>
#include <pthread.h>
#include <stdint.h>
#include <string> #include <string>
#include <sys/types.h>
#include <vector> #include <vector>
#include "CipherKey.h" #include "CipherKey.h"
@ -37,6 +37,8 @@
#include "FileNode.h" #include "FileNode.h"
#include "NameIO.h" #include "NameIO.h"
namespace encfs {
class Cipher; class Cipher;
class EncFS_Context; class EncFS_Context;
class FileNode; class FileNode;
@ -46,8 +48,8 @@ struct RenameEl;
class DirTraverse { class DirTraverse {
public: public:
DirTraverse(const shared_ptr<DIR> &dirPtr, uint64_t iv, DirTraverse(const std::shared_ptr<DIR> &dirPtr, uint64_t iv,
const shared_ptr<NameIO> &naming); const std::shared_ptr<NameIO> &naming);
DirTraverse(const DirTraverse &src); DirTraverse(const DirTraverse &src);
~DirTraverse(); ~DirTraverse();
@ -68,11 +70,11 @@ class DirTraverse {
std::string nextInvalid(); std::string nextInvalid();
private: private:
shared_ptr<DIR> dir; // struct DIR std::shared_ptr<DIR> dir; // struct DIR
// initialization vector to use. Not very general purpose, but makes it // initialization vector to use. Not very general purpose, but makes it
// more efficient to support filename IV chaining.. // more efficient to support filename IV chaining..
uint64_t iv; uint64_t iv;
shared_ptr<NameIO> naming; std::shared_ptr<NameIO> naming;
}; };
inline bool DirTraverse::valid() const { return dir.get() != 0; } inline bool DirTraverse::valid() const { return dir.get() != 0; }
@ -90,16 +92,16 @@ class DirNode {
bool touchesMountpoint(const char *realPath) const; bool touchesMountpoint(const char *realPath) const;
// find files // find files
shared_ptr<FileNode> lookupNode(const char *plaintextName, std::shared_ptr<FileNode> lookupNode(const char *plaintextName,
const char *requestor); const char *requestor);
/* /*
Combined lookupNode + node->open() call. If the open fails, then the Combined lookupNode + node->open() call. If the open fails, then the
node is not retained. If the open succeeds, then the node is returned. node is not retained. If the open succeeds, then the node is returned.
*/ */
shared_ptr<FileNode> openNode(const char *plaintextName, std::shared_ptr<FileNode> openNode(const char *plaintextName,
const char *requestor, int flags, const char *requestor, int flags,
int *openResult); int *openResult);
std::string cipherPath(const char *plaintextPath); std::string cipherPath(const char *plaintextPath);
std::string cipherPathWithoutRoot(const char *plaintextPath); std::string cipherPathWithoutRoot(const char *plaintextPath);
@ -141,9 +143,9 @@ class DirNode {
this call has no effect. this call has no effect.
Returns the FileNode if it was found. Returns the FileNode if it was found.
*/ */
shared_ptr<FileNode> renameNode(const char *from, const char *to); std::shared_ptr<FileNode> renameNode(const char *from, const char *to);
shared_ptr<FileNode> renameNode(const char *from, const char *to, std::shared_ptr<FileNode> renameNode(const char *from, const char *to,
bool forwardMode); bool forwardMode);
/* /*
when directory IV chaining is enabled, a directory can't be renamed when directory IV chaining is enabled, a directory can't be renamed
@ -151,7 +153,7 @@ class DirNode {
called after renaming the directory, passing in the plaintext from and called after renaming the directory, passing in the plaintext from and
to paths. to paths.
*/ */
shared_ptr<RenameOp> newRenameOp(const char *from, const char *to); std::shared_ptr<RenameOp> newRenameOp(const char *from, const char *to);
private: private:
friend class RenameOp; friend class RenameOp;
@ -159,7 +161,7 @@ class DirNode {
bool genRenameList(std::list<RenameEl> &list, const char *fromP, bool genRenameList(std::list<RenameEl> &list, const char *fromP,
const char *toP); const char *toP);
shared_ptr<FileNode> findOrCreate(const char *plainName); std::shared_ptr<FileNode> findOrCreate(const char *plainName);
pthread_mutex_t mutex; pthread_mutex_t mutex;
@ -169,7 +171,9 @@ class DirNode {
std::string rootDir; std::string rootDir;
FSConfigPtr fsConfig; FSConfigPtr fsConfig;
shared_ptr<NameIO> naming; std::shared_ptr<NameIO> naming;
}; };
} // namespace encfs
#endif #endif

9
encfs/Error.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "Error.h"
namespace encfs {
el::base::DispatchAction rlogAction = el::base::DispatchAction::NormalLog;
Error::Error(const char *msg) : runtime_error(msg) {}
} // namespace encfs

44
encfs/Error.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef _Error_incl_
#define _Error_incl_
// Provides compatibility with RLog's rAssert, which throws an Error exception.
#include "internal/easylogging++.h"
#include <stdexcept>
namespace encfs {
class Error : public std::runtime_error {
public:
Error(const char *msg);
};
#define STR(X) #X
#define rAssert(cond) \
do { \
if ((cond) == false) { \
RLOG(ERROR) << "Assert failed: " << STR(cond); \
throw encfs::Error(STR(cond)); \
} \
} while (0)
inline void initLogging() {
el::Configurations defaultConf;
defaultConf.setToDefault();
defaultConf.set(el::Level::Verbose, el::ConfigurationType::Format,
std::string("%datetime %level [%fbase:%line] %msg"));
el::Loggers::reconfigureLogger("default", defaultConf);
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
}
// This can be changed to change log action between normal and syslog logging.
// Not thread-safe, so any change must occur outside of threading context.
extern el::base::DispatchAction rlogAction;
#define RLOG(LEVEL, ...) \
C##LEVEL(el::base::Writer, rlogAction, ELPP_CURR_FILE_LOGGER_ID)
} // namespace encfs
#endif

View File

@ -21,13 +21,15 @@
#ifndef _FSConfig_incl_ #ifndef _FSConfig_incl_
#define _FSConfig_incl_ #define _FSConfig_incl_
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "encfs.h"
#include "Interface.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "shared_ptr.h" #include "Interface.h"
#include "encfs.h"
namespace encfs {
enum ConfigType { enum ConfigType {
Config_None = 0, Config_None = 0,
@ -52,10 +54,10 @@ struct EncFSConfig {
int subVersion; int subVersion;
// interface of cipher // interface of cipher
rel::Interface cipherIface; Interface cipherIface;
// interface used for file name coding // interface used for file name coding
rel::Interface nameIface; Interface nameIface;
int keySize; // reported in bits int keySize; // reported in bits
int blockSize; // reported in bytes int blockSize; // reported in bytes
@ -93,7 +95,7 @@ struct EncFSConfig {
const std::string &rootDir); const std::string &rootDir);
CipherKey getNewUserKey(); CipherKey getNewUserKey();
shared_ptr<Cipher> getCipher() const; std::shared_ptr<Cipher> getCipher() const;
// deprecated // deprecated
void assignKeyData(const std::string &in); void assignKeyData(const std::string &in);
@ -112,12 +114,12 @@ std::ostream &operator<<(std::ostream &os, const EncFSConfig &cfg);
std::istream &operator>>(std::istream &os, EncFSConfig &cfg); std::istream &operator>>(std::istream &os, EncFSConfig &cfg);
struct FSConfig { struct FSConfig {
shared_ptr<EncFSConfig> config; std::shared_ptr<EncFSConfig> config;
shared_ptr<EncFS_Opts> opts; std::shared_ptr<EncFS_Opts> opts;
shared_ptr<Cipher> cipher; std::shared_ptr<Cipher> cipher;
CipherKey key; CipherKey key;
shared_ptr<NameIO> nameCoding; std::shared_ptr<NameIO> nameCoding;
bool forceDecode; // force decode on MAC block failures bool forceDecode; // force decode on MAC block failures
bool reverseEncryption; // reverse encryption operation bool reverseEncryption; // reverse encryption operation
@ -128,6 +130,8 @@ struct FSConfig {
: forceDecode(false), reverseEncryption(false), idleTracking(false) {} : forceDecode(false), reverseEncryption(false), idleTracking(false) {}
}; };
typedef shared_ptr<FSConfig> FSConfigPtr; typedef std::shared_ptr<FSConfig> FSConfigPtr;
} // namespace encfs
#endif #endif

View File

@ -20,6 +20,8 @@
#include "FileIO.h" #include "FileIO.h"
namespace encfs {
FileIO::FileIO() {} FileIO::FileIO() {}
FileIO::~FileIO() {} FileIO::~FileIO() {}
@ -30,3 +32,5 @@ bool FileIO::setIV(uint64_t iv) {
(void)iv; (void)iv;
return true; return true;
} }
} // namespace encfs

View File

@ -28,6 +28,8 @@
#include "Interface.h" #include "Interface.h"
#include "encfs.h" #include "encfs.h"
namespace encfs {
struct IORequest { struct IORequest {
off_t offset; off_t offset;
@ -45,7 +47,7 @@ class FileIO {
FileIO(); FileIO();
virtual ~FileIO(); virtual ~FileIO();
virtual rel::Interface interface() const = 0; virtual Interface interface() const = 0;
// default implementation returns 1, meaning this is not block oriented. // default implementation returns 1, meaning this is not block oriented.
virtual int blockSize() const; virtual int blockSize() const;
@ -78,4 +80,6 @@ class FileIO {
FileIO &operator=(const FileIO &); FileIO &operator=(const FileIO &);
}; };
} // namespace encfs
#endif #endif

View File

@ -28,10 +28,10 @@
#include <sys/fsuid.h> #include <sys/fsuid.h>
#endif #endif
#include <rlog/rlog.h>
#include <cstring> #include <cstring>
#include "CipherFileIO.h" #include "CipherFileIO.h"
#include "Error.h"
#include "FileIO.h" #include "FileIO.h"
#include "FileNode.h" #include "FileNode.h"
#include "FileUtils.h" #include "FileUtils.h"
@ -39,13 +39,9 @@
#include "Mutex.h" #include "Mutex.h"
#include "RawFileIO.h" #include "RawFileIO.h"
namespace rlog {
class RLogChannel;
} // namespace rlog
using namespace std; using namespace std;
using namespace rel;
using namespace rlog; namespace encfs {
/* /*
TODO: locking at the FileNode level is inefficient, since this precludes TODO: locking at the FileNode level is inefficient, since this precludes
@ -56,8 +52,6 @@ using namespace rlog;
sent to the IO subsystem! sent to the IO subsystem!
*/ */
static RLogChannel *Info = DEF_CHANNEL("info/FileNode", Log_Info);
FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg, FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
const char *plaintextName_, const char *cipherName_) { const char *plaintextName_, const char *cipherName_) {
pthread_mutex_init(&mutex, 0); pthread_mutex_init(&mutex, 0);
@ -71,11 +65,11 @@ FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
this->fsConfig = cfg; this->fsConfig = cfg;
// chain RawFileIO & CipherFileIO // chain RawFileIO & CipherFileIO
shared_ptr<FileIO> rawIO(new RawFileIO(_cname)); std::shared_ptr<FileIO> rawIO(new RawFileIO(_cname));
io = 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 || cfg->config->blockMACRandBytes)
io = shared_ptr<FileIO>(new MACFileIO(io, fsConfig)); io = std::shared_ptr<FileIO>(new MACFileIO(io, fsConfig));
} }
FileNode::~FileNode() { FileNode::~FileNode() {
@ -95,7 +89,7 @@ const char *FileNode::plaintextName() const { return _pname.c_str(); }
string FileNode::plaintextParent() const { return parentDirectory(_pname); } string FileNode::plaintextParent() const { return parentDirectory(_pname); }
static bool setIV(const shared_ptr<FileIO> &io, uint64_t iv) { static bool setIV(const 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);
@ -106,7 +100,7 @@ static bool setIV(const shared_ptr<FileIO> &io, uint64_t iv) {
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 );
rDebug("calling setIV on %s", cipherName_); 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;
@ -145,14 +139,14 @@ int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid) {
if (uid != 0) { if (uid != 0) {
olduid = setfsuid(uid); olduid = setfsuid(uid);
if (olduid == -1) { if (olduid == -1) {
rInfo("setfsuid error: %s", strerror(errno)); RLOG(INFO) << "setfsuid error: " << strerror(errno);
return -EPERM; return -EPERM;
} }
} }
if (gid != 0) { if (gid != 0) {
oldgid = setfsgid(gid); oldgid = setfsgid(gid);
if (oldgid == -1) { if (oldgid == -1) {
rInfo("setfsgid error: %s", strerror(errno)); RLOG(INFO) << "setfsgid error: " << strerror(errno);
return -EPERM; return -EPERM;
} }
} }
@ -175,7 +169,7 @@ int FileNode::mknod(mode_t mode, dev_t rdev, uid_t uid, gid_t gid) {
if (res == -1) { if (res == -1) {
int eno = errno; int eno = errno;
rDebug("mknod error: %s", strerror(eno)); VLOG(1) << "mknod error: " << strerror(eno);
res = -eno; res = -eno;
} }
@ -215,8 +209,7 @@ ssize_t FileNode::read(off_t offset, unsigned char *data, ssize_t size) const {
} }
bool FileNode::write(off_t offset, unsigned char *data, ssize_t size) { bool FileNode::write(off_t offset, unsigned char *data, ssize_t size) {
rLog(Info, "FileNode::write offset %" PRIi64 ", data size %i", offset, RLOG(INFO) << "FileNode::write offset " << offset << ", data size " << size;
(int)size);
IORequest req; IORequest req;
req.offset = offset; req.offset = offset;
@ -258,3 +251,5 @@ int FileNode::sync(bool datasync) {
} else } else
return fh; return fh;
} }
} // namespace encfs

View File

@ -22,17 +22,19 @@
#define _FileNode_incl_ #define _FileNode_incl_
#include <inttypes.h> #include <inttypes.h>
#include <memory>
#include <pthread.h> #include <pthread.h>
#include <stdint.h> #include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <string> #include <string>
#include <sys/types.h>
#include "CipherKey.h" #include "CipherKey.h"
#include "FileUtils.h"
#include "FSConfig.h" #include "FSConfig.h"
#include "FileUtils.h"
#include "encfs.h" #include "encfs.h"
namespace encfs {
class Cipher; class Cipher;
class DirNode; class DirNode;
class FileIO; class FileIO;
@ -85,7 +87,7 @@ class FileNode {
FSConfigPtr fsConfig; FSConfigPtr fsConfig;
shared_ptr<FileIO> io; std::shared_ptr<FileIO> io;
std::string _pname; // plaintext name std::string _pname; // plaintext name
std::string _cname; // encrypted name std::string _cname; // encrypted name
DirNode *parent; DirNode *parent;
@ -95,4 +97,6 @@ class FileNode {
FileNode &operator=(const FileNode &src); FileNode &operator=(const FileNode &src);
}; };
} // namespace encfs
#endif #endif

View File

@ -24,22 +24,21 @@
#endif #endif
#define _BSD_SOURCE // pick up setenv on RH7.3 #define _BSD_SOURCE // pick up setenv on RH7.3
#include <fcntl.h> #include "internal/easylogging++.h"
#include <rlog/Error.h>
#include <rlog/rlog.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <cctype> #include <cctype>
#include <cerrno> #include <cerrno>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <iostream> #include <fcntl.h>
#include <fstream> #include <fstream>
#include <iostream>
#include <list> #include <list>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <tinyxml2.h> #include <tinyxml2.h>
#include <unistd.h>
#include <vector> #include <vector>
#include "BlockNameIO.h" #include "BlockNameIO.h"
@ -49,6 +48,7 @@
#include "ConfigVar.h" #include "ConfigVar.h"
#include "Context.h" #include "Context.h"
#include "DirNode.h" #include "DirNode.h"
#include "Error.h"
#include "FSConfig.h" #include "FSConfig.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "Interface.h" #include "Interface.h"
@ -62,15 +62,11 @@
#include "intl/gettext.h" #include "intl/gettext.h"
#include "readpassphrase.h" #include "readpassphrase.h"
// disable rlog section grouping for this file.. seems to cause problems
#undef RLOG_SECTION
#define RLOG_SECTION
using namespace rel;
using namespace rlog;
using namespace std; using namespace std;
using gnu::autosprintf; using gnu::autosprintf;
namespace encfs {
static const int DefaultBlockSize = 1024; static const int DefaultBlockSize = 1024;
// The maximum length of text passwords. If longer are needed, // The maximum length of text passwords. If longer are needed,
// use the extpass option, as extpass can return arbitrary length binary data. // use the extpass option, as extpass can return arbitrary length binary data.
@ -109,18 +105,18 @@ struct ConfigInfo {
int currentSubVersion; int currentSubVersion;
int defaultSubVersion; int defaultSubVersion;
} ConfigFileMapping[] = { } ConfigFileMapping[] = {
// current format // current format
{".encfs6.xml", Config_V6, "ENCFS6_CONFIG", readV6Config, writeV6Config, {".encfs6.xml", Config_V6, "ENCFS6_CONFIG", readV6Config, writeV6Config,
V6SubVersion, 0}, V6SubVersion, 0},
// 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, NULL, 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, NULL, NULL, NULL, 0, 0},
{".encfs2", Config_Prehistoric, NULL, NULL, NULL, 0, 0}, {".encfs2", Config_Prehistoric, NULL, NULL, NULL, 0, 0},
{".encfs", Config_Prehistoric, NULL, NULL, NULL, 0, 0}, {".encfs", Config_Prehistoric, NULL, NULL, NULL, 0, 0},
{NULL, Config_None, NULL, NULL, NULL, 0, 0}}; {NULL, Config_None, NULL, NULL, NULL, 0, 0}};
EncFS_Root::EncFS_Root() {} EncFS_Root::EncFS_Root() {}
@ -217,11 +213,12 @@ ConfigType readConfig_load(ConfigInfo *nm, const char *path,
config->cfgType = nm->type; config->cfgType = nm->type;
return nm->type; return nm->type;
} }
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
err.log(_RLWarningChannel); RLOG(ERROR) << "readConfig error: " << err.what();
} }
rError(_("Found config file %s, but failed to load - exiting"), path); RLOG(ERROR) << "Found config file " << path
<< ", but failed to load - exiting";
exit(1); exit(1);
} else { } else {
// No load function - must be an unsupported type.. // No load function - must be an unsupported type..
@ -242,9 +239,9 @@ ConfigType readConfig(const string &rootDir, EncFSConfig *config) {
char *envFile = getenv(nm->environmentOverride); char *envFile = getenv(nm->environmentOverride);
if (envFile != NULL) { if (envFile != NULL) {
if (!fileExists(envFile)) { if (!fileExists(envFile)) {
rError( RLOG(ERROR)
"fatal: config file specified by environment does not exist: %s", << "fatal: config file specified by environment does not exist: "
envFile); << envFile;
exit(1); exit(1);
} }
return readConfig_load(nm, envFile, config); return readConfig_load(nm, envFile, config);
@ -265,14 +262,13 @@ ConfigType readConfig(const string &rootDir, EncFSConfig *config) {
* Read config file in current "V6" XML format, normally named ".encfs6.xml" * Read config file in current "V6" XML format, normally named ".encfs6.xml"
* This format is in use since Apr 13, 2008 (commit 6d081f5c) * This format is in use since Apr 13, 2008 (commit 6d081f5c)
*/ */
// Read a boost::serialization config file using an Xml reader.. // Read a boost::serialization config file using an Xml reader..
bool readV6Config(const char *configFile, EncFSConfig *cfg, bool readV6Config(const char *configFile, EncFSConfig *cfg, ConfigInfo *info) {
ConfigInfo *info) {
(void)info; (void)info;
XmlReader rdr; XmlReader rdr;
if (!rdr.load(configFile)) { if (!rdr.load(configFile)) {
rError("Failed to load config file %s", configFile); RLOG(ERROR) << "Failed to load config file " << configFile;
return false; return false;
} }
@ -282,34 +278,34 @@ bool readV6Config(const char *configFile, EncFSConfig *cfg,
config = (*serialization)["config"]; config = (*serialization)["config"];
} }
if (!config) { if (!config) {
rError("Unable to find XML configuration in file %s", configFile); RLOG(ERROR) << "Unable to find XML configuration in file " << configFile;
return false; return false;
} }
int version; int version;
if (!config->read("version", &version) && if (!config->read("version", &version) &&
!config->read("@version", &version)) { !config->read("@version", &version)) {
rError("Unable to find version in config file"); RLOG(ERROR) << "Unable to find version in config file";
return false; return false;
} }
// version numbering was complicated by boost::archive // version numbering was complicated by boost::archive
if (version == 20 || version >= 20100713) { if (version == 20 || version >= 20100713) {
rDebug("found new serialization format"); VLOG(1) << "found new serialization format";
cfg->subVersion = version; cfg->subVersion = version;
} else if (version == 26800) { } else if (version == 26800) {
rDebug("found 20080816 version"); VLOG(1) << "found 20080816 version";
cfg->subVersion = 20080816; cfg->subVersion = 20080816;
} else if (version == 26797) { } else if (version == 26797) {
rDebug("found 20080813"); VLOG(1) << "found 20080813";
cfg->subVersion = 20080813; cfg->subVersion = 20080813;
} else if (version < V5SubVersion) { } else if (version < V5SubVersion) {
rError("Invalid version %d - please fix config file", version); RLOG(ERROR) << "Invalid version " << version << " - please fix config file";
} else { } else {
rInfo("Boost <= 1.41 compatibility mode"); VLOG(1) << "Boost <= 1.41 compatibility mode";
cfg->subVersion = version; cfg->subVersion = version;
} }
rDebug("subVersion = %d", cfg->subVersion); VLOG(1) << "subVersion = " << cfg->subVersion;
config->read("creator", &cfg->creator); config->read("creator", &cfg->creator);
config->read("cipherAlg", &cfg->cipherIface); config->read("cipherAlg", &cfg->cipherIface);
@ -367,15 +363,14 @@ bool readV5Config(const char *configFile, EncFSConfig *config,
if (config->subVersion > info->currentSubVersion) { if (config->subVersion > info->currentSubVersion) {
/* config file specifies a version outside our supported /* config file specifies a version outside our supported
range.. */ range.. */
rWarning(_("Config subversion %i found, but this version of" RLOG(WARNING) << "Config subversion " << config->subVersion
" encfs only supports up to version %i."), << " found, which is newer than supported version "
config->subVersion, info->currentSubVersion); << info->currentSubVersion;
return false; return false;
} }
if (config->subVersion < 20040813) { if (config->subVersion < 20040813) {
rError( RLOG(ERROR) << "This version of EncFS doesn't support "
_("This version of EncFS doesn't support " "filesystems created before 2004-08-13";
"filesystems created before 2004-08-13"));
return false; return false;
} }
@ -395,9 +390,9 @@ bool readV5Config(const char *configFile, EncFSConfig *config,
config->blockMACRandBytes = cfgRdr["blockMACRandBytes"].readInt(0); config->blockMACRandBytes = cfgRdr["blockMACRandBytes"].readInt(0);
ok = true; ok = true;
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
err.log(_RLWarningChannel); RLOG(WARNING) << err.what();
rDebug("Error parsing data in config file %s", configFile); VLOG(1) << "Error parsing data in config file " << configFile;
ok = false; ok = false;
} }
} }
@ -435,9 +430,9 @@ bool readV4Config(const char *configFile, EncFSConfig *config,
config->chainedNameIV = false; config->chainedNameIV = false;
ok = true; ok = true;
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
err.log(_RLWarningChannel); RLOG(WARNING) << err.what();
rDebug("Error parsing config file %s", configFile); VLOG(1) << "Error parsing config file " << configFile;
ok = false; ok = false;
} }
} }
@ -461,8 +456,8 @@ bool saveConfig(ConfigType type, const string &rootDir,
try { try {
ok = (*nm->saveFunc)(path.c_str(), config); ok = (*nm->saveFunc)(path.c_str(), config);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
err.log(_RLWarningChannel); RLOG(WARNING) << err.what();
ok = false; ok = false;
} }
break; break;
@ -558,8 +553,7 @@ bool writeV6Config(const char *configFile, const EncFSConfig *cfg) {
return err == tinyxml2::XML_SUCCESS; return err == tinyxml2::XML_SUCCESS;
} }
bool writeV5Config(const char *configFile, bool writeV5Config(const char *configFile, const EncFSConfig *config) {
const EncFSConfig *config) {
ConfigReader cfg; ConfigReader cfg;
cfg["creator"] << config->creator; cfg["creator"] << config->creator;
@ -580,8 +574,7 @@ bool writeV5Config(const char *configFile,
return cfg.save(configFile); return cfg.save(configFile);
} }
bool writeV4Config(const char *configFile, bool writeV4Config(const char *configFile, const EncFSConfig *config) {
const EncFSConfig *config) {
ConfigReader cfg; ConfigReader cfg;
cfg["cipher"] << config->cipherIface; cfg["cipher"] << config->cipherIface;
@ -632,20 +625,23 @@ static Cipher::CipherAlgorithm selectCipherAlgorithm() {
// shown after algorithm name and description. // shown after algorithm name and description.
// xgroup(setup) // xgroup(setup)
_(" -- Supports key lengths of %i to %i bits"), _(" -- Supports key lengths of %i to %i bits"),
it->keyLength.min(), it->keyLength.max()) << "\n"; it->keyLength.min(), it->keyLength.max())
<< "\n";
} }
if (it->blockSize.min() == it->blockSize.max()) { if (it->blockSize.min() == it->blockSize.max()) {
cout << autosprintf( cout << autosprintf(
// shown after algorithm name and description. // shown after algorithm name and description.
// xgroup(setup) // xgroup(setup)
_(" -- block size %i bytes"), it->blockSize.min()) << "\n"; _(" -- block size %i bytes"), it->blockSize.min())
<< "\n";
} else { } else {
cout << autosprintf( cout << autosprintf(
// shown after algorithm name and description. // shown after algorithm name and description.
// xgroup(setup) // xgroup(setup)
_(" -- Supports block sizes of %i to %i bytes"), _(" -- Supports block sizes of %i to %i bytes"),
it->blockSize.min(), it->blockSize.max()) << "\n"; it->blockSize.min(), it->blockSize.max())
<< "\n";
} }
} }
@ -777,7 +773,8 @@ static int selectBlockSize(const Cipher::CipherAlgorithm &alg) {
cout << autosprintf( cout << autosprintf(
// xgroup(setup) // xgroup(setup)
_("Using filesystem block size of %i bytes"), _("Using filesystem block size of %i bytes"),
alg.blockSize.min()) << "\n"; alg.blockSize.min())
<< "\n";
return alg.blockSize.min(); return alg.blockSize.min();
} }
@ -869,8 +866,9 @@ static void selectBlockMAC(int *macBytes, int *macRandBytes, bool forceMac) {
"performance but it also means [almost] any modifications or errors\n" "performance but it also means [almost] any modifications or errors\n"
"within a block will be caught and will cause a read error.")); "within a block will be caught and will cause a read error."));
} else { } else {
cout << "\n\n" << _("You specified --require-macs. " cout << "\n\n"
"Enabling block authentication code headers...") << _("You specified --require-macs. "
"Enabling block authentication code headers...")
<< "\n\n"; << "\n\n";
addMAC = true; addMAC = true;
} }
@ -950,7 +948,8 @@ static bool selectZeroBlockPassThrough() {
"This avoids writing encrypted blocks when file holes are created.")); "This avoids writing encrypted blocks when file holes are created."));
} }
RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) { RootPtr createV6Config(EncFS_Context *ctx,
const std::shared_ptr<EncFS_Opts> &opts) {
const std::string rootDir = opts->rootDir; const std::string rootDir = opts->rootDir;
bool enableIdleTracking = opts->idleTracking; bool enableIdleTracking = opts->idleTracking;
bool forceDecode = opts->forceDecode; bool forceDecode = opts->forceDecode;
@ -1007,7 +1006,7 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
if (configMode == Config_Paranoia || answer[0] == 'p') { if (configMode == Config_Paranoia || answer[0] == 'p') {
if (reverseEncryption) { if (reverseEncryption) {
rError(_("Paranoia configuration not supported for reverse encryption")); cerr << _("Paranoia configuration not supported for reverse encryption");
return rootInfo; return rootInfo;
} }
@ -1022,7 +1021,7 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
blockSize = DefaultBlockSize; blockSize = DefaultBlockSize;
alg = findCipherAlgorithm("AES", keySize); alg = findCipherAlgorithm("AES", keySize);
// If case-insensitive system, opt for Block32 filename encoding // If case-insensitive system, opt for Block32 filename encoding
#if defined(__APPLE__) || defined(WIN32) #if defined(__APPLE__) || defined(WIN32)
nameIOIface = BlockNameIO::CurrentInterface(true); nameIOIface = BlockNameIO::CurrentInterface(true);
#else #else
@ -1042,7 +1041,7 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
blockSize = DefaultBlockSize; blockSize = DefaultBlockSize;
alg = findCipherAlgorithm("AES", keySize); alg = findCipherAlgorithm("AES", keySize);
// If case-insensitive system, opt for Block32 filename encoding // If case-insensitive system, opt for Block32 filename encoding
#if defined(__APPLE__) || defined(WIN32) #if defined(__APPLE__) || defined(WIN32)
nameIOIface = BlockNameIO::CurrentInterface(true); nameIOIface = BlockNameIO::CurrentInterface(true);
#else #else
@ -1096,17 +1095,18 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
} }
} }
shared_ptr<Cipher> cipher = Cipher::New(alg.name, keySize); std::shared_ptr<Cipher> cipher = Cipher::New(alg.name, keySize);
if (!cipher) { if (!cipher) {
rError(_("Unable to instanciate cipher %s, key size %i, block size %i"), cerr << autosprintf(
alg.name.c_str(), keySize, blockSize); _("Unable to instanciate cipher %s, key size %i, block size %i"),
alg.name.c_str(), keySize, blockSize);
return rootInfo; return rootInfo;
} else { } else {
rDebug("Using cipher %s, key size %i, block size %i", alg.name.c_str(), VLOG(1) << "Using cipher " << alg.name << ", key size " << keySize
keySize, blockSize); << ", block size " << blockSize;
} }
shared_ptr<EncFSConfig> config(new EncFSConfig); std::shared_ptr<EncFSConfig> config(new EncFSConfig);
config->cfgType = Config_V6; config->cfgType = Config_V6;
config->cipherIface = cipher->interface(); config->cipherIface = cipher->interface();
@ -1129,7 +1129,8 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
cout << "\n"; cout << "\n";
// xgroup(setup) // xgroup(setup)
cout << _("Configuration finished. The filesystem to be created has\n" cout << _("Configuration finished. The filesystem to be created has\n"
"the following properties:") << endl; "the following properties:")
<< endl;
showFSInfo(config.get()); showFSInfo(config.get());
if (config->externalIVChaining) { if (config->externalIVChaining) {
@ -1140,7 +1141,8 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
"The programs 'mutt' and 'procmail' are known to fail. For\n" "The programs 'mutt' and 'procmail' are known to fail. For\n"
"more information, please see the encfs mailing list.\n" "more information, please see the encfs mailing list.\n"
"If you would like to choose another configuration setting,\n" "If you would like to choose another configuration setting,\n"
"please press CTRL-C now to abort and start over.") << endl; "please press CTRL-C now to abort and start over.")
<< endl;
cout << endl; cout << endl;
} }
@ -1158,7 +1160,7 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
// get user key and use it to encode volume key // get user key and use it to encode volume key
CipherKey userKey; CipherKey userKey;
rDebug("useStdin: %i", 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);
@ -1174,19 +1176,21 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
delete[] encodedKey; delete[] encodedKey;
if (!volumeKey) { if (!volumeKey) {
rWarning( cerr << _(
_("Failure generating new volume key! " "Failure generating new volume key! "
"Please report this error.")); "Please report this error.");
return rootInfo; return rootInfo;
} }
if (!saveConfig(Config_V6, rootDir, config.get())) return rootInfo; if (!saveConfig(Config_V6, rootDir, config.get())) {
return rootInfo;
}
// fill in config struct // fill in config struct
shared_ptr<NameIO> nameCoder = std::shared_ptr<NameIO> nameCoder =
NameIO::New(config->nameIface, cipher, volumeKey); NameIO::New(config->nameIface, cipher, volumeKey);
if (!nameCoder) { if (!nameCoder) {
rWarning(_("Name coding interface not supported")); cerr << _("Name coding interface not supported");
cout << _("The filename encoding interface requested is not available") cout << _("The filename encoding interface requested is not available")
<< endl; << endl;
return rootInfo; return rootInfo;
@ -1208,13 +1212,14 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
rootInfo = RootPtr(new EncFS_Root); rootInfo = RootPtr(new EncFS_Root);
rootInfo->cipher = cipher; rootInfo->cipher = cipher;
rootInfo->volumeKey = volumeKey; rootInfo->volumeKey = volumeKey;
rootInfo->root = shared_ptr<DirNode>(new DirNode(ctx, rootDir, fsConfig)); rootInfo->root =
std::shared_ptr<DirNode>(new DirNode(ctx, rootDir, fsConfig));
return rootInfo; return rootInfo;
} }
void showFSInfo(const EncFSConfig *config) { void showFSInfo(const EncFSConfig *config) {
shared_ptr<Cipher> cipher = Cipher::New(config->cipherIface, -1); std::shared_ptr<Cipher> cipher = Cipher::New(config->cipherIface, -1);
{ {
cout << autosprintf( cout << autosprintf(
// xgroup(diag) // xgroup(diag)
@ -1243,7 +1248,7 @@ void showFSInfo(const EncFSConfig *config) {
config->nameIface.revision(), config->nameIface.age()); config->nameIface.revision(), config->nameIface.age());
// check if we support the filename encoding interface.. // check if we support the filename encoding interface..
shared_ptr<NameIO> nameCoder = std::shared_ptr<NameIO> nameCoder =
NameIO::New(config->nameIface, cipher, CipherKey()); NameIO::New(config->nameIface, cipher, CipherKey());
if (!nameCoder) { if (!nameCoder) {
// xgroup(diag) // xgroup(diag)
@ -1269,7 +1274,8 @@ void showFSInfo(const EncFSConfig *config) {
} }
if (config->kdfIterations > 0 && config->salt.size() > 0) { if (config->kdfIterations > 0 && config->salt.size() > 0) {
cout << autosprintf(_("Using PBKDF2, with %i iterations"), cout << autosprintf(_("Using PBKDF2, with %i iterations"),
config->kdfIterations) << "\n"; config->kdfIterations)
<< "\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";
} }
@ -1279,14 +1285,16 @@ void showFSInfo(const EncFSConfig *config) {
// xgroup(diag) // xgroup(diag)
_("Block Size: %i bytes + %i byte MAC header"), _("Block Size: %i bytes + %i byte MAC header"),
config->blockSize, config->blockSize,
config->blockMACBytes + config->blockMACRandBytes) << endl; config->blockMACBytes + config->blockMACRandBytes)
<< endl;
} else { } else {
// new version stores the header as part of that block size.. // new version stores the header as part of that block size..
cout << autosprintf( cout << autosprintf(
// xgroup(diag) // xgroup(diag)
_("Block Size: %i bytes, including %i byte MAC header"), _("Block Size: %i bytes, including %i byte MAC header"),
config->blockSize, config->blockSize,
config->blockMACBytes + config->blockMACRandBytes) << endl; config->blockMACBytes + config->blockMACRandBytes)
<< endl;
} }
} else { } else {
// xgroup(diag) // xgroup(diag)
@ -1312,8 +1320,7 @@ void showFSInfo(const EncFSConfig *config) {
} }
cout << "\n"; cout << "\n";
} }
std::shared_ptr<Cipher> EncFSConfig::getCipher() const {
shared_ptr<Cipher> EncFSConfig::getCipher() const {
return Cipher::New(cipherIface, keySize); return Cipher::New(cipherIface, keySize);
} }
@ -1339,7 +1346,7 @@ unsigned char *EncFSConfig::getSaltData() const {
CipherKey EncFSConfig::makeKey(const char *password, int passwdLen) { CipherKey EncFSConfig::makeKey(const char *password, int passwdLen) {
CipherKey userKey; CipherKey userKey;
shared_ptr<Cipher> cipher = getCipher(); std::shared_ptr<Cipher> cipher = getCipher();
// 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..
@ -1427,7 +1434,7 @@ CipherKey EncFSConfig::getUserKey(const std::string &passProg,
perror(_("Internal error: socketpair() failed")); perror(_("Internal error: socketpair() failed"));
return result; return result;
} }
rDebug("getUserKey: fds = %i, %i", fds[0], fds[1]); VLOG(1) << "getUserKey: fds = " << fds[0] << ", " << fds[1];
pid = fork(); pid = fork();
if (pid == -1) { if (pid == -1) {
@ -1518,9 +1525,9 @@ CipherKey EncFSConfig::getNewUserKey() {
return userKey; return userKey;
} }
RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) { RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts) {
RootPtr rootInfo; RootPtr rootInfo;
shared_ptr<EncFSConfig> config(new EncFSConfig); std::shared_ptr<EncFSConfig> config(new EncFSConfig);
if (readConfig(opts->rootDir, config.get()) != Config_None) { if (readConfig(opts->rootDir, config.get()) != Config_None) {
if (config->blockMACBytes == 0 && opts->requireMac) { if (config->blockMACBytes == 0 && opts->requireMac) {
@ -1539,11 +1546,12 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
} }
// first, instanciate the cipher. // first, instanciate the cipher.
shared_ptr<Cipher> cipher = config->getCipher(); std::shared_ptr<Cipher> cipher = config->getCipher();
if (!cipher) { if (!cipher) {
rError(_("Unable to find cipher %s, version %i:%i:%i"), cerr << autosprintf(
config->cipherIface.name().c_str(), config->cipherIface.current(), _("Unable to find cipher %s, version %i:%i:%i"),
config->cipherIface.revision(), config->cipherIface.age()); config->cipherIface.name().c_str(), config->cipherIface.current(),
config->cipherIface.revision(), config->cipherIface.age());
// xgroup(diag) // xgroup(diag)
cout << _("The requested cipher interface is not available\n"); cout << _("The requested cipher interface is not available\n");
return rootInfo; return rootInfo;
@ -1552,7 +1560,7 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
if (opts->delayMount) { if (opts->delayMount) {
rootInfo = RootPtr(new EncFS_Root); rootInfo = RootPtr(new EncFS_Root);
rootInfo->cipher = cipher; rootInfo->cipher = cipher;
rootInfo->root = shared_ptr<DirNode>(); rootInfo->root = std::shared_ptr<DirNode>();
return rootInfo; return rootInfo;
} }
@ -1560,7 +1568,7 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
CipherKey userKey; CipherKey userKey;
if (opts->passwordProgram.empty()) { if (opts->passwordProgram.empty()) {
rDebug("useStdin: %i", 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
@ -1568,7 +1576,7 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
if (!userKey) return rootInfo; if (!userKey) return rootInfo;
rDebug("cipher key size = %i", cipher->encodedKeySize()); VLOG(1) << "cipher key size = " << cipher->encodedKeySize();
// decode volume key.. // decode volume key..
CipherKey volumeKey = CipherKey volumeKey =
cipher->readKey(config->getKeyData(), userKey, opts->checkKey); cipher->readKey(config->getKeyData(), userKey, opts->checkKey);
@ -1580,12 +1588,13 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
return rootInfo; return rootInfo;
} }
shared_ptr<NameIO> nameCoder = std::shared_ptr<NameIO> nameCoder =
NameIO::New(config->nameIface, cipher, volumeKey); NameIO::New(config->nameIface, cipher, volumeKey);
if (!nameCoder) { if (!nameCoder) {
rError(_("Unable to find nameio interface %s, version %i:%i:%i"), cerr << autosprintf(
config->nameIface.name().c_str(), config->nameIface.current(), _("Unable to find nameio interface '%s', version %i:%i:%i"),
config->nameIface.revision(), config->nameIface.age()); config->nameIface.name().c_str(), config->nameIface.current(),
config->nameIface.revision(), config->nameIface.age());
// xgroup(diag) // xgroup(diag)
cout << _( cout << _(
"The requested filename coding interface is " "The requested filename coding interface is "
@ -1609,7 +1618,7 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
rootInfo->cipher = cipher; rootInfo->cipher = cipher;
rootInfo->volumeKey = volumeKey; rootInfo->volumeKey = volumeKey;
rootInfo->root = rootInfo->root =
shared_ptr<DirNode>(new 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
@ -1621,14 +1630,16 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
} }
int remountFS(EncFS_Context *ctx) { int remountFS(EncFS_Context *ctx) {
rDebug("Attempting to reinitialize filesystem"); VLOG(1) << "Attempting to reinitialize filesystem";
RootPtr rootInfo = initFS(ctx, ctx->opts); RootPtr rootInfo = initFS(ctx, ctx->opts);
if (rootInfo) { if (rootInfo) {
ctx->setRoot(rootInfo->root); ctx->setRoot(rootInfo->root);
return 0; return 0;
} else { } else {
rInfo(_("Remount failed")); RLOG(INFO) << "Remount failed";
return -EACCES; return -EACCES;
} }
} }
} // namespace encfs

View File

@ -21,15 +21,17 @@
#ifndef _FileUtils_incl_ #ifndef _FileUtils_incl_
#define _FileUtils_incl_ #define _FileUtils_incl_
#include <sys/types.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <sys/types.h>
#include "CipherKey.h" #include "CipherKey.h"
#include "FSConfig.h" #include "FSConfig.h"
#include "Interface.h" #include "Interface.h"
#include "encfs.h" #include "encfs.h"
namespace encfs {
// true if the path points to an existing node (of any type) // true if the path points to an existing node (of any type)
bool fileExists(const char *fileName); bool fileExists(const char *fileName);
// true if path is a directory // true if path is a directory
@ -50,15 +52,15 @@ class Cipher;
class DirNode; class DirNode;
struct EncFS_Root { struct EncFS_Root {
shared_ptr<Cipher> cipher; std::shared_ptr<Cipher> cipher;
CipherKey volumeKey; CipherKey volumeKey;
shared_ptr<DirNode> root; std::shared_ptr<DirNode> root;
EncFS_Root(); EncFS_Root();
~EncFS_Root(); ~EncFS_Root();
}; };
typedef shared_ptr<EncFS_Root> RootPtr; typedef std::shared_ptr<EncFS_Root> RootPtr;
enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia }; enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia };
@ -129,9 +131,10 @@ bool saveConfig(ConfigType type, const std::string &rootdir,
class EncFS_Context; class EncFS_Context;
RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts); RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr<EncFS_Opts> &opts);
RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts); RootPtr createV6Config(EncFS_Context *ctx,
const std::shared_ptr<EncFS_Opts> &opts);
void showFSInfo(const EncFSConfig *config); void showFSInfo(const EncFSConfig *config);
@ -147,4 +150,6 @@ bool readV6Config(const char *configFile, EncFSConfig *config,
struct ConfigInfo *); struct ConfigInfo *);
bool writeV6Config(const char *configFile, const EncFSConfig *config); bool writeV6Config(const char *configFile, const EncFSConfig *config);
} // namespace encfs
#endif #endif

View File

@ -20,18 +20,10 @@
#include "Interface.h" #include "Interface.h"
#include <rlog/rlog.h>
#include "ConfigVar.h" #include "ConfigVar.h"
#include "Error.h"
namespace rlog { namespace encfs {
class RLogChannel;
} // namespace rlog
using namespace rel;
using namespace rlog;
static RLogChannel *Info = DEF_CHANNEL("info/iface", Log_Info);
Interface::Interface(const char *name_, int Current, int Revision, int Age) 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) {}
@ -115,9 +107,9 @@ static int diffSum(const Interface &A, const Interface &B) {
const int EqualVersion = (1 * 3 + 1) * 3 + 1; const int EqualVersion = (1 * 3 + 1) * 3 + 1;
bool Interface::implements(const Interface &B) const { bool Interface::implements(const Interface &B) const {
rLog(Info, "checking if %s(%i:%i:%i) implements %s(%i:%i:%i)", name().c_str(), VLOG(1) << "checking if " << name() << "(" << current() << ":" << revision()
current(), revision(), age(), B.name().c_str(), B.current(), << ":" << age() << ") implements " << B.name() << "(" << B.current()
B.revision(), B.age()); << ":" << B.revision() << ")";
if (name() != B.name()) return false; if (name() != B.name()) return false;
@ -153,7 +145,7 @@ bool operator>=(const Interface &A, const Interface &B) {
return A.name() < B.name(); return A.name() < B.name();
} }
ConfigVar &operator<<(ConfigVar &dst, const rel::Interface &iface) { ConfigVar &operator<<(ConfigVar &dst, const Interface &iface) {
dst << iface.name() << iface.current() << iface.revision() << iface.age(); dst << iface.name() << iface.current() << iface.revision() << iface.age();
return dst; return dst;
} }
@ -165,3 +157,5 @@ const ConfigVar &operator>>(const ConfigVar &src, Interface &iface) {
src >> iface.age(); src >> iface.age();
return src; return src;
} }
} // namespace encfs

View File

@ -23,10 +23,9 @@
#include <string> #include <string>
class ConfigVar; namespace encfs {
// part of REL library.. class ConfigVar;
namespace rel {
class Interface { class Interface {
public: public:
@ -67,16 +66,17 @@ class Interface {
int _revision; int _revision;
int _age; int _age;
}; };
}
ConfigVar &operator<<(ConfigVar &, const rel::Interface &); ConfigVar &operator<<(ConfigVar &, const Interface &);
const ConfigVar &operator>>(const ConfigVar &, rel::Interface &); const ConfigVar &operator>>(const ConfigVar &, Interface &);
bool operator<(const rel::Interface &A, const rel::Interface &B); bool operator<(const Interface &A, const Interface &B);
bool operator>(const rel::Interface &A, const rel::Interface &B); bool operator>(const Interface &A, const Interface &B);
bool operator<=(const rel::Interface &A, const rel::Interface &B); bool operator<=(const Interface &A, const Interface &B);
bool operator>=(const rel::Interface &A, const rel::Interface &B); bool operator>=(const Interface &A, const Interface &B);
bool operator==(const rel::Interface &A, const rel::Interface &B); bool operator==(const Interface &A, const Interface &B);
bool operator!=(const rel::Interface &A, const rel::Interface &B); bool operator!=(const Interface &A, const Interface &B);
} // namespace encfs
#endif #endif

View File

@ -20,29 +20,23 @@
#include "MACFileIO.h" #include "MACFileIO.h"
#include <inttypes.h> #include "internal/easylogging++.h"
#include <rlog/Error.h>
#include <rlog/rlog.h>
#include <sys/stat.h>
#include <cstring> #include <cstring>
#include <inttypes.h>
#include <sys/stat.h>
#include "BlockFileIO.h" #include "BlockFileIO.h"
#include "Cipher.h" #include "Cipher.h"
#include "Error.h"
#include "FileIO.h" #include "FileIO.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "MemoryPool.h" #include "MemoryPool.h"
#include "i18n.h" #include "i18n.h"
namespace rlog {
class RLogChannel;
} // namespace rlog
using namespace rlog;
using namespace rel;
using namespace std; using namespace std;
static RLogChannel *Info = DEF_CHANNEL("info/MACFileIO", Log_Info); namespace encfs {
//
// Version 1.0 worked on blocks of size (blockSize + headerSize). // Version 1.0 worked on blocks of size (blockSize + headerSize).
// That is, it took [blockSize] worth of user data and added headers. // That is, it took [blockSize] worth of user data and added headers.
// Version 2.0 takes [blockSize - headerSize] worth of user data and writes // Version 2.0 takes [blockSize - headerSize] worth of user data and writes
@ -55,14 +49,15 @@ static RLogChannel *Info = DEF_CHANNEL("info/MACFileIO", Log_Info);
// compatible, except at a high level by checking a revision number for the // compatible, except at a high level by checking a revision number for the
// filesystem... // filesystem...
// //
static rel::Interface MACFileIO_iface("FileIO/MAC", 2, 1, 0); static Interface MACFileIO_iface("FileIO/MAC", 2, 1, 0);
int dataBlockSize(const FSConfigPtr &cfg) { int dataBlockSize(const FSConfigPtr &cfg) {
return cfg->config->blockSize - cfg->config->blockMACBytes - return cfg->config->blockSize - cfg->config->blockMACBytes -
cfg->config->blockMACRandBytes; cfg->config->blockMACRandBytes;
} }
MACFileIO::MACFileIO(const shared_ptr<FileIO> &_base, const FSConfigPtr &cfg) MACFileIO::MACFileIO(const std::shared_ptr<FileIO> &_base,
const FSConfigPtr &cfg)
: BlockFileIO(dataBlockSize(cfg), cfg), : BlockFileIO(dataBlockSize(cfg), cfg),
base(_base), base(_base),
cipher(cfg->cipher), cipher(cfg->cipher),
@ -72,14 +67,14 @@ MACFileIO::MACFileIO(const shared_ptr<FileIO> &_base, const FSConfigPtr &cfg)
warnOnly(cfg->opts->forceDecode) { warnOnly(cfg->opts->forceDecode) {
rAssert(macBytes >= 0 && macBytes <= 8); rAssert(macBytes >= 0 && macBytes <= 8);
rAssert(randBytes >= 0); rAssert(randBytes >= 0);
rLog(Info, "fs block size = %i, macBytes = %i, randBytes = %i", VLOG(1) << "fs block size = " << cfg->config->blockSize
cfg->config->blockSize, cfg->config->blockMACBytes, << ", macBytes = " << cfg->config->blockMACBytes
cfg->config->blockMACRandBytes); << ", randBytes = " << cfg->config->blockMACRandBytes;
} }
MACFileIO::~MACFileIO() {} MACFileIO::~MACFileIO() {}
rel::Interface MACFileIO::interface() const { return MACFileIO_iface; } Interface MACFileIO::interface() const { return MACFileIO_iface; }
int MACFileIO::open(int flags) { return base->open(flags); } int MACFileIO::open(int flags) { return base->open(flags); }
@ -192,10 +187,10 @@ ssize_t MACFileIO::readOneBlock(const IORequest &req) const {
if (fail > 0) { if (fail > 0) {
// uh oh.. // uh oh..
long blockNum = req.offset / bs; long blockNum = req.offset / bs;
rWarning(_("MAC comparison failure in block %li"), blockNum); RLOG(WARNING) << "MAC comparison failure in block " << blockNum;
if (!warnOnly) { if (!warnOnly) {
MemoryPool::release(mb); MemoryPool::release(mb);
throw ERROR(_("MAC comparison failure, refusing to read")); throw Error(_("MAC comparison failure, refusing to read"));
} }
} }
} }
@ -204,7 +199,7 @@ ssize_t MACFileIO::readOneBlock(const IORequest &req) const {
readSize -= headerSize; readSize -= headerSize;
memcpy(req.data, tmp.data + headerSize, readSize); memcpy(req.data, tmp.data + headerSize, readSize);
} else { } else {
rDebug("readSize %i at offset %" PRIi64, (int)readSize, req.offset); VLOG(1) << "readSize " << readSize << " at offset " << req.offset;
if (readSize > 0) readSize = 0; if (readSize > 0) readSize = 0;
} }
@ -264,3 +259,5 @@ int MACFileIO::truncate(off_t size) {
} }
bool MACFileIO::isWritable() const { return base->isWritable(); } bool MACFileIO::isWritable() const { return base->isWritable(); }
} // namespace encfs

View File

@ -21,9 +21,9 @@
#ifndef _MACFileIO_incl_ #ifndef _MACFileIO_incl_
#define _MACFileIO_incl_ #define _MACFileIO_incl_
#include <memory>
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <memory>
#include "BlockFileIO.h" #include "BlockFileIO.h"
#include "Cipher.h" #include "Cipher.h"
@ -31,6 +31,8 @@
#include "FSConfig.h" #include "FSConfig.h"
#include "Interface.h" #include "Interface.h"
namespace encfs {
class Cipher; class Cipher;
class FileIO; class FileIO;
struct IORequest; struct IORequest;
@ -42,11 +44,11 @@ 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 shared_ptr<FileIO> &base, const FSConfigPtr &cfg); MACFileIO(const std::shared_ptr<FileIO> &base, const FSConfigPtr &cfg);
MACFileIO(); MACFileIO();
virtual ~MACFileIO(); virtual ~MACFileIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual void setFileName(const char *fileName); virtual void setFileName(const char *fileName);
virtual const char *getFileName() const; virtual const char *getFileName() const;
@ -64,12 +66,14 @@ class MACFileIO : public BlockFileIO {
virtual ssize_t readOneBlock(const IORequest &req) const; virtual ssize_t readOneBlock(const IORequest &req) const;
virtual bool writeOneBlock(const IORequest &req); virtual bool writeOneBlock(const IORequest &req);
shared_ptr<FileIO> base; std::shared_ptr<FileIO> base;
shared_ptr<Cipher> cipher; std::shared_ptr<Cipher> cipher;
CipherKey key; CipherKey key;
int macBytes; int macBytes;
int randBytes; int randBytes;
bool warnOnly; bool warnOnly;
}; };
} // namespace encfs
#endif #endif

View File

@ -20,9 +20,9 @@
#include "MemoryPool.h" #include "MemoryPool.h"
#include <cstring>
#include <openssl/ossl_typ.h> #include <openssl/ossl_typ.h>
#include <pthread.h> #include <pthread.h>
#include <cstring>
#ifdef HAVE_VALGRIND_MEMCHECK_H #ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h> #include <valgrind/memcheck.h>
@ -33,7 +33,9 @@
#include <openssl/buffer.h> #include <openssl/buffer.h>
#define BLOCKDATA(BLOCK) (unsigned char *) BLOCK->data->data #define BLOCKDATA(BLOCK) (unsigned char *)BLOCK->data->data
namespace encfs {
struct BlockList { struct BlockList {
BlockList *next; BlockList *next;
@ -124,3 +126,5 @@ void MemoryPool::destroyAll() {
block = next; block = next;
} }
} }
} // namespace encfs

View File

@ -21,6 +21,8 @@
#ifndef _MemoryPool_incl_ #ifndef _MemoryPool_incl_
#define _MemoryPool_incl_ #define _MemoryPool_incl_
namespace encfs {
struct MemBlock { struct MemBlock {
unsigned char *data; unsigned char *data;
@ -46,4 +48,6 @@ void release(const MemBlock &el);
void destroyAll(); void destroyAll();
} }
} // namespace encfs
#endif #endif

View File

@ -23,7 +23,7 @@
#include <pthread.h> #include <pthread.h>
namespace rel { namespace encfs {
class Lock { class Lock {
public: public:
@ -50,6 +50,7 @@ inline Lock::~Lock() {
} }
inline void Lock::leave() { _mutex = 0; } inline void Lock::leave() { _mutex = 0; }
}
} // namespace encfs
#endif #endif

View File

@ -20,8 +20,7 @@
#include "NameIO.h" #include "NameIO.h"
#include <rlog/Error.h> #include "internal/easylogging++.h"
#include <rlog/rlog.h>
#include <cstring> #include <cstring>
// for static build. Need to reference the modules which are registered at // for static build. Need to reference the modules which are registered at
// run-time, to ensure that the linker doesn't optimize them away. // run-time, to ensure that the linker doesn't optimize them away.
@ -31,17 +30,18 @@
#include "BlockNameIO.h" #include "BlockNameIO.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "Error.h"
#include "Interface.h" #include "Interface.h"
#include "NullNameIO.h" #include "NullNameIO.h"
#include "StreamNameIO.h" #include "StreamNameIO.h"
using namespace std; using namespace std;
using namespace rel;
using namespace rlog;
#define REF_MODULE(TYPE) \ #define REF_MODULE(TYPE) \
if (!TYPE::Enabled()) cerr << "referenceModule: should never happen\n"; if (!TYPE::Enabled()) cerr << "referenceModule: should never happen\n";
namespace encfs {
static void AddSymbolReferences() { static void AddSymbolReferences() {
REF_MODULE(BlockNameIO) REF_MODULE(BlockNameIO)
REF_MODULE(StreamNameIO) REF_MODULE(StreamNameIO)
@ -94,11 +94,10 @@ bool NameIO::Register(const char *name, const char *description,
gNameIOMap->insert(make_pair(string(name), alg)); gNameIOMap->insert(make_pair(string(name), alg));
return true; return true;
} }
std::shared_ptr<NameIO> NameIO::New(const string &name,
shared_ptr<NameIO> NameIO::New(const string &name, const std::shared_ptr<Cipher> &cipher,
const shared_ptr<Cipher> &cipher, const CipherKey &key) {
const CipherKey &key) { std::shared_ptr<NameIO> result;
shared_ptr<NameIO> result;
if (gNameIOMap) { if (gNameIOMap) {
NameIOMap_t::const_iterator it = gNameIOMap->find(name); NameIOMap_t::const_iterator it = gNameIOMap->find(name);
if (it != gNameIOMap->end()) { if (it != gNameIOMap->end()) {
@ -108,11 +107,10 @@ shared_ptr<NameIO> NameIO::New(const string &name,
} }
return result; return result;
} }
std::shared_ptr<NameIO> NameIO::New(const Interface &iface,
shared_ptr<NameIO> NameIO::New(const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const shared_ptr<Cipher> &cipher, const CipherKey &key) {
const CipherKey &key) { std::shared_ptr<NameIO> result;
shared_ptr<NameIO> result;
if (gNameIOMap) { if (gNameIOMap) {
NameIOMap_t::const_iterator it; NameIOMap_t::const_iterator it;
NameIOMap_t::const_iterator end = gNameIOMap->end(); NameIOMap_t::const_iterator end = gNameIOMap->end();
@ -139,11 +137,10 @@ void NameIO::setReverseEncryption(bool enable) { reverseEncryption = enable; }
bool NameIO::getReverseEncryption() const { return reverseEncryption; } bool NameIO::getReverseEncryption() const { return reverseEncryption; }
std::string NameIO::recodePath(const char *path, std::string NameIO::recodePath(
int (NameIO::*_length)(int) const, const char *path, int (NameIO::*_length)(int) const,
int (NameIO::*_code)(const char *, int, int (NameIO::*_code)(const char *, int, uint64_t *, char *, int) const,
uint64_t *, char *, int) const, uint64_t *iv) const {
uint64_t *iv) const {
string output; string output;
while (*path) { while (*path) {
@ -165,7 +162,7 @@ std::string NameIO::recodePath(const char *path,
// 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)
@ -218,11 +215,13 @@ std::string NameIO::decodePath(const char *path, uint64_t *iv) const {
return getReverseEncryption() ? _encodePath(path, iv) : _decodePath(path, iv); return getReverseEncryption() ? _encodePath(path, iv) : _decodePath(path, iv);
} }
int NameIO::encodeName(const char *input, int length, char *output, int bufferLength) const { int NameIO::encodeName(const char *input, int length, char *output,
int bufferLength) const {
return encodeName(input, length, (uint64_t *)0, output, bufferLength); return encodeName(input, length, (uint64_t *)0, output, bufferLength);
} }
int NameIO::decodeName(const char *input, int length, char *output, int bufferLength) const { int NameIO::decodeName(const char *input, int length, char *output,
int bufferLength) const {
return decodeName(input, length, (uint64_t *)0, output, bufferLength); return decodeName(input, length, (uint64_t *)0, output, bufferLength);
} }
@ -290,3 +289,5 @@ int NameIO::decodeName( const char *path, int length,
_decodeName( path, length, output ); _decodeName( path, length, output );
} }
*/ */
} // namespace encfs

View File

@ -22,47 +22,49 @@
#define _NameIO_incl_ #define _NameIO_incl_
#include <inttypes.h> #include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <list> #include <list>
#include <memory> #include <memory>
#include <stdint.h>
#include <string.h>
#include <string> #include <string>
#include "CipherKey.h" #include "CipherKey.h"
#include "Interface.h" #include "Interface.h"
namespace encfs {
class Cipher; class Cipher;
class NameIO { class NameIO {
public: public:
typedef shared_ptr<NameIO>(*Constructor)(const rel::Interface &iface, typedef std::shared_ptr<NameIO> (*Constructor)(
const shared_ptr<Cipher> &cipher, const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key); const CipherKey &key);
struct Algorithm { struct Algorithm {
std::string name; std::string name;
std::string description; std::string description;
rel::Interface iface; Interface iface;
}; };
typedef std::list<Algorithm> AlgorithmList; typedef std::list<Algorithm> AlgorithmList;
static AlgorithmList GetAlgorithmList(bool includeHidden = false); static AlgorithmList GetAlgorithmList(bool includeHidden = false);
static shared_ptr<NameIO> New(const rel::Interface &iface, static std::shared_ptr<NameIO> New(const Interface &iface,
const shared_ptr<Cipher> &cipher, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key); const CipherKey &key);
static shared_ptr<NameIO> New(const std::string &name, static std::shared_ptr<NameIO> New(const std::string &name,
const shared_ptr<Cipher> &cipher, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key); const CipherKey &key);
static bool Register(const char *name, const char *description, static bool Register(const char *name, const char *description,
const rel::Interface &iface, Constructor constructor, const Interface &iface, Constructor constructor,
bool hidden = false); bool hidden = false);
NameIO(); NameIO();
virtual ~NameIO(); virtual ~NameIO();
virtual rel::Interface interface() const = 0; virtual Interface interface() const = 0;
void setChainedNameIV(bool enable); void setChainedNameIV(bool enable);
bool getChainedNameIV() const; bool getChainedNameIV() const;
@ -95,7 +97,8 @@ class NameIO {
private: private:
std::string recodePath(const char *path, int (NameIO::*codingLen)(int) const, std::string recodePath(const char *path, int (NameIO::*codingLen)(int) const,
int (NameIO::*codingFunc)(const char *, int, int (NameIO::*codingFunc)(const char *, int,
uint64_t *, char *, int) const, uint64_t *, char *, int)
const,
uint64_t *iv) const; uint64_t *iv) const;
std::string _encodePath(const char *plaintextPath, uint64_t *iv) const; std::string _encodePath(const char *plaintextPath, uint64_t *iv) const;
@ -138,4 +141,6 @@ class NameIO {
} \ } \
} while (0); } while (0);
} // namespace encfs
#endif #endif

View File

@ -28,16 +28,17 @@
#include "Range.h" #include "Range.h"
using namespace std; using namespace std;
using namespace rel;
using namespace rlog; namespace encfs {
static Interface NullInterface("nullCipher", 1, 0, 0); static Interface NullInterface("nullCipher", 1, 0, 0);
static Range NullKeyRange(0); static Range NullKeyRange(0);
static Range NullBlockRange(1, 4096, 1); static Range NullBlockRange(1, 4096, 1);
static shared_ptr<Cipher> NewNullCipher(const Interface &iface, int keyLen) { static std::shared_ptr<Cipher> NewNullCipher(const Interface &iface,
int keyLen) {
(void)keyLen; (void)keyLen;
return shared_ptr<Cipher>(new NullCipher(iface)); return std::shared_ptr<Cipher>(new NullCipher(iface));
} }
const bool HiddenCipher = true; const bool HiddenCipher = true;
@ -61,8 +62,7 @@ class NullDestructor {
NullDestructor &operator=(const NullDestructor &) { return *this; } NullDestructor &operator=(const NullDestructor &) { return *this; }
void operator()(NullKey *&) {} void operator()(NullKey *&) {}
}; };
std::shared_ptr<AbstractCipherKey> gNullKey(new NullKey(), NullDestructor());
shared_ptr<AbstractCipherKey> gNullKey(new NullKey(), NullDestructor());
NullCipher::NullCipher(const Interface &iface_) { this->iface = iface_; } NullCipher::NullCipher(const Interface &iface_) { this->iface = iface_; }
@ -97,8 +97,8 @@ void NullCipher::writeKey(const CipherKey &, unsigned char *,
const CipherKey &) {} const CipherKey &) {}
bool NullCipher::compareKey(const CipherKey &A_, const CipherKey &B_) const { bool NullCipher::compareKey(const CipherKey &A_, const CipherKey &B_) const {
shared_ptr<NullKey> A = dynamic_pointer_cast<NullKey>(A_); std::shared_ptr<NullKey> A = dynamic_pointer_cast<NullKey>(A_);
shared_ptr<NullKey> B = dynamic_pointer_cast<NullKey>(B_); std::shared_ptr<NullKey> B = dynamic_pointer_cast<NullKey>(B_);
return A.get() == B.get(); return A.get() == B.get();
} }
@ -137,3 +137,5 @@ bool NullCipher::blockDecode(unsigned char *, int, uint64_t,
} }
bool NullCipher::Enabled() { return true; } bool NullCipher::Enabled() { return true; }
} // namespace encfs

View File

@ -27,18 +27,20 @@
#include "CipherKey.h" #include "CipherKey.h"
#include "Interface.h" #include "Interface.h"
namespace encfs {
/* /*
Implements Cipher interface for a pass-through mode. May be useful for Implements Cipher interface for a pass-through mode. May be useful for
testing, but that's it. testing, but that's it.
*/ */
class NullCipher : public Cipher { class NullCipher : public Cipher {
rel::Interface iface; Interface iface;
public: public:
NullCipher(const rel::Interface &iface); NullCipher(const Interface &iface);
virtual ~NullCipher(); virtual ~NullCipher();
virtual rel::Interface interface() const; virtual Interface interface() const;
// create a new key based on a password // create a new key based on a password
virtual CipherKey newKey(const char *password, int passwdLength, virtual CipherKey newKey(const char *password, int passwdLength,
@ -80,4 +82,6 @@ class NullCipher : public Cipher {
static bool Enabled(); static bool Enabled();
}; };
} // namespace encfs
#endif #endif

View File

@ -24,15 +24,17 @@
#include <memory> #include <memory>
#include "CipherKey.h" #include "CipherKey.h"
#include "Error.h"
#include "NameIO.h" #include "NameIO.h"
namespace encfs {
class Cipher; class Cipher;
using namespace rel; static std::shared_ptr<NameIO> NewNNIO(const Interface &,
const std::shared_ptr<Cipher> &,
static shared_ptr<NameIO> NewNNIO(const Interface &, const shared_ptr<Cipher> &, const CipherKey &) {
const CipherKey &) { return std::shared_ptr<NameIO>(new NullNameIO());
return shared_ptr<NameIO>(new NullNameIO());
} }
static Interface NNIOIface("nameio/null", 1, 0, 0); static Interface NNIOIface("nameio/null", 1, 0, 0);
@ -76,3 +78,5 @@ int NullNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
} }
bool NullNameIO::Enabled() { return true; } bool NullNameIO::Enabled() { return true; }
} // namespace encfs

View File

@ -23,20 +23,20 @@
#include <stdint.h> #include <stdint.h>
#include "rlog/Error.h"
#include "rlog/rlog.h"
#include "Interface.h" #include "Interface.h"
#include "NameIO.h" #include "NameIO.h"
namespace encfs {
class NullNameIO : public NameIO { class NullNameIO : public NameIO {
public: public:
static rel::Interface CurrentInterface(); static Interface CurrentInterface();
NullNameIO(); NullNameIO();
virtual ~NullNameIO(); virtual ~NullNameIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual int maxEncodedNameLen(int plaintextNameLen) const; virtual int maxEncodedNameLen(int plaintextNameLen) const;
virtual int maxDecodedNameLen(int encodedNameLen) const; virtual int maxDecodedNameLen(int encodedNameLen) const;
@ -53,4 +53,6 @@ class NullNameIO : public NameIO {
private: private:
}; };
} // namespace encfs
#endif #endif

View File

@ -21,6 +21,8 @@
#ifndef _Range_incl_ #ifndef _Range_incl_
#define _Range_incl_ #define _Range_incl_
namespace encfs {
class Range { class Range {
int minVal; int minVal;
int maxVal; int maxVal;
@ -86,4 +88,6 @@ inline int Range::max() const { return maxVal; }
inline int Range::inc() const { return increment; } inline int Range::inc() const { return increment; }
} // namespace encfs
#endif #endif

View File

@ -21,22 +21,25 @@
#ifdef linux #ifdef linux
#define _XOPEN_SOURCE 500 // pick up pread , pwrite #define _XOPEN_SOURCE 500 // pick up pread , pwrite
#endif #endif
#include <fcntl.h> #include "internal/easylogging++.h"
#include <inttypes.h>
#include <rlog/rlog.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
#include <fcntl.h>
#include <inttypes.h>
#include <sys/stat.h>
#include <unistd.h>
#include "Error.h"
#include "FileIO.h" #include "FileIO.h"
#include "RawFileIO.h" #include "RawFileIO.h"
using namespace std; using namespace std;
static rel::Interface RawFileIO_iface("FileIO/Raw", 1, 0, 0); namespace encfs {
FileIO *NewRawFileIO(const rel::Interface &iface) { static Interface RawFileIO_iface("FileIO/Raw", 1, 0, 0);
FileIO *NewRawFileIO(const Interface &iface) {
(void)iface; (void)iface;
return new RawFileIO(); return new RawFileIO();
} }
@ -70,7 +73,7 @@ RawFileIO::~RawFileIO() {
if (_fd != -1) close(_fd); if (_fd != -1) close(_fd);
} }
rel::Interface RawFileIO::interface() const { return RawFileIO_iface; } Interface RawFileIO::interface() const { return RawFileIO_iface; }
/* /*
We shouldn't have to support all possible open flags, so untaint the flags We shouldn't have to support all possible open flags, so untaint the flags
@ -83,14 +86,13 @@ rel::Interface RawFileIO::interface() const { return RawFileIO_iface; }
*/ */
int RawFileIO::open(int flags) { int RawFileIO::open(int flags) {
bool requestWrite = ((flags & O_RDWR) || (flags & O_WRONLY)); bool requestWrite = ((flags & O_RDWR) || (flags & O_WRONLY));
VLOG(1) << "open call, requestWrite = " << requestWrite;
rDebug("open call for %s file", requestWrite ? "writable" : "read only");
int result = 0; int result = 0;
// if we have a descriptor and it is writable, or we don't need writable.. // if we have a descriptor and it is writable, or we don't need writable..
if ((fd >= 0) && (canWrite || !requestWrite)) { if ((fd >= 0) && (canWrite || !requestWrite)) {
rDebug("using existing file descriptor"); VLOG(1) << "using existing file descriptor";
result = fd; // success result = fd; // success
} else { } else {
int finalFlags = requestWrite ? O_RDWR : O_RDONLY; int finalFlags = requestWrite ? O_RDWR : O_RDONLY;
@ -103,12 +105,12 @@ int RawFileIO::open(int flags) {
int newFd = ::open(name.c_str(), finalFlags); int newFd = ::open(name.c_str(), finalFlags);
rDebug("open file with flags %i, result = %i", finalFlags, newFd); VLOG(1) << "open file with flags " << finalFlags << ", result = " << newFd;
if (newFd >= 0) { if (newFd >= 0) {
if (oldfd >= 0) { if (oldfd >= 0) {
rError("leaking FD?: oldfd = %i, fd = %i, newfd = %i", oldfd, fd, RLOG(ERROR) << "leaking FD?: oldfd = " << oldfd << ", fd = " << fd
newFd); << ", newfd = " << newFd;
} }
// the old fd might still be in use, so just keep it around for // the old fd might still be in use, so just keep it around for
@ -118,12 +120,10 @@ int RawFileIO::open(int flags) {
result = fd = newFd; result = fd = newFd;
} else { } else {
result = -errno; result = -errno;
rInfo("::open error: %s", strerror(errno)); RLOG(INFO) << "::open error: " << strerror(errno);
} }
} }
if (result < 0) rInfo("file %s open failure: %i", name.c_str(), -result);
return result; return result;
} }
@ -131,7 +131,9 @@ int RawFileIO::getAttr(struct stat *stbuf) const {
int res = lstat(name.c_str(), stbuf); int res = lstat(name.c_str(), stbuf);
int eno = errno; int eno = errno;
if (res < 0) rInfo("getAttr error on %s: %s", name.c_str(), strerror(eno)); if (res < 0) {
RLOG(INFO) << "getAttr error on " << name << ": " << strerror(eno);
}
return (res < 0) ? -eno : 0; return (res < 0) ? -eno : 0;
} }
@ -151,7 +153,7 @@ off_t RawFileIO::getSize() const {
const_cast<RawFileIO *>(this)->knownSize = true; const_cast<RawFileIO *>(this)->knownSize = true;
return fileSize; return fileSize;
} else { } else {
rError("getSize on %s failed: %s", name.c_str(), strerror(errno)); RLOG(ERROR) << "getSize on " << name << " failed: " << strerror(errno);
return -1; return -1;
} }
} else { } else {
@ -165,8 +167,8 @@ ssize_t RawFileIO::read(const IORequest &req) const {
ssize_t readSize = pread(fd, req.data, req.dataLen, req.offset); ssize_t readSize = pread(fd, req.data, req.dataLen, req.offset);
if (readSize < 0) { if (readSize < 0) {
rInfo("read failed at offset %" PRIi64 " for %i bytes: %s", req.offset, RLOG(INFO) << "read failed at offset " << req.offset << " for "
req.dataLen, strerror(errno)); << req.dataLen << " bytes: " << strerror(errno);
} }
return readSize; return readSize;
@ -186,8 +188,8 @@ bool RawFileIO::write(const IORequest &req) {
if (writeSize < 0) { if (writeSize < 0) {
knownSize = false; knownSize = false;
rInfo("write failed at offset %" PRIi64 " for %i bytes: %s", offset, RLOG(INFO) << "write failed at offset " << offset << " for " << bytes
(int)bytes, strerror(errno)); << " bytes: " << strerror(errno);
return false; return false;
} }
@ -198,8 +200,8 @@ bool RawFileIO::write(const IORequest &req) {
} }
if (bytes != 0) { if (bytes != 0) {
rError("Write error: wrote %i bytes of %i, max retries reached\n", RLOG(ERROR) << "Write error: wrote " << req.dataLen - bytes << " bytes of "
(int)(req.dataLen - bytes), req.dataLen); << req.dataLen << ", max retries reached";
knownSize = false; knownSize = false;
return false; return false;
} else { } else {
@ -225,8 +227,8 @@ int RawFileIO::truncate(off_t size) {
if (res < 0) { if (res < 0) {
int eno = errno; int eno = errno;
rInfo("truncate failed for %s (%i) size %" PRIi64 ", error %s", RLOG(INFO) << "truncate failed for " << name << " (" << fd << ") size "
name.c_str(), fd, size, strerror(eno)); << size << ", error " << strerror(eno);
res = -eno; res = -eno;
knownSize = false; knownSize = false;
} else { } else {
@ -239,3 +241,5 @@ int RawFileIO::truncate(off_t size) {
} }
bool RawFileIO::isWritable() const { return canWrite; } bool RawFileIO::isWritable() const { return canWrite; }
} // namespace encfs

View File

@ -21,11 +21,13 @@
#ifndef _RawFileIO_incl_ #ifndef _RawFileIO_incl_
#define _RawFileIO_incl_ #define _RawFileIO_incl_
#include <sys/types.h>
#include <string> #include <string>
#include <sys/types.h>
#include "Interface.h"
#include "FileIO.h" #include "FileIO.h"
#include "Interface.h"
namespace encfs {
class RawFileIO : public FileIO { class RawFileIO : public FileIO {
public: public:
@ -33,7 +35,7 @@ class RawFileIO : public FileIO {
RawFileIO(const std::string &fileName); RawFileIO(const std::string &fileName);
virtual ~RawFileIO(); virtual ~RawFileIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual void setFileName(const char *fileName); virtual void setFileName(const char *fileName);
virtual const char *getFileName() const; virtual const char *getFileName() const;
@ -61,4 +63,6 @@ class RawFileIO : public FileIO {
bool canWrite; bool canWrite;
}; };
} // namespace encfs
#endif #endif

View File

@ -18,6 +18,8 @@
* 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 "internal/easylogging++.h"
#include <cstring>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/evp.h> #include <openssl/evp.h>
@ -25,27 +27,21 @@
#include <openssl/ossl_typ.h> #include <openssl/ossl_typ.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <pthread.h> #include <pthread.h>
#include <rlog/Error.h> #include <string>
#include <rlog/rlog.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/time.h> #include <sys/time.h>
#include <cstring>
#include <string>
#include "Cipher.h" #include "Cipher.h"
#include "Error.h"
#include "Interface.h" #include "Interface.h"
#include "Mutex.h" #include "Mutex.h"
#include "Range.h" #include "Range.h"
#include "SSL_Cipher.h" #include "SSL_Cipher.h"
#include "intl/gettext.h" #include "intl/gettext.h"
namespace rlog {
class RLogChannel;
} // namespace rlog
using namespace std; using namespace std;
using namespace rel;
using namespace rlog; namespace encfs {
const int MAX_KEYLENGTH = 32; // in bytes (256 bit) const int MAX_KEYLENGTH = 32; // in bytes (256 bit)
const int MAX_IVLENGTH = 16; // 128 bit (AES block size, Blowfish has 64) const int MAX_IVLENGTH = 16; // 128 bit (AES block size, Blowfish has 64)
@ -162,7 +158,7 @@ static Interface AESInterface("ssl/aes", 3, 0, 2);
static Range BFKeyRange(128, 256, 32); static Range BFKeyRange(128, 256, 32);
static Range BFBlockRange(64, 4096, 8); static Range BFBlockRange(64, 4096, 8);
static 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);
@ -170,7 +166,7 @@ static shared_ptr<Cipher> NewBFCipher(const Interface &iface, int keyLen) {
const EVP_CIPHER *blockCipher = EVP_bf_cbc(); const EVP_CIPHER *blockCipher = EVP_bf_cbc();
const EVP_CIPHER *streamCipher = EVP_bf_cfb(); const EVP_CIPHER *streamCipher = EVP_bf_cfb();
return shared_ptr<Cipher>(new SSL_Cipher( return std::shared_ptr<Cipher>(new SSL_Cipher(
iface, BlowfishInterface, blockCipher, streamCipher, keyLen / 8)); iface, BlowfishInterface, blockCipher, streamCipher, keyLen / 8));
} }
@ -186,7 +182,8 @@ static bool BF_Cipher_registered =
static Range AESKeyRange(128, 256, 64); static Range AESKeyRange(128, 256, 64);
static Range AESBlockRange(64, 4096, 16); static Range AESBlockRange(64, 4096, 16);
static shared_ptr<Cipher> NewAESCipher(const Interface &iface, int keyLen) { static std::shared_ptr<Cipher> NewAESCipher(const Interface &iface,
int keyLen) {
if (keyLen <= 0) keyLen = 192; if (keyLen <= 0) keyLen = 192;
keyLen = AESKeyRange.closest(keyLen); keyLen = AESKeyRange.closest(keyLen);
@ -212,8 +209,8 @@ static shared_ptr<Cipher> NewAESCipher(const Interface &iface, int keyLen) {
break; break;
} }
return shared_ptr<Cipher>(new SSL_Cipher(iface, AESInterface, blockCipher, return std::shared_ptr<Cipher>(new SSL_Cipher(
streamCipher, keyLen / 8)); iface, AESInterface, blockCipher, streamCipher, keyLen / 8));
} }
static bool AES_Cipher_registered = static bool AES_Cipher_registered =
@ -275,14 +272,14 @@ SSLKey::~SSLKey() {
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
} }
inline unsigned char *KeyData(const shared_ptr<SSLKey> &key) { inline unsigned char *KeyData(const std::shared_ptr<SSLKey> &key) {
return key->buffer; return key->buffer;
} }
inline unsigned char *IVData(const shared_ptr<SSLKey> &key) { inline unsigned char *IVData(const std::shared_ptr<SSLKey> &key) {
return key->buffer + key->keySize; return key->buffer + key->keySize;
} }
void initKey(const shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher, void initKey(const std::shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher,
const EVP_CIPHER *_streamCipher, int _keySize) { const EVP_CIPHER *_streamCipher, int _keySize) {
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
@ -316,8 +313,6 @@ void initKey(const shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher,
HMAC_Init_ex(&key->mac_ctx, KeyData(key), _keySize, EVP_sha1(), 0); HMAC_Init_ex(&key->mac_ctx, KeyData(key), _keySize, EVP_sha1(), 0);
} }
static RLogChannel *CipherInfo = DEF_CHANNEL("info/cipher", Log_Info);
SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_, SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_,
const EVP_CIPHER *blockCipher, const EVP_CIPHER *blockCipher,
const EVP_CIPHER *streamCipher, int keySize_) { const EVP_CIPHER *streamCipher, int keySize_) {
@ -330,16 +325,15 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_,
rAssert(_ivLength == 8 || _ivLength == 16); rAssert(_ivLength == 8 || _ivLength == 16);
rLog(CipherInfo, "allocated cipher %s, keySize %i, ivlength %i", VLOG(1) << "allocated cipher " << iface.name() << ", keySize " << _keySize
iface.name().c_str(), _keySize, _ivLength); << ", ivlength " << _ivLength;
if ((EVP_CIPHER_key_length(_blockCipher) != (int)_keySize) && if ((EVP_CIPHER_key_length(_blockCipher) != (int)_keySize) &&
iface.current() == 1) { iface.current() == 1) {
rWarning( RLOG(WARNING) << "Running in backward compatibilty mode for 1.0 - "
"Running in backward compatibilty mode for 1.0 - \n" "key is really "
"key is really %i bits, not %i.\n" << EVP_CIPHER_key_length(_blockCipher) * 8 << " bits, not "
"Consider creating a new filesystem and moving your data.", << _keySize * 8;
EVP_CIPHER_key_length(_blockCipher) * 8, _keySize * 8);
} }
} }
@ -357,7 +351,7 @@ Interface SSL_Cipher::interface() const { return realIface; }
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength, CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
int &iterationCount, long desiredDuration, int &iterationCount, long desiredDuration,
const unsigned char *salt, int saltLen) { const unsigned char *salt, int saltLen) {
shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength)); std::shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength));
if (iterationCount == 0) { if (iterationCount == 0) {
// timed run, fills in iteration count // timed run, fills in iteration count
@ -365,7 +359,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
TimedPBKDF2(password, passwdLength, salt, saltLen, _keySize + _ivLength, TimedPBKDF2(password, passwdLength, salt, saltLen, _keySize + _ivLength,
KeyData(key), 1000 * desiredDuration); KeyData(key), 1000 * desiredDuration);
if (res <= 0) { if (res <= 0) {
rWarning("openssl error, PBKDF2 failed"); RLOG(WARNING) << "openssl error, PBKDF2 failed";
return CipherKey(); return CipherKey();
} else } else
iterationCount = res; iterationCount = res;
@ -374,7 +368,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
if (PKCS5_PBKDF2_HMAC_SHA1( if (PKCS5_PBKDF2_HMAC_SHA1(
password, passwdLength, const_cast<unsigned char *>(salt), saltLen, password, passwdLength, const_cast<unsigned char *>(salt), saltLen,
iterationCount, _keySize + _ivLength, KeyData(key)) != 1) { iterationCount, _keySize + _ivLength, KeyData(key)) != 1) {
rWarning("openssl error, PBKDF2 failed"); RLOG(WARNING) << "openssl error, PBKDF2 failed";
return CipherKey(); return CipherKey();
} }
} }
@ -385,7 +379,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
} }
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength) { CipherKey SSL_Cipher::newKey(const char *password, int passwdLength) {
shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength)); std::shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength));
int bytes = 0; int bytes = 0;
if (iface.current() > 1) { if (iface.current() > 1) {
@ -397,8 +391,8 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength) {
// the reason for moving from EVP_BytesToKey to BytesToKey function.. // the reason for moving from EVP_BytesToKey to BytesToKey function..
if (bytes != (int)_keySize) { if (bytes != (int)_keySize) {
rWarning("newKey: BytesToKey returned %i, expecting %i key bytes", bytes, RLOG(WARNING) << "newKey: BytesToKey returned " << bytes << ", expecting "
_keySize); << _keySize << " key bytes";
} }
} else { } else {
// for backward compatibility with filesystems created with 1:0 // for backward compatibility with filesystems created with 1:0
@ -429,13 +423,13 @@ CipherKey SSL_Cipher::newRandomKey() {
if (!randomize(tmpBuf, bufLen, true) || !randomize(saltBuf, saltLen, true)) if (!randomize(tmpBuf, bufLen, true) || !randomize(saltBuf, saltLen, true))
return CipherKey(); return CipherKey();
shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength)); std::shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength));
// doesn't need to be versioned, because a random key is a random key.. // doesn't need to be versioned, because a random key is a random key..
// Doesn't need to be reproducable.. // Doesn't need to be reproducable..
if (PKCS5_PBKDF2_HMAC_SHA1((char *)tmpBuf, bufLen, saltBuf, saltLen, 1000, if (PKCS5_PBKDF2_HMAC_SHA1((char *)tmpBuf, bufLen, saltBuf, saltLen, 1000,
_keySize + _ivLength, KeyData(key)) != 1) { _keySize + _ivLength, KeyData(key)) != 1) {
rWarning("openssl error, PBKDF2 failed"); RLOG(WARNING) << "openssl error, PBKDF2 failed";
return CipherKey(); return CipherKey();
} }
@ -496,25 +490,28 @@ bool SSL_Cipher::randomize(unsigned char *buf, int len,
// to avoid warnings of uninitialized data from valgrind // to avoid warnings of uninitialized data from valgrind
memset(buf, 0, len); memset(buf, 0, len);
int result; int result;
if (strongRandom) if (strongRandom) {
result = RAND_bytes(buf, len); result = RAND_bytes(buf, len);
else } else {
result = RAND_pseudo_bytes(buf, len); result = RAND_pseudo_bytes(buf, len);
}
if (result != 1) { if (result != 1) {
char errStr[120]; // specs require string at least 120 bytes long.. char errStr[120]; // specs require string at least 120 bytes long..
unsigned long errVal = 0; unsigned long errVal = 0;
if ((errVal = ERR_get_error()) != 0) if ((errVal = ERR_get_error()) != 0) {
rWarning("openssl error: %s", ERR_error_string(errVal, errStr)); RLOG(WARNING) << "openssl error: " << ERR_error_string(errVal, errStr);
}
return false; return false;
} else } 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,
const CipherKey &key, uint64_t *chainedIV) const { const CipherKey &key, uint64_t *chainedIV) const {
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) *chainedIV = tmp;
@ -524,7 +521,7 @@ uint64_t SSL_Cipher::MAC_64(const unsigned char *data, int len,
CipherKey SSL_Cipher::readKey(const unsigned char *data, CipherKey SSL_Cipher::readKey(const unsigned char *data,
const CipherKey &masterKey, bool checkKey) { const CipherKey &masterKey, bool checkKey) {
shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(masterKey); std::shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(masterKey);
rAssert(mk->keySize == _keySize); rAssert(mk->keySize == _keySize);
unsigned char tmpBuf[MAX_KEYLENGTH + MAX_IVLENGTH]; unsigned char tmpBuf[MAX_KEYLENGTH + MAX_IVLENGTH];
@ -540,13 +537,14 @@ CipherKey SSL_Cipher::readKey(const unsigned char *data,
// check for success // check for success
unsigned int checksum2 = MAC_32(tmpBuf, _keySize + _ivLength, masterKey); unsigned int checksum2 = MAC_32(tmpBuf, _keySize + _ivLength, masterKey);
if (checksum2 != checksum && checkKey) { if (checksum2 != checksum && checkKey) {
rDebug("checksum mismatch: expected %u, got %u", checksum, checksum2); VLOG(1) << "checksum mismatch: expected " << checksum << ", got "
rDebug("on decode of %i bytes", _keySize + _ivLength); << checksum2;
VLOG(1) << "on decode of " << _keySize + _ivLength << " bytes";
memset(tmpBuf, 0, sizeof(tmpBuf)); memset(tmpBuf, 0, sizeof(tmpBuf));
return CipherKey(); return CipherKey();
} }
shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength)); std::shared_ptr<SSLKey> key(new SSLKey(_keySize, _ivLength));
memcpy(key->buffer, tmpBuf, _keySize + _ivLength); memcpy(key->buffer, tmpBuf, _keySize + _ivLength);
memset(tmpBuf, 0, sizeof(tmpBuf)); memset(tmpBuf, 0, sizeof(tmpBuf));
@ -558,11 +556,11 @@ CipherKey SSL_Cipher::readKey(const unsigned char *data,
void SSL_Cipher::writeKey(const CipherKey &ckey, unsigned char *data, void SSL_Cipher::writeKey(const CipherKey &ckey, unsigned char *data,
const CipherKey &masterKey) { const CipherKey &masterKey) {
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey); std::shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize); rAssert(key->keySize == _keySize);
rAssert(key->ivLength == _ivLength); rAssert(key->ivLength == _ivLength);
shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(masterKey); std::shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(masterKey);
rAssert(mk->keySize == _keySize); rAssert(mk->keySize == _keySize);
rAssert(mk->ivLength == _ivLength); rAssert(mk->ivLength == _ivLength);
@ -586,8 +584,8 @@ void SSL_Cipher::writeKey(const CipherKey &ckey, unsigned char *data,
} }
bool SSL_Cipher::compareKey(const CipherKey &A, const CipherKey &B) const { bool SSL_Cipher::compareKey(const CipherKey &A, const CipherKey &B) const {
shared_ptr<SSLKey> key1 = dynamic_pointer_cast<SSLKey>(A); std::shared_ptr<SSLKey> key1 = dynamic_pointer_cast<SSLKey>(A);
shared_ptr<SSLKey> key2 = dynamic_pointer_cast<SSLKey>(B); std::shared_ptr<SSLKey> key2 = dynamic_pointer_cast<SSLKey>(B);
rAssert(key1->keySize == _keySize); rAssert(key1->keySize == _keySize);
rAssert(key2->keySize == _keySize); rAssert(key2->keySize == _keySize);
@ -625,7 +623,7 @@ int SSL_Cipher::cipherBlockSize() const {
* requirement for "seed" is that is must be unique. * requirement for "seed" is that is must be unique.
*/ */
void SSL_Cipher::setIVec(unsigned char *ivec, uint64_t seed, void SSL_Cipher::setIVec(unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key) const { const std::shared_ptr<SSLKey> &key) const {
if (iface.current() >= 3) { if (iface.current() >= 3) {
memcpy(ivec, IVData(key), _ivLength); memcpy(ivec, IVData(key), _ivLength);
@ -657,7 +655,7 @@ void SSL_Cipher::setIVec(unsigned char *ivec, uint64_t seed,
decrypting the file). decrypting the file).
*/ */
void SSL_Cipher::setIVec_old(unsigned char *ivec, unsigned int seed, void SSL_Cipher::setIVec_old(unsigned char *ivec, unsigned int seed,
const shared_ptr<SSLKey> &key) const { const std::shared_ptr<SSLKey> &key) const {
/* These multiplication constants chosen as they represent (non optimal) /* These multiplication constants chosen as they represent (non optimal)
Golumb rulers, the idea being to spread around the information in the Golumb rulers, the idea being to spread around the information in the
seed. seed.
@ -721,7 +719,7 @@ static void unshuffleBytes(unsigned char *buf, int size) {
bool SSL_Cipher::streamEncode(unsigned char *buf, int size, uint64_t iv64, bool SSL_Cipher::streamEncode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &ckey) const { const CipherKey &ckey) const {
rAssert(size > 0); rAssert(size > 0);
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey); std::shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize); rAssert(key->keySize == _keySize);
rAssert(key->ivLength == _ivLength); rAssert(key->ivLength == _ivLength);
@ -747,8 +745,8 @@ bool SSL_Cipher::streamEncode(unsigned char *buf, int size, uint64_t iv64,
dstLen += tmpLen; dstLen += tmpLen;
if (dstLen != size) { if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen, RLOG(ERROR) << "encoding " << size << " bytes, got back " << dstLen << " ("
tmpLen); << tmpLen << " in final_ex)";
} }
return true; return true;
@ -757,7 +755,7 @@ bool SSL_Cipher::streamEncode(unsigned char *buf, int size, uint64_t iv64,
bool SSL_Cipher::streamDecode(unsigned char *buf, int size, uint64_t iv64, bool SSL_Cipher::streamDecode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &ckey) const { const CipherKey &ckey) const {
rAssert(size > 0); rAssert(size > 0);
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey); std::shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize); rAssert(key->keySize == _keySize);
rAssert(key->ivLength == _ivLength); rAssert(key->ivLength == _ivLength);
@ -783,8 +781,8 @@ bool SSL_Cipher::streamDecode(unsigned char *buf, int size, uint64_t iv64,
dstLen += tmpLen; dstLen += tmpLen;
if (dstLen != size) { if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen, RLOG(ERROR) << "decoding " << size << " bytes, got back " << dstLen << " ("
tmpLen); << tmpLen << " in final_ex)";
} }
return true; return true;
@ -793,14 +791,14 @@ bool SSL_Cipher::streamDecode(unsigned char *buf, int size, uint64_t iv64,
bool SSL_Cipher::blockEncode(unsigned char *buf, int size, uint64_t iv64, bool SSL_Cipher::blockEncode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &ckey) const { const CipherKey &ckey) const {
rAssert(size > 0); rAssert(size > 0);
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey); std::shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize); rAssert(key->keySize == _keySize);
rAssert(key->ivLength == _ivLength); rAssert(key->ivLength == _ivLength);
// 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);
@ -815,8 +813,8 @@ bool SSL_Cipher::blockEncode(unsigned char *buf, int size, uint64_t iv64,
dstLen += tmpLen; dstLen += tmpLen;
if (dstLen != size) { if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen, RLOG(ERROR) << "encoding " << size << " bytes, got back " << dstLen << " ("
tmpLen); << tmpLen << " in final_ex)";
} }
return true; return true;
@ -825,14 +823,14 @@ bool SSL_Cipher::blockEncode(unsigned char *buf, int size, uint64_t iv64,
bool SSL_Cipher::blockDecode(unsigned char *buf, int size, uint64_t iv64, bool SSL_Cipher::blockDecode(unsigned char *buf, int size, uint64_t iv64,
const CipherKey &ckey) const { const CipherKey &ckey) const {
rAssert(size > 0); rAssert(size > 0);
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey); std::shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
rAssert(key->keySize == _keySize); rAssert(key->keySize == _keySize);
rAssert(key->ivLength == _ivLength); rAssert(key->ivLength == _ivLength);
// 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);
@ -847,11 +845,13 @@ bool SSL_Cipher::blockDecode(unsigned char *buf, int size, uint64_t iv64,
dstLen += tmpLen; dstLen += tmpLen;
if (dstLen != size) { if (dstLen != size) {
rError("decoding %i bytes, got back %i (%i in final_ex)", size, dstLen, RLOG(ERROR) << "decoding " << size << " bytes, got back " << dstLen << " ("
tmpLen); << tmpLen << " in final_ex)";
} }
return true; return true;
} }
bool SSL_Cipher::Enabled() { return true; } bool SSL_Cipher::Enabled() { return true; }
} // namespace encfs

View File

@ -21,20 +21,23 @@
#ifndef _SSL_Cipher_incl_ #ifndef _SSL_Cipher_incl_
#define _SSL_Cipher_incl_ #define _SSL_Cipher_incl_
#include <stdint.h>
#include <memory> #include <memory>
#include <stdint.h>
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "Interface.h" #include "Interface.h"
class SSLKey;
#ifndef EVP_CIPHER #ifndef EVP_CIPHER
struct evp_cipher_st; struct evp_cipher_st;
typedef struct evp_cipher_st EVP_CIPHER; typedef struct evp_cipher_st EVP_CIPHER;
#endif #endif
namespace encfs {
class SSLKey;
/* /*
Implements Cipher interface for OpenSSL's ciphers. Implements Cipher interface for OpenSSL's ciphers.
@ -74,21 +77,21 @@ typedef struct evp_cipher_st EVP_CIPHER;
simpler to reuse the encryption algorithm as is. simpler to reuse the encryption algorithm as is.
*/ */
class SSL_Cipher : public Cipher { class SSL_Cipher : public Cipher {
rel::Interface iface; Interface iface;
rel::Interface realIface; Interface realIface;
const EVP_CIPHER *_blockCipher; const EVP_CIPHER *_blockCipher;
const EVP_CIPHER *_streamCipher; const EVP_CIPHER *_streamCipher;
unsigned int _keySize; // in bytes unsigned int _keySize; // in bytes
unsigned int _ivLength; unsigned int _ivLength;
public: public:
SSL_Cipher(const rel::Interface &iface, const rel::Interface &realIface, SSL_Cipher(const Interface &iface, const Interface &realIface,
const EVP_CIPHER *blockCipher, const EVP_CIPHER *streamCipher, const EVP_CIPHER *blockCipher, const EVP_CIPHER *streamCipher,
int keyLength); int keyLength);
virtual ~SSL_Cipher(); virtual ~SSL_Cipher();
// returns the real interface, not the one we're emulating (if any).. // returns the real interface, not the one we're emulating (if any)..
virtual rel::Interface interface() const; virtual Interface interface() const;
// create a new key based on a password // create a new key based on a password
virtual CipherKey newKey(const char *password, int passwdLength, virtual CipherKey newKey(const char *password, int passwdLength,
@ -140,11 +143,13 @@ class SSL_Cipher : public Cipher {
private: private:
void setIVec(unsigned char *ivec, uint64_t seed, void setIVec(unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key) const; const std::shared_ptr<SSLKey> &key) const;
// deprecated - for backward compatibility // deprecated - for backward compatibility
void setIVec_old(unsigned char *ivec, unsigned int seed, void setIVec_old(unsigned char *ivec, unsigned int seed,
const shared_ptr<SSLKey> &key) const; const std::shared_ptr<SSLKey> &key) const;
}; };
} // namespace encfs
#endif #endif

View File

@ -20,23 +20,24 @@
#include "StreamNameIO.h" #include "StreamNameIO.h"
#include <rlog/Error.h> #include "internal/easylogging++.h"
#include <rlog/rlog.h>
#include <cstring> #include <cstring>
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "Error.h"
#include "NameIO.h" #include "NameIO.h"
#include "base64.h" #include "base64.h"
#include "intl/gettext.h" #include "intl/gettext.h"
using namespace rel;
using namespace std; using namespace std;
static shared_ptr<NameIO> NewStreamNameIO(const Interface &iface, namespace encfs {
const shared_ptr<Cipher> &cipher,
const CipherKey &key) { static std::shared_ptr<NameIO> NewStreamNameIO(
return shared_ptr<NameIO>(new StreamNameIO(iface, cipher, key)); const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key) {
return std::shared_ptr<NameIO>(new StreamNameIO(iface, cipher, key));
} }
static bool StreamIO_registered = NameIO::Register( static bool StreamIO_registered = NameIO::Register(
@ -70,8 +71,8 @@ Interface StreamNameIO::CurrentInterface() {
return Interface("nameio/stream", 2, 1, 2); return Interface("nameio/stream", 2, 1, 2);
} }
StreamNameIO::StreamNameIO(const rel::Interface &iface, StreamNameIO::StreamNameIO(const Interface &iface,
const shared_ptr<Cipher> &cipher, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key) const CipherKey &key)
: _interface(iface.current()), _cipher(cipher), _key(key) {} : _interface(iface.current()), _cipher(cipher), _key(key) {}
@ -90,7 +91,8 @@ int StreamNameIO::maxDecodedNameLen(int encodedStreamLen) const {
} }
int StreamNameIO::encodeName(const char *plaintextName, int length, int StreamNameIO::encodeName(const char *plaintextName, int length,
uint64_t *iv, char *encodedName, int bufferLength) const { uint64_t *iv, char *encodedName,
int bufferLength) const {
uint64_t tmpIV = 0; uint64_t tmpIV = 0;
if (iv && _interface >= 2) tmpIV = *iv; if (iv && _interface >= 2) tmpIV = *iv;
@ -133,7 +135,7 @@ 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);
@ -172,12 +174,14 @@ int StreamNameIO::decodeName(const char *encodedName, int length, uint64_t *iv,
BUFFER_RESET(tmpBuf); BUFFER_RESET(tmpBuf);
if (mac2 != mac) { if (mac2 != mac) {
rDebug("checksum mismatch: expected %u, got %u", mac, mac2); VLOG(1) << "checksum mismatch: expected " << mac << ", got " << mac2;
rDebug("on decode of %i bytes", decodedStreamLen); VLOG(1) << "on decode of " << decodedStreamLen << " bytes";
throw ERROR("checksum mismatch in filename decode"); throw Error("checksum mismatch in filename decode");
} }
return decodedStreamLen; return decodedStreamLen;
} }
bool StreamNameIO::Enabled() { return true; } bool StreamNameIO::Enabled() { return true; }
} // namespace encfs

View File

@ -21,24 +21,26 @@
#ifndef _StreamNameIO_incl_ #ifndef _StreamNameIO_incl_
#define _StreamNameIO_incl_ #define _StreamNameIO_incl_
#include <stdint.h>
#include <memory> #include <memory>
#include <stdint.h>
#include "CipherKey.h" #include "CipherKey.h"
#include "Interface.h" #include "Interface.h"
#include "NameIO.h" #include "NameIO.h"
namespace encfs {
class Cipher; class Cipher;
class StreamNameIO : public NameIO { class StreamNameIO : public NameIO {
public: public:
static rel::Interface CurrentInterface(); static Interface CurrentInterface();
StreamNameIO(const rel::Interface &iface, const shared_ptr<Cipher> &cipher, StreamNameIO(const Interface &iface, const std::shared_ptr<Cipher> &cipher,
const CipherKey &key); const CipherKey &key);
virtual ~StreamNameIO(); virtual ~StreamNameIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual int maxEncodedNameLen(int plaintextNameLen) const; virtual int maxEncodedNameLen(int plaintextNameLen) const;
virtual int maxDecodedNameLen(int encodedNameLen) const; virtual int maxDecodedNameLen(int encodedNameLen) const;
@ -54,8 +56,10 @@ class StreamNameIO : public NameIO {
private: private:
int _interface; int _interface;
shared_ptr<Cipher> _cipher; std::shared_ptr<Cipher> _cipher;
CipherKey _key; CipherKey _key;
}; };
} // namespace encfs
#endif #endif

View File

@ -20,23 +20,17 @@
#include "XmlReader.h" #include "XmlReader.h"
#include <sys/types.h> #include <algorithm> // for remove_if
#include <sys/stat.h> #include <cstring> // for NULL
#include <fcntl.h> #include <memory> // for shared_ptr
#include <unistd.h>
#include <algorithm> #include <tinyxml2.h> // for XMLElement, XMLNode, XMLDocument (ptr only)
#include <cstring>
#include <map>
#include <tinyxml2.h> #include "Error.h"
#include <rlog/Error.h>
#include <rlog/rlog.h>
#include "base64.h"
#include "Interface.h" #include "Interface.h"
#include "shared_ptr.h" #include "base64.h"
namespace encfs {
XmlValue::~XmlValue() {} XmlValue::~XmlValue() {}
@ -44,7 +38,7 @@ XmlValuePtr XmlValue::operator[](const char *path) const { return find(path); }
XmlValuePtr XmlValue::find(const char *path) const { XmlValuePtr XmlValue::find(const char *path) const {
// Shouldn't get here. // Shouldn't get here.
rError("in XmlValue::find(%s)", path); RLOG(ERROR) << "in XmlValue::find for path " << path;
return XmlValuePtr(); return XmlValuePtr();
} }
@ -88,7 +82,8 @@ bool XmlValue::read(const char *path, bool *out) const {
return true; return true;
} }
bool XmlValue::readB64(const char *path, unsigned char *data, int length) const { bool XmlValue::readB64(const char *path, unsigned char *data,
int length) const {
XmlValuePtr value = find(path); XmlValuePtr value = find(path);
if (!value) return false; if (!value) return false;
@ -98,25 +93,26 @@ bool XmlValue::readB64(const char *path, unsigned char *data, int length) const
int decodedSize = B64ToB256Bytes(s.size()); int decodedSize = B64ToB256Bytes(s.size());
if (decodedSize != length) { if (decodedSize != length) {
rError("decoding bytes len %d, expecting output len %d, got %d", s.size(), RLOG(ERROR) << "decoding bytes len " << s.size()
length, decodedSize); << ", expecting output len " << length << ", got "
<< decodedSize;
return false; return false;
} }
if (!B64StandardDecode(data, (unsigned char *)s.data(), s.size())) { if (!B64StandardDecode(data, (unsigned char *)s.data(), s.size())) {
rError("B64 decode failure on \"%s\"", s.c_str()); RLOG(ERROR) << "B64 decode failure on \"" << s << "\"";
return false; return false;
} }
return true; return true;
} }
bool XmlValue::read(const char *path, rel::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()) &&
node->read("minor", &out->revision()); node->read("minor", &out->revision());
return ok; return ok;
} }
@ -161,7 +157,7 @@ class XmlNode : virtual public XmlValue {
}; };
struct XmlReader::XmlReaderData { struct XmlReader::XmlReaderData {
shared_ptr<tinyxml2::XMLDocument> doc; std::shared_ptr<tinyxml2::XMLDocument> doc;
}; };
XmlReader::XmlReader() : pd(new XmlReaderData()) {} XmlReader::XmlReader() : pd(new XmlReaderData()) {}
@ -178,15 +174,17 @@ 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 == NULL) {
rError("Xml node %s not found", name); RLOG(ERROR) << "Xml node " << name << " not found";
return XmlValuePtr(new XmlValue()); return XmlValuePtr(new XmlValue());
} }
tinyxml2::XMLElement *element = node->ToElement(); tinyxml2::XMLElement *element = node->ToElement();
if (element == NULL) { if (element == NULL) {
rError("Xml node %s not element", name); RLOG(ERROR) << "Xml node " << name << " not element";
return XmlValuePtr(new XmlValue()); return XmlValuePtr(new XmlValue());
} }
return XmlValuePtr(new XmlNode(element)); return XmlValuePtr(new XmlNode(element));
} }
} // namespace encfs

View File

@ -21,12 +21,15 @@
#ifndef _XmlReader_incl_ #ifndef _XmlReader_incl_
#define _XmlReader_incl_ #define _XmlReader_incl_
#include <memory>
#include <string> #include <string>
#include "Interface.h" #include "Interface.h"
#include "shared_ptr.h"
namespace encfs {
class XmlValue; class XmlValue;
typedef shared_ptr<XmlValue> XmlValuePtr; typedef std::shared_ptr<XmlValue> XmlValuePtr;
class XmlValue { class XmlValue {
std::string value; std::string value;
@ -49,7 +52,7 @@ class XmlValue {
bool read(const char *path, double *out) const; bool read(const char *path, double *out) const;
bool read(const char *path, bool *out) const; bool read(const char *path, bool *out) const;
bool read(const char *path, rel::Interface *out) const; bool read(const char *path, Interface *out) const;
protected: protected:
virtual XmlValuePtr find(const char *name) const; virtual XmlValuePtr find(const char *name) const;
@ -66,7 +69,9 @@ class XmlReader {
private: private:
struct XmlReaderData; struct XmlReaderData;
shared_ptr<XmlReaderData> pd; std::shared_ptr<XmlReaderData> pd;
}; };
} // namespace encfs
#endif #endif

View File

@ -27,12 +27,10 @@
/* Specification. */ /* Specification. */
#include "autosprintf.h" #include "autosprintf.h"
#include <stdarg.h> #include <stdarg.h> // for va_list
#include <stdarg.h> #include <stdio.h> // for NULL, vasprintf
//#include "lib-asprintf.h" #include <stdlib.h> // for free
#include <stdio.h> #include <string.h> // for strdup
#include <stdlib.h>
#include <string.h>
namespace gnu { namespace gnu {

View File

@ -32,8 +32,8 @@
#endif #endif
#endif #endif
#include <string>
#include <iostream> #include <iostream>
#include <string>
namespace gnu { namespace gnu {
/* A temporary object, usually allocated on the stack, representing /* A temporary object, usually allocated on the stack, representing

View File

@ -20,10 +20,11 @@
#include "base64.h" #include "base64.h"
#include <cstdlib> #include <ctype.h> // for toupper
#include <ctype.h>
#include <rlog/rlog.h> #include "Error.h"
namespace encfs {
// change between two powers of two, stored as the low bits of the bytes in the // change between two powers of two, stored as the low bits of the bytes in the
// arrays. // arrays.
@ -202,7 +203,7 @@ bool B64StandardDecode(unsigned char *out, const unsigned char *in, int inLen) {
while (in < end) { while (in < end) {
unsigned char v = *in++; unsigned char v = *in++;
if (v > 'z') { if (v > 'z') {
rError("Invalid character: %d", (unsigned int)v); RLOG(ERROR) << "Invalid character: " << (unsigned int)v;
return false; return false;
} }
unsigned char c = d[v]; unsigned char c = d[v];
@ -211,7 +212,7 @@ bool B64StandardDecode(unsigned char *out, const unsigned char *in, int inLen) {
case WHITESPACE: case WHITESPACE:
continue; /* skip whitespace */ continue; /* skip whitespace */
case INVALID: case INVALID:
rError("Invalid character: %d", (unsigned int)v); RLOG(ERROR) << "Invalid character: " << (unsigned int)v;
return false; /* invalid input, return error */ return false; /* invalid input, return error */
case EQUALS: /* pad character, end of data */ case EQUALS: /* pad character, end of data */
in = end; in = end;
@ -276,3 +277,5 @@ std::string B64StandardEncode(std::vector<unsigned char> inputBuffer) {
} }
return encodedString; return encodedString;
} }
} // namespace encfs

View File

@ -21,8 +21,10 @@
#ifndef _base64_incl_ #ifndef _base64_incl_
#define _base64_incl_ #define _base64_incl_
#include <string> #include <string> // for string
#include <vector> #include <vector> // for vector
namespace encfs {
inline int B64ToB256Bytes(int numB64Bytes) { inline int B64ToB256Bytes(int numB64Bytes) {
return (numB64Bytes * 6) / 8; // round down return (numB64Bytes * 6) / 8; // round down
@ -68,8 +70,11 @@ void AsciiToB32(unsigned char *out, const unsigned char *in, int length);
// Decode standard B64 into the output array. // Decode standard B64 into the output array.
// Used only to decode legacy Boost XML serialized config format. // Used only to decode legacy Boost XML serialized config format.
// The output size must be at least B64ToB256Bytes(inputLen). // The output size must be at least B64ToB256Bytes(inputLen).
bool B64StandardDecode(unsigned char *out, const unsigned char *in, int inputLen); bool B64StandardDecode(unsigned char *out, const unsigned char *in,
int inputLen);
std::string B64StandardEncode(std::vector<unsigned char> input); std::string B64StandardEncode(std::vector<unsigned char> input);
} // namespace encfs
#endif #endif

View File

@ -17,8 +17,13 @@
#include "encfs.h" #include "encfs.h"
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h> #include <inttypes.h>
#include <memory>
#include <stdint.h> #include <stdint.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/statvfs.h> #include <sys/statvfs.h>
@ -26,11 +31,6 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <utime.h> #include <utime.h>
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <memory>
#ifdef linux #ifdef linux
#include <sys/fsuid.h> #include <sys/fsuid.h>
#endif #endif
@ -41,25 +41,18 @@
#include <attr/xattr.h> #include <attr/xattr.h>
#endif #endif
#include <rlog/Error.h> #include "internal/easylogging++.h"
#include <rlog/rlog.h>
#include <functional> #include <functional>
#include <string> #include <string>
#include <vector> #include <vector>
#include "Context.h" #include "Context.h"
#include "DirNode.h" #include "DirNode.h"
#include "Error.h"
#include "FileNode.h" #include "FileNode.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "fuse.h" #include "fuse.h"
namespace rel {
class Lock;
} // namespace rel
namespace rlog {
class RLogChannel;
} // namespace rlog
#ifndef MIN #ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif #endif
@ -68,12 +61,10 @@ class RLogChannel;
using namespace std; using namespace std;
using namespace std::placeholders; using namespace std::placeholders;
using namespace rlog;
using rel::Lock;
#define GET_FN(ctx, finfo) ctx->getNode((void *)(uintptr_t) finfo->fh) namespace encfs {
static RLogChannel *Info = DEF_CHANNEL("info", Log_Info); #define GET_FN(ctx, finfo) ctx->getNode((void *)(uintptr_t)finfo->fh)
static EncFS_Context *context() { static EncFS_Context *context() {
return (EncFS_Context *)fuse_get_context()->private_data; return (EncFS_Context *)fuse_get_context()->private_data;
@ -97,24 +88,25 @@ static int withCipherPath(const char *opName, const char *path,
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
int res = -EIO; int res = -EIO;
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);
rLog(Info, "%s %s", opName, cyName.c_str()); VLOG(1) << "op: " << opName << " : " << cyName;
res = op(ctx, cyName); res = op(ctx, cyName);
if (res == -1) { if (res == -1) {
int eno = errno; int eno = errno;
rInfo("%s error: %s", opName, strerror(eno)); VLOG(1) << "op: " << opName << " error: " << strerror(eno);
res = -eno; res = -eno;
} else if (!passReturnCode) } else if (!passReturnCode) {
res = ESUCCESS; res = ESUCCESS;
} catch (rlog::Error &err) { }
rError("withCipherPath: error caught in %s: %s", opName, err.message()); } catch (encfs::Error &err) {
err.log(_RLWarningChannel); RLOG(ERROR) << "withCipherPath: error caught in " << opName << ": "
<< err.what();
} }
return res; return res;
} }
@ -126,11 +118,11 @@ static int withFileNode(const char *opName, const char *path,
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
int res = -EIO; int res = -EIO;
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 {
shared_ptr<FileNode> fnode; std::shared_ptr<FileNode> fnode;
if (fi != NULL) if (fi != NULL)
fnode = GET_FN(ctx, fi); fnode = GET_FN(ctx, fi);
@ -138,29 +130,28 @@ static int withFileNode(const char *opName, const char *path,
fnode = FSRoot->lookupNode(path, opName); fnode = FSRoot->lookupNode(path, opName);
rAssert(fnode.get() != NULL); rAssert(fnode.get() != NULL);
rLog(Info, "%s %s", opName, fnode->cipherName()); VLOG(1) << "op: " << opName << " : " << fnode->cipherName();
// check that we're not recursing into the mount point itself // check that we're not recursing into the mount point itself
if (FSRoot->touchesMountpoint(fnode->cipherName())) { if (FSRoot->touchesMountpoint(fnode->cipherName())) {
rInfo("%s error: Tried to touch mountpoint: '%s'", VLOG(1) << "op: " << opName << " error: Tried to touch mountpoint: '"
opName, fnode->cipherName()); << fnode->cipherName() << "'";
return res; // still -EIO return res; // still -EIO
} }
res = op(fnode.get()); res = op(fnode.get());
if (res < 0) rInfo("%s error: %s", opName, strerror(-res)); LOG_IF(res < 0, INFO) << "op: " << opName << " error: " << strerror(-res);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("withFileNode: error caught in %s: %s", opName, err.message()); RLOG(ERROR) << "withFileNode: error caught in " << opName << ": "
err.log(_RLWarningChannel); << err.what();
} }
return res; return res;
} }
/* /*
The rLog messages below always prints out encrypted filenames, not The log messages below always print encrypted filenames, not
plaintext. The reason is so that it isn't possible to leak information plaintext. This avoids possibly leaking information to log files.
about the encrypted data through rlog interfaces.
The purpose of this layer of code is to take the FUSE request and dispatch The purpose of this layer of code is to take the FUSE request and dispatch
to the internal interfaces. Any marshaling of arguments and return types to the internal interfaces. Any marshaling of arguments and return types
@ -171,7 +162,7 @@ int _do_getattr(FileNode *fnode, struct stat *stbuf) {
int res = fnode->getAttr(stbuf); int res = fnode->getAttr(stbuf);
if (res == ESUCCESS && S_ISLNK(stbuf->st_mode)) { if (res == ESUCCESS && S_ISLNK(stbuf->st_mode)) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
shared_ptr<DirNode> FSRoot = ctx->getRoot(&res); std::shared_ptr<DirNode> FSRoot = ctx->getRoot(&res);
if (FSRoot) { if (FSRoot) {
// determine plaintext link size.. Easiest to read and decrypt.. // determine plaintext link size.. Easiest to read and decrypt..
std::vector<char> buf(stbuf->st_size + 1, '\0'); std::vector<char> buf(stbuf->st_size + 1, '\0');
@ -185,8 +176,9 @@ int _do_getattr(FileNode *fnode, struct stat *stbuf) {
stbuf->st_size = FSRoot->plainPath(buf.data()).length(); stbuf->st_size = FSRoot->plainPath(buf.data()).length();
res = ESUCCESS; res = ESUCCESS;
} else } else {
res = -errno; res = -errno;
}
} }
} }
@ -206,14 +198,14 @@ int encfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
int res = ESUCCESS; int res = ESUCCESS;
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 {
DirTraverse dt = FSRoot->openDir(path); DirTraverse dt = FSRoot->openDir(path);
rLog(Info, "getdir on %s", FSRoot->cipherPath(path).c_str()); VLOG(1) << "getdir on " << FSRoot->cipherPath(path);
if (dt.valid()) { if (dt.valid()) {
int fileType = 0; int fileType = 0;
@ -228,13 +220,12 @@ int encfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) {
name = dt.nextPlaintextName(&fileType, &inode); name = dt.nextPlaintextName(&fileType, &inode);
} }
} else { } else {
rInfo("getdir request invalid, path: '%s'", path); VLOG(1) << "getdir request invalid, path: '" << path << "'";
} }
return res; return res;
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("Error caught in getdir"); RLOG(ERROR) << "Error caught in getdir";
err.log(_RLWarningChannel);
return -EIO; return -EIO;
} }
} }
@ -245,14 +236,14 @@ int encfs_mknod(const char *path, mode_t mode, dev_t rdev) {
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) return -EROFS;
int res = -EIO; int res = -EIO;
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 {
shared_ptr<FileNode> fnode = FSRoot->lookupNode(path, "mknod"); std::shared_ptr<FileNode> fnode = FSRoot->lookupNode(path, "mknod");
rLog(Info, "mknod on %s, mode %i, dev %" PRIi64, fnode->cipherName(), mode, VLOG(1) << "mknod on " << fnode->cipherName() << ", mode " << mode
(int64_t)rdev); << ", dev " << rdev;
uid_t uid = 0; uid_t uid = 0;
gid_t gid = 0; gid_t gid = 0;
@ -266,16 +257,16 @@ int encfs_mknod(const char *path, mode_t mode, dev_t rdev) {
if (ctx->publicFilesystem && -res == EACCES) { if (ctx->publicFilesystem && -res == EACCES) {
// try again using the parent dir's group // try again using the parent dir's group
string parent = fnode->plaintextParent(); string parent = fnode->plaintextParent();
rInfo("trying public filesystem workaround for %s", parent.c_str()); VLOG(1) << "trying public filesystem workaround for " << parent;
shared_ptr<FileNode> dnode = FSRoot->lookupNode(parent.c_str(), "mknod"); std::shared_ptr<FileNode> dnode =
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 (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in mknod"); RLOG(ERROR) << "error caught in mknod: " << err.what();
err.log(_RLWarningChannel);
} }
return res; return res;
} }
@ -287,7 +278,7 @@ int encfs_mkdir(const char *path, mode_t mode) {
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) return -EROFS;
int res = -EIO; int res = -EIO;
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 {
@ -302,15 +293,15 @@ int encfs_mkdir(const char *path, mode_t mode) {
if (ctx->publicFilesystem && -res == EACCES) { if (ctx->publicFilesystem && -res == EACCES) {
// try again using the parent dir's group // try again using the parent dir's group
string parent = parentDirectory(path); string parent = parentDirectory(path);
shared_ptr<FileNode> dnode = FSRoot->lookupNode(parent.c_str(), "mkdir"); std::shared_ptr<FileNode> dnode =
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 (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in mkdir"); RLOG(ERROR) << "error caught in mkdir: " << err.what();
err.log(_RLWarningChannel);
} }
return res; return res;
} }
@ -321,16 +312,15 @@ int encfs_unlink(const char *path) {
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) return -EROFS;
int res = -EIO; int res = -EIO;
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
// conditions // conditions
res = FSRoot->unlink(path); res = FSRoot->unlink(path);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in unlink"); RLOG(ERROR) << "error caught in unlink: " << err.what();
err.log(_RLWarningChannel);
} }
return res; return res;
} }
@ -347,7 +337,7 @@ int encfs_rmdir(const char *path) {
int _do_readlink(EncFS_Context *ctx, const string &cyName, char *buf, int _do_readlink(EncFS_Context *ctx, const string &cyName, char *buf,
size_t size) { size_t size) {
int res = ESUCCESS; int res = ESUCCESS;
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);
@ -359,6 +349,7 @@ int _do_readlink(EncFS_Context *ctx, const string &cyName, char *buf,
try { try {
decodedName = FSRoot->plainPath(buf); decodedName = FSRoot->plainPath(buf);
} catch (...) { } catch (...) {
VLOG(1) << "caught error decoding path";
} }
if (!decodedName.empty()) { if (!decodedName.empty()) {
@ -367,7 +358,7 @@ int _do_readlink(EncFS_Context *ctx, const string &cyName, char *buf,
return ESUCCESS; return ESUCCESS;
} else { } else {
rWarning("Error decoding link"); RLOG(WARNING) << "Error decoding link";
return -1; return -1;
} }
} }
@ -386,7 +377,7 @@ int encfs_symlink(const char *to, const char *from) {
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) return -EROFS;
int res = -EIO; int res = -EIO;
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 {
@ -394,7 +385,7 @@ int encfs_symlink(const char *to, const char *from) {
// allow fully qualified names in symbolic links. // allow fully qualified names in symbolic links.
string toCName = FSRoot->relativeCipherPath(to); string toCName = FSRoot->relativeCipherPath(to);
rLog(Info, "symlink %s -> %s", fromCName.c_str(), toCName.c_str()); VLOG(1) << "symlink " << fromCName << " -> " << toCName;
// use setfsuid / setfsgid so that the new link will be owned by the // use setfsuid / setfsgid so that the new link will be owned by the
// uid/gid provided by the fuse_context. // uid/gid provided by the fuse_context.
@ -413,9 +404,8 @@ int encfs_symlink(const char *to, const char *from) {
res = -errno; res = -errno;
else else
res = ESUCCESS; res = ESUCCESS;
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in symlink"); RLOG(ERROR) << "error caught in symlink: " << err.what();
err.log(_RLWarningChannel);
} }
return res; return res;
} }
@ -426,14 +416,13 @@ int encfs_link(const char *from, const char *to) {
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) return -EROFS;
int res = -EIO; int res = -EIO;
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);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in link"); RLOG(ERROR) << "error caught in link: " << err.what();
err.log(_RLWarningChannel);
} }
return res; return res;
} }
@ -444,14 +433,13 @@ int encfs_rename(const char *from, const char *to) {
if (isReadOnly(ctx)) return -EROFS; if (isReadOnly(ctx)) return -EROFS;
int res = -EIO; int res = -EIO;
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);
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in rename"); RLOG(ERROR) << "error caught in rename: " << err.what();
err.log(_RLWarningChannel);
} }
return res; return res;
} }
@ -521,25 +509,24 @@ int encfs_open(const char *path, struct fuse_file_info *file) {
return -EROFS; return -EROFS;
int res = -EIO; int res = -EIO;
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 {
shared_ptr<FileNode> fnode = std::shared_ptr<FileNode> fnode =
FSRoot->openNode(path, "open", file->flags, &res); FSRoot->openNode(path, "open", file->flags, &res);
if (fnode) { if (fnode) {
rLog(Info, "encfs_open for %s, flags %i", fnode->cipherName(), VLOG(1) << "encfs_open for " << fnode->cipherName() << ", flags "
file->flags); << file->flags;
if (res >= 0) { if (res >= 0) {
file->fh = (uintptr_t)ctx->putNode(path, fnode); file->fh = (uintptr_t)ctx->putNode(path, fnode);
res = ESUCCESS; res = ESUCCESS;
} }
} }
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in open"); RLOG(ERROR) << "error caught in open: " << err.what();
err.log(_RLWarningChannel);
} }
return res; return res;
@ -574,11 +561,10 @@ int encfs_release(const char *path, struct fuse_file_info *finfo) {
EncFS_Context *ctx = context(); EncFS_Context *ctx = context();
try { try {
ctx->eraseNode(path, (void *)(uintptr_t) finfo->fh); ctx->eraseNode(path, (void *)(uintptr_t)finfo->fh);
return ESUCCESS; return ESUCCESS;
} catch (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in release"); RLOG(ERROR) << "error caught in release: " << err.what();
err.log(_RLWarningChannel);
return -EIO; return -EIO;
} }
} }
@ -626,16 +612,15 @@ int encfs_statfs(const char *path, struct statvfs *st) {
rAssert(st != NULL); rAssert(st != NULL);
string cyName = ctx->rootCipherDir; string cyName = ctx->rootCipherDir;
rLog(Info, "doing statfs of %s", cyName.c_str()); VLOG(1) << "doing statfs of " << cyName;
res = statvfs(cyName.c_str(), st); res = statvfs(cyName.c_str(), st);
if (!res) { if (!res) {
// 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 (rlog::Error &err) { } catch (encfs::Error &err) {
rError("error caught in statfs"); RLOG(ERROR) << "error caught in statfs: " << err.what();
err.log(_RLWarningChannel);
} }
return res; return res;
} }
@ -726,4 +711,6 @@ int encfs_removexattr(const char *path, const char *name) {
bind(_do_removexattr, _1, _2, name)); bind(_do_removexattr, _1, _2, name));
} }
} // namespace encfs
#endif // HAVE_XATTR #endif // HAVE_XATTR

View File

@ -21,13 +21,15 @@
#ifndef _encfs_incl_ #ifndef _encfs_incl_
#define _encfs_incl_ #define _encfs_incl_
#include "internal/easylogging++.h"
#include <fuse.h> #include <fuse.h>
#include <rlog/rlog.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "config.h" #include "config.h"
namespace encfs {
#if defined(HAVE_SYS_XATTR_H) | defined(HAVE_ATTR_XATTR_H) #if defined(HAVE_SYS_XATTR_H) | defined(HAVE_ATTR_XATTR_H)
#define HAVE_XATTR #define HAVE_XATTR
#endif #endif
@ -39,8 +41,7 @@ static __inline int setfsuid(uid_t uid) {
uid_t olduid = geteuid(); uid_t olduid = geteuid();
if (seteuid(uid) != 0) { if (seteuid(uid) != 0) {
// ignore error. VLOG(1) << "seteuid error: " << errno;
rDebug("seteuid error: %i", errno);
} }
return olduid; return olduid;
@ -50,8 +51,7 @@ static __inline int setfsgid(gid_t gid) {
gid_t oldgid = getegid(); gid_t oldgid = getegid();
if (setegid(gid) != 0) { if (setegid(gid) != 0) {
// ignore error. VLOG(1) << "setfsgid error: " << errno;
rDebug("setfsgid error: %i", errno);
} }
return oldgid; return oldgid;
@ -105,4 +105,6 @@ int encfs_removexattr(const char *path, const char *name);
int encfs_utimens(const char *path, const struct timespec ts[2]); int encfs_utimens(const char *path, const struct timespec ts[2]);
} // namespace encfs
#endif #endif

View File

@ -17,19 +17,16 @@
#include <fcntl.h> #include <fcntl.h>
#include <getopt.h> #include <getopt.h>
#include <iostream>
#include <limits.h> #include <limits.h>
#include <rlog/RLogChannel.h> #include <memory>
#include <rlog/StdioNode.h>
#include <rlog/rlog.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <string>
#include <sys/stat.h> #include <sys/stat.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector> #include <vector>
#define NO_DES #define NO_DES
@ -38,6 +35,7 @@
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "DirNode.h" #include "DirNode.h"
#include "Error.h"
#include "FSConfig.h" #include "FSConfig.h"
#include "FileNode.h" #include "FileNode.h"
#include "FileUtils.h" #include "FileUtils.h"
@ -51,9 +49,11 @@
#define PATH_MAX 4096 #define PATH_MAX 4096
#endif #endif
using namespace rlog;
using namespace std; using namespace std;
using gnu::autosprintf; using gnu::autosprintf;
using namespace encfs;
INITIALIZE_EASYLOGGINGPP
static int showInfo(int argc, char **argv); static int showInfo(int argc, char **argv);
static int showVersion(int argc, char **argv); static int showVersion(int argc, char **argv);
@ -76,47 +76,45 @@ struct CommandOpts {
const char *argStr; const char *argStr;
const char *usageStr; const char *usageStr;
} commands[] = { } commands[] = {
{"info", 1, 1, showInfo, "(root dir)", {"info", 1, 1, showInfo, "(root dir)",
// xgroup(usage) // xgroup(usage)
gettext_noop(" -- show information (Default command)")}, gettext_noop(" -- show information (Default command)")},
{"showKey", 1, 1, cmd_showKey, "(root dir)", {"showKey", 1, 1, cmd_showKey, "(root dir)",
// xgroup(usage) // xgroup(usage)
gettext_noop(" -- show key")}, gettext_noop(" -- show key")},
{"passwd", 1, 1, chpasswd, "(root dir)", {"passwd", 1, 1, chpasswd, "(root dir)",
// xgroup(usage) // xgroup(usage)
gettext_noop(" -- change password for volume")}, gettext_noop(" -- change password for volume")},
{"autopasswd", 1, 1, chpasswdAutomaticly, "(root dir)", {"autopasswd", 1, 1, chpasswdAutomaticly, "(root dir)",
// xgroup(usage) // xgroup(usage)
gettext_noop( gettext_noop(" -- change password for volume, taking password"
" -- change password for volume, taking password" " from standard input.\n\tNo prompts are issued.")},
" from standard input.\n\tNo prompts are issued.")}, {"autocheckpasswd", 1, 1, ckpasswdAutomaticly, "(root dir)",
{"autocheckpasswd", 1, 1, ckpasswdAutomaticly, "(root dir)", // xgroup(usage)
// xgroup(usage) gettext_noop(" -- check password for volume, taking password"
gettext_noop( " from standard input.\n\tNo prompts are issued.")},
" -- check password for volume, taking password" {"ls", 1, 2, cmd_ls, 0, 0},
" from standard input.\n\tNo prompts are issued.")}, {"showcruft", 1, 1, cmd_showcruft, "(root dir)",
{"ls", 1, 2, cmd_ls, 0, 0}, // xgroup(usage)
{"showcruft", 1, 1, cmd_showcruft, "(root dir)", gettext_noop(" -- show undecodable filenames in the volume")},
// xgroup(usage) {"cat", 2, 3, cmd_cat, "[--extpass=prog] (root dir) path",
gettext_noop(" -- show undecodable filenames in the volume")}, // xgroup(usage)
{"cat", 2, 3, cmd_cat, "[--extpass=prog] (root dir) path", gettext_noop(" -- decodes the file and cats it to standard out")},
// xgroup(usage) {"decode", 1, 100, cmd_decode,
gettext_noop(" -- decodes the file and cats it to standard out")}, "[--extpass=prog] (root dir) [encoded-name ...]",
{"decode", 1, 100, cmd_decode, // xgroup(usage)
"[--extpass=prog] (root dir) [encoded-name ...]", gettext_noop(" -- decodes name and prints plaintext version")},
// xgroup(usage) {"encode", 1, 100, cmd_encode,
gettext_noop(" -- decodes name and prints plaintext version")}, "[--extpass=prog] (root dir) [plaintext-name ...]",
{"encode", 1, 100, cmd_encode, // xgroup(usage)
"[--extpass=prog] (root dir) [plaintext-name ...]", gettext_noop(" -- encodes a filename and print result")},
// xgroup(usage) {"export", 2, 2, cmd_export, "(root dir) path",
gettext_noop(" -- encodes a filename and print result")}, // xgroup(usage)
{"export", 2, 2, cmd_export, "(root dir) path", gettext_noop(" -- decrypts a volume and writes results to path")},
// xgroup(usage) {"--version", 0, 0, showVersion, "",
gettext_noop(" -- decrypts a volume and writes results to path")}, // xgroup(usage)
{"--version", 0, 0, showVersion, "", gettext_noop(" -- print version number and exit")},
// xgroup(usage) {0, 0, 0, 0, 0, 0}};
gettext_noop(" -- print version number and exit")},
{0, 0, 0, 0, 0, 0}};
static void usage(const char *name) { static void usage(const char *name) {
cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n" cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n"
@ -167,7 +165,7 @@ static int showInfo(int argc, char **argv) {
string rootDir = argv[1]; string rootDir = argv[1];
if (!checkDir(rootDir)) return EXIT_FAILURE; if (!checkDir(rootDir)) return EXIT_FAILURE;
EncFSConfig* config = new EncFSConfig; EncFSConfig *config = new EncFSConfig;
ConfigType type = readConfig(rootDir, config); ConfigType type = readConfig(rootDir, config);
// show information stored in config.. // show information stored in config..
@ -184,38 +182,43 @@ static int showInfo(int argc, char **argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
case Config_V3: case Config_V3:
// xgroup(diag) // xgroup(diag)
cout << "\n" << autosprintf(_("Version 3 configuration; " cout << "\n"
"created by %s\n"), << autosprintf(_("Version 3 configuration; "
config->creator.c_str()); "created by %s\n"),
config->creator.c_str());
break; break;
case Config_V4: case Config_V4:
// xgroup(diag) // xgroup(diag)
cout << "\n" << autosprintf(_("Version 4 configuration; " cout << "\n"
"created by %s\n"), << autosprintf(_("Version 4 configuration; "
config->creator.c_str()); "created by %s\n"),
config->creator.c_str());
break; break;
case Config_V5: case Config_V5:
// xgroup(diag) // xgroup(diag)
cout << "\n" << autosprintf(_("Version 5 configuration; " cout << "\n"
"created by %s (revision %i)\n"), << autosprintf(_("Version 5 configuration; "
config->creator.c_str(), config->subVersion); "created by %s (revision %i)\n"),
config->creator.c_str(), config->subVersion);
break; break;
case Config_V6: case Config_V6:
// xgroup(diag) // xgroup(diag)
cout << "\n" << autosprintf(_("Version 6 configuration; " cout << "\n"
"created by %s (revision %i)\n"), << autosprintf(_("Version 6 configuration; "
config->creator.c_str(), config->subVersion); "created by %s (revision %i)\n"),
config->creator.c_str(), config->subVersion);
break; break;
} }
showFSInfo(config); showFSInfo(config);
delete config;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
static RootPtr initRootInfo(int &argc, char **&argv) { static RootPtr initRootInfo(int &argc, char **&argv) {
RootPtr result; RootPtr result;
shared_ptr<EncFS_Opts> opts(new EncFS_Opts()); std::shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
opts->createIfNotFound = false; opts->createIfNotFound = false;
opts->checkKey = false; opts->checkKey = false;
@ -232,7 +235,7 @@ static RootPtr initRootInfo(int &argc, char **&argv) {
opts->passwordProgram.assign(optarg); opts->passwordProgram.assign(optarg);
break; break;
default: default:
rWarning(_("getopt error: %i"), res); RLOG(WARNING) << "getopt error: " << res;
break; break;
} }
} }
@ -262,7 +265,7 @@ static RootPtr initRootInfo(const char *crootDir) {
RootPtr result; RootPtr result;
if (checkDir(rootDir)) { if (checkDir(rootDir)) {
shared_ptr<EncFS_Opts> opts(new EncFS_Opts()); std::shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
opts->rootDir = rootDir; opts->rootDir = rootDir;
opts->createIfNotFound = false; opts->createIfNotFound = false;
opts->checkKey = false; opts->checkKey = false;
@ -341,7 +344,7 @@ static int cmd_ls(int argc, char **argv) {
if (dt.valid()) { if (dt.valid()) {
for (string name = dt.nextPlaintextName(); !name.empty(); for (string name = dt.nextPlaintextName(); !name.empty();
name = dt.nextPlaintextName()) { name = dt.nextPlaintextName()) {
shared_ptr<FileNode> fnode = std::shared_ptr<FileNode> fnode =
rootInfo->root->lookupNode(name.c_str(), "encfsctl-ls"); rootInfo->root->lookupNode(name.c_str(), "encfsctl-ls");
struct stat stbuf; struct stat stbuf;
fnode->getAttr(&stbuf); fnode->getAttr(&stbuf);
@ -364,10 +367,10 @@ static int cmd_ls(int argc, char **argv) {
// apply an operation to every block in the file // apply an operation to every block in the file
template <typename T> template <typename T>
int processContents(const shared_ptr<EncFS_Root> &rootInfo, const char *path, int processContents(const std::shared_ptr<EncFS_Root> &rootInfo,
T &op) { const char *path, T &op) {
int errCode = 0; int errCode = 0;
shared_ptr<FileNode> node = std::shared_ptr<FileNode> node =
rootInfo->root->openNode(path, "encfsctl", O_RDONLY, &errCode); rootInfo->root->openNode(path, "encfsctl", O_RDONLY, &errCode);
if (!node) { if (!node) {
@ -421,8 +424,8 @@ static int cmd_cat(int argc, char **argv) {
} }
static int copyLink(const struct stat &stBuf, static int copyLink(const struct stat &stBuf,
const shared_ptr<EncFS_Root> &rootInfo, const string &cpath, const std::shared_ptr<EncFS_Root> &rootInfo,
const string &destName) { const string &cpath, const string &destName) {
std::vector<char> buf(stBuf.st_size + 1, '\0'); std::vector<char> buf(stBuf.st_size + 1, '\0');
int res = ::readlink(cpath.c_str(), buf.data(), stBuf.st_size); int res = ::readlink(cpath.c_str(), buf.data(), stBuf.st_size);
if (res == -1) { if (res == -1) {
@ -442,9 +445,10 @@ static int copyLink(const struct stat &stBuf,
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
static int copyContents(const shared_ptr<EncFS_Root> &rootInfo, static int copyContents(const std::shared_ptr<EncFS_Root> &rootInfo,
const char *encfsName, const char *targetName) { const char *encfsName, const char *targetName) {
shared_ptr<FileNode> node = rootInfo->root->lookupNode(encfsName, "encfsctl"); std::shared_ptr<FileNode> node =
rootInfo->root->lookupNode(encfsName, "encfsctl");
if (!node) { if (!node) {
cerr << "unable to open " << encfsName << "\n"; cerr << "unable to open " << encfsName << "\n";
@ -484,7 +488,7 @@ static bool endsWith(const string &str, char ch) {
return str[str.length() - 1] == ch; return str[str.length() - 1] == ch;
} }
static int traverseDirs(const shared_ptr<EncFS_Root> &rootInfo, static int traverseDirs(const std::shared_ptr<EncFS_Root> &rootInfo,
string volumeDir, string destDir) { string volumeDir, string destDir) {
if (!endsWith(volumeDir, '/')) volumeDir.append("/"); if (!endsWith(volumeDir, '/')) volumeDir.append("/");
if (!endsWith(destDir, '/')) destDir.append("/"); if (!endsWith(destDir, '/')) destDir.append("/");
@ -493,7 +497,7 @@ static int traverseDirs(const shared_ptr<EncFS_Root> &rootInfo,
// with the same permissions // with the same permissions
{ {
struct stat st; struct stat st;
shared_ptr<FileNode> dirNode = std::shared_ptr<FileNode> dirNode =
rootInfo->root->lookupNode(volumeDir.c_str(), "encfsctl"); rootInfo->root->lookupNode(volumeDir.c_str(), "encfsctl");
if (dirNode->getAttr(&st)) return EXIT_FAILURE; if (dirNode->getAttr(&st)) return EXIT_FAILURE;
@ -547,7 +551,8 @@ static int cmd_export(int argc, char **argv) {
return traverseDirs(rootInfo, "/", destDir); return traverseDirs(rootInfo, "/", destDir);
} }
int showcruft(const shared_ptr<EncFS_Root> &rootInfo, const char *dirName) { int showcruft(const std::shared_ptr<EncFS_Root> &rootInfo,
const char *dirName) {
int found = 0; int found = 0;
DirTraverse dt = rootInfo->root->openDir(dirName); DirTraverse dt = rootInfo->root->openDir(dirName);
if (dt.valid()) { if (dt.valid()) {
@ -607,17 +612,19 @@ static int cmd_showcruft(int argc, char **argv) {
// depend upon this broken singular form, so it isn't easy to change. // depend upon this broken singular form, so it isn't easy to change.
cerr << autosprintf(ngettext("Found %i invalid file.", cerr << autosprintf(ngettext("Found %i invalid file.",
"Found %i invalid files.", filesFound), "Found %i invalid files.", filesFound),
filesFound) << "\n"; filesFound)
<< "\n";
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc, char **argv) { static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc,
char **argv) {
(void)argc; (void)argc;
string rootDir = argv[1]; string rootDir = argv[1];
if (!checkDir(rootDir)) return EXIT_FAILURE; if (!checkDir(rootDir)) return EXIT_FAILURE;
EncFSConfig* config = new EncFSConfig; EncFSConfig *config = new EncFSConfig;
ConfigType cfgType = readConfig(rootDir, config); ConfigType cfgType = readConfig(rootDir, config);
if (cfgType == Config_None) { if (cfgType == Config_None) {
@ -626,7 +633,8 @@ static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc, c
} }
// instanciate proper cipher // instanciate proper cipher
shared_ptr<Cipher> cipher = Cipher::New(config->cipherIface, config->keySize); std::shared_ptr<Cipher> cipher =
Cipher::New(config->cipherIface, config->keySize);
if (!cipher) { if (!cipher) {
cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"), cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"),
config->cipherIface.name().c_str()); config->cipherIface.name().c_str());
@ -648,8 +656,7 @@ static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc, c
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if(checkOnly) if (checkOnly) {
{
cout << _("Password is correct\n"); cout << _("Password is correct\n");
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@ -708,7 +715,8 @@ static int ckpasswdAutomaticly(int argc, char **argv) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
RLogInit(argc, argv); START_EASYLOGGINGPP(argc, argv);
encfs::initLogging();
#if defined(ENABLE_NLS) && defined(LOCALEDIR) #if defined(ENABLE_NLS) && defined(LOCALEDIR)
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
@ -719,15 +727,19 @@ int main(int argc, char **argv) {
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
StdioNode *slog = new StdioNode(STDERR_FILENO);
slog->subscribeTo(GetGlobalChannel("error"));
slog->subscribeTo(GetGlobalChannel("warning"));
if (argc < 2) { if (argc < 2) {
usage(argv[0]); usage(argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Skip over uninteresting args.
while (argc > 2 && *argv[1] == '-') {
VLOG(1) << "skipping arg " << argv[1];
argc--;
argv[1] = argv[0];
argv++;
}
if (argc == 2 && !(*argv[1] == '-' && *(argv[1] + 1) == '-')) { if (argc == 2 && !(*argv[1] == '-' && *(argv[1] + 1) == '-')) {
// default command when only 1 argument given -- treat the argument as // default command when only 1 argument given -- treat the argument as
// a directory.. // a directory..
@ -747,7 +759,8 @@ int main(int argc, char **argv) {
(argc - 2 > commands[offset].maxOptions)) { (argc - 2 > commands[offset].maxOptions)) {
cerr << autosprintf( cerr << autosprintf(
_("Incorrect number of arguments for command \"%s\""), _("Incorrect number of arguments for command \"%s\""),
argv[1]) << "\n"; argv[1])
<< "\n";
} else } else
return (*commands[offset].func)(argc - 1, argv + 1); return (*commands[offset].func)(argc - 1, argv + 1);
} }

View File

@ -16,27 +16,24 @@
* *
*/ */
#include <getopt.h>
#include <pthread.h>
#include <rlog/RLogChannel.h>
#include <rlog/StdioNode.h>
#include <rlog/SyslogNode.h>
#include <rlog/rlog.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <cerrno> #include <cerrno>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <exception> #include <exception>
#include <getopt.h>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <pthread.h>
#include <sstream> #include <sstream>
#include <stdlib.h>
#include <string> #include <string>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "Context.h" #include "Context.h"
#include "Error.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "MemoryPool.h" #include "MemoryPool.h"
#include "autosprintf.h" #include "autosprintf.h"
@ -46,8 +43,6 @@
#include "i18n.h" #include "i18n.h"
#include "openssl.h" #include "openssl.h"
class DirNode;
// Fuse version >= 26 requires another argument to fuse_unmount, which we // Fuse version >= 26 requires another argument to fuse_unmount, which we
// don't have. So use the backward compatible call instead.. // don't have. So use the backward compatible call instead..
extern "C" void fuse_unmount_compat22(const char *mountpoint); extern "C" void fuse_unmount_compat22(const char *mountpoint);
@ -60,10 +55,15 @@ extern "C" void fuse_unmount_compat22(const char *mountpoint);
#define LONG_OPT_REQUIRE_MAC 515 #define LONG_OPT_REQUIRE_MAC 515
using namespace std; using namespace std;
using namespace rlog; using namespace encfs;
using namespace rel;
using gnu::autosprintf; using gnu::autosprintf;
INITIALIZE_EASYLOGGINGPP
namespace encfs {
class DirNode;
// Maximum number of arguments that we're going to pass on to fuse. Doesn't // Maximum number of arguments that we're going to pass on to fuse. Doesn't
// affect how many arguments we can handle, just how many we can pass on.. // affect how many arguments we can handle, just how many we can pass on..
const int MaxFuseArgs = 32; const int MaxFuseArgs = 32;
@ -74,14 +74,14 @@ const int MaxFuseArgs = 32;
* derived from the arguments * derived from the arguments
*/ */
struct EncFS_Args { struct EncFS_Args {
bool isDaemon; // true == spawn in background, log to syslog bool isDaemon; // true == spawn in background, log to syslog
bool isThreaded; // true == threaded bool isThreaded; // true == threaded
bool isVerbose; // false == only enable warning/error messages bool isVerbose; // false == only enable warning/error messages
int idleTimeout; // 0 == idle time in minutes to trigger unmount int idleTimeout; // 0 == idle time in minutes to trigger unmount
const char *fuseArgv[MaxFuseArgs]; const char *fuseArgv[MaxFuseArgs];
int fuseArgc; int fuseArgc;
shared_ptr<EncFS_Opts> opts; std::shared_ptr<EncFS_Opts> opts;
// for debugging // for debugging
// In case someone sends me a log dump, I want to know how what options are // In case someone sends me a log dump, I want to know how what options are
@ -110,6 +110,8 @@ struct EncFS_Args {
static int oldStderr = STDERR_FILENO; static int oldStderr = STDERR_FILENO;
} // namespace encfs
static void usage(const char *name) { static void usage(const char *name) {
// xgroup(usage) // xgroup(usage)
cerr << autosprintf(_("Build: encfs version %s"), VERSION) << "\n\n" cerr << autosprintf(_("Build: encfs version %s"), VERSION) << "\n\n"
@ -117,7 +119,8 @@ static void usage(const char *name) {
<< autosprintf( << autosprintf(
_("Usage: %s [options] rootDir mountPoint [-- [FUSE Mount " _("Usage: %s [options] rootDir mountPoint [-- [FUSE Mount "
"Options]]"), "Options]]"),
name) << "\n\n" name)
<< "\n\n"
// xgroup(usage) // xgroup(usage)
<< _("Common Options:\n" << _("Common Options:\n"
" -H\t\t\t" " -H\t\t\t"
@ -141,8 +144,9 @@ static void usage(const char *name) {
"\t\t\t(for filesystems using MAC block headers)\n") "\t\t\t(for filesystems using MAC block headers)\n")
<< _(" --public\t\t" << _(" --public\t\t"
"act as a typical multi-user filesystem\n" "act as a typical multi-user filesystem\n"
"\t\t\t(encfs must be run as root)\n") << _(" --reverse\t\t" "\t\t\t(encfs must be run as root)\n")
"reverse encryption\n") << _(" --reverse\t\t"
"reverse encryption\n")
// xgroup(usage) // xgroup(usage)
<< _(" --extpass=program\tUse external program for password prompt\n" << _(" --extpass=program\tUse external program for password prompt\n"
@ -151,13 +155,15 @@ static void usage(const char *name) {
" encfs ~/.crypt ~/crypt\n" " encfs ~/.crypt ~/crypt\n"
"\n") "\n")
// xgroup(usage) // xgroup(usage)
<< _("For more information, see the man page encfs(1)") << "\n" << endl; << _("For more information, see the man page encfs(1)") << "\n"
<< endl;
} }
static void FuseUsage() { static void FuseUsage() {
// xgroup(usage) // xgroup(usage)
cerr << _("encfs [options] rootDir mountPoint -- [FUSE Mount Options]\n" cerr << _("encfs [options] rootDir mountPoint -- [FUSE Mount Options]\n"
"valid FUSE Mount Options follow:\n") << endl; "valid FUSE Mount Options follow:\n")
<< endl;
int argc = 2; int argc = 2;
const char *argv[] = {"...", "-h"}; const char *argv[] = {"...", "-h"};
@ -177,7 +183,7 @@ static string slashTerminate(const string &src) {
} }
static bool processArgs(int argc, char *argv[], static bool processArgs(int argc, char *argv[],
const shared_ptr<EncFS_Args> &out) { const std::shared_ptr<EncFS_Args> &out) {
// set defaults // set defaults
out->isDaemon = true; out->isDaemon = true;
out->isThreaded = true; out->isThreaded = true;
@ -337,7 +343,7 @@ static bool processArgs(int argc, char *argv[],
break; break;
case 'P': case 'P':
if (geteuid() != 0) if (geteuid() != 0)
rWarning(_("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
@ -362,7 +368,7 @@ static bool processArgs(int argc, char *argv[],
// missing parameter for option.. // missing parameter for option..
break; break;
default: default:
rWarning(_("getopt error: %i"), res); RLOG(WARNING) << "getopt error: " << res;
break; break;
} }
} }
@ -378,7 +384,7 @@ static bool processArgs(int argc, char *argv[],
out->opts->mountPoint = slashTerminate(argv[optind++]); out->opts->mountPoint = slashTerminate(argv[optind++]);
} else { } else {
// no mount point specified // no mount point specified
rWarning(_("Missing one or more arguments, aborting.")); cerr << _("Missing one or more arguments, aborting.");
return false; return false;
} }
@ -426,7 +432,8 @@ static bool processArgs(int argc, char *argv[],
cerr << cerr <<
// xgroup(usage) // xgroup(usage)
_("When specifying daemon mode, you must use absolute paths " _("When specifying daemon mode, you must use absolute paths "
"(beginning with '/')") << endl; "(beginning with '/')")
<< endl;
return false; return false;
} }
@ -439,7 +446,8 @@ static bool processArgs(int argc, char *argv[],
cerr << cerr <<
// xgroup(usage) // xgroup(usage)
_("The raw directory may not be a subdirectory of the " _("The raw directory may not be a subdirectory of the "
"mount point.") << endl; "mount point.")
<< endl;
return false; return false;
} }
} }
@ -462,13 +470,13 @@ static bool processArgs(int argc, char *argv[],
if (!isDirectory(out->opts->rootDir.c_str()) && if (!isDirectory(out->opts->rootDir.c_str()) &&
!userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(), !userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(),
0700)) { 0700)) {
rWarning(_("Unable to locate root directory, aborting.")); cerr << _("Unable to locate root directory, aborting.");
return false; return false;
} }
if (!isDirectory(out->opts->mountPoint.c_str()) && if (!isDirectory(out->opts->mountPoint.c_str()) &&
!userAllowMkdir(out->opts->annotate ? 2 : 0, out->opts->mountPoint.c_str(), !userAllowMkdir(out->opts->annotate ? 2 : 0,
0700)) { out->opts->mountPoint.c_str(), 0700)) {
rWarning(_("Unable to locate mount point, aborting.")); cerr << _("Unable to locate mount point, aborting.");
return false; return false;
} }
@ -486,23 +494,27 @@ void *encfs_init(fuse_conn_info *conn) {
// set fuse connection options // set fuse connection options
conn->async_read = true; conn->async_read = true;
if (ctx->args->isDaemon) {
// Switch to using syslog.
encfs::rlogAction = el::base::DispatchAction::SysLog;
}
// 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.
if (ctx->args->idleTimeout > 0) { if (ctx->args->idleTimeout > 0) {
rDebug("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, 0, idleMonitor, (void *)ctx);
if (res != 0) { if (res != 0) {
rError( RLOG(ERROR) << "error starting idle monitor thread, "
"error starting idle monitor thread, " "res = "
"res = %i, errno = %i", << res << ", errno = " << errno;
res, errno);
} }
} }
if (ctx->args->isDaemon && oldStderr >= 0) { if (ctx->args->isDaemon && oldStderr >= 0) {
rInfo("Closing stderr"); VLOG(1) << "Closing stderr";
close(oldStderr); close(oldStderr);
oldStderr = -1; oldStderr = -1;
} }
@ -516,19 +528,18 @@ void encfs_destroy(void *_ctx) {
ctx->running = false; ctx->running = false;
// wake up the thread if it is waiting.. // wake up the thread if it is waiting..
rDebug("waking up monitoring thread"); VLOG(1) << "waking up monitoring thread";
pthread_mutex_lock(&ctx->wakeupMutex); pthread_mutex_lock(&ctx->wakeupMutex);
pthread_cond_signal(&ctx->wakeupCond); pthread_cond_signal(&ctx->wakeupCond);
pthread_mutex_unlock(&ctx->wakeupMutex); pthread_mutex_unlock(&ctx->wakeupMutex);
rDebug("joining with idle monitoring thread"); VLOG(1) << "joining with idle monitoring thread";
pthread_join(ctx->monitorThread, 0); pthread_join(ctx->monitorThread, 0);
rDebug("join done"); VLOG(1) << "join done";
} }
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// initialize the logging library encfs::initLogging();
RLogInit(argc, argv);
#if defined(ENABLE_NLS) && defined(LOCALEDIR) #if defined(ENABLE_NLS) && defined(LOCALEDIR)
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
@ -536,17 +547,9 @@ int main(int argc, char *argv[]) {
textdomain(PACKAGE); textdomain(PACKAGE);
#endif #endif
// log to stderr by default..
std::unique_ptr<StdioNode> slog(new StdioNode(STDERR_FILENO));
std::unique_ptr<SyslogNode> logNode;
// show error and warning output
slog->subscribeTo(GetGlobalChannel("error"));
slog->subscribeTo(GetGlobalChannel("warning"));
// 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.
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] = NULL; // libfuse expects null args..
@ -556,13 +559,11 @@ int main(int argc, char *argv[]) {
} }
if (encfsArgs->isVerbose) { if (encfsArgs->isVerbose) {
// subscribe to more logging channels.. el::Loggers::setVerboseLevel(1);
slog->subscribeTo(GetGlobalChannel("info"));
slog->subscribeTo(GetGlobalChannel("debug"));
} }
rDebug("Root directory: %s", encfsArgs->opts->rootDir.c_str()); VLOG(1) << "Root directory: " << encfsArgs->opts->rootDir;
rDebug("Fuse arguments: %s", encfsArgs->toString().c_str()); VLOG(1) << "Fuse arguments: " << encfsArgs->toString();
fuse_operations encfs_oper; fuse_operations encfs_oper;
// in case this code is compiled against a newer FUSE library and new // in case this code is compiled against a newer FUSE library and new
@ -609,15 +610,15 @@ int main(int argc, char *argv[]) {
encfs_oper.fgetattr = encfs_fgetattr; encfs_oper.fgetattr = encfs_fgetattr;
// encfs_oper.lock = encfs_lock; // encfs_oper.lock = encfs_lock;
encfs_oper.utimens = encfs_utimens; encfs_oper.utimens = encfs_utimens;
// encfs_oper.bmap = encfs_bmap; // encfs_oper.bmap = encfs_bmap;
openssl_init(encfsArgs->isThreaded); openssl_init(encfsArgs->isThreaded);
// 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.
EncFS_Context *ctx = new EncFS_Context; auto ctx = std::shared_ptr<EncFS_Context>(new EncFS_Context);
ctx->publicFilesystem = encfsArgs->opts->ownerCreate; ctx->publicFilesystem = encfsArgs->opts->ownerCreate;
RootPtr rootInfo = initFS(ctx, encfsArgs->opts); RootPtr rootInfo = initFS(ctx.get(), encfsArgs->opts);
int returnCode = EXIT_FAILURE; int returnCode = EXIT_FAILURE;
@ -637,7 +638,8 @@ int main(int argc, char *argv[]) {
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"
"single-threaded, but threads will still be used to\n" "single-threaded, but threads will still be used to\n"
"implement idle checking.") << endl; "implement idle checking.")
<< endl;
} }
// reset umask now, since we don't want it to interfere with the // reset umask now, since we don't want it to interfere with the
@ -645,14 +647,6 @@ int main(int argc, char *argv[]) {
umask(0); umask(0);
if (encfsArgs->isDaemon) { if (encfsArgs->isDaemon) {
// switch to logging just warning and error messages via syslog
logNode.reset(new SyslogNode("encfs"));
logNode->subscribeTo(GetGlobalChannel("warning"));
logNode->subscribeTo(GetGlobalChannel("error"));
// disable stderr reporting..
slog.reset();
// keep around a pointer just in case we end up needing it to // keep around a pointer just in case we end up needing it to
// report a fatal condition later (fuse_main exits unexpectedly)... // report a fatal condition later (fuse_main exits unexpectedly)...
oldStderr = dup(STDERR_FILENO); oldStderr = dup(STDERR_FILENO);
@ -671,7 +665,7 @@ int main(int argc, char *argv[]) {
// fuse_main returns an error code in newer versions of fuse.. // fuse_main returns an error code in newer versions of fuse..
int res = fuse_main(encfsArgs->fuseArgc, int res = fuse_main(encfsArgs->fuseArgc,
const_cast<char **>(encfsArgs->fuseArgv), &encfs_oper, const_cast<char **>(encfsArgs->fuseArgv), &encfs_oper,
(void *)ctx); (void *)ctx.get());
time(&endTime); time(&endTime);
@ -692,16 +686,16 @@ int main(int argc, char *argv[]) {
fclose(out); fclose(out);
} }
} catch (std::exception &ex) { } catch (std::exception &ex) {
rError(_("Internal error: Caught exception from main loop: %s"), RLOG(ERROR) << "Internal error: Caught exception from main loop: "
ex.what()); << ex.what();
} catch (...) { } catch (...) {
rError(_("Internal error: Caught unexpected exception")); RLOG(ERROR) << "Internal error: Caught unexpected exception";
} }
} }
// cleanup so that we can check for leaked resources.. // cleanup so that we can check for leaked resources..
rootInfo.reset(); rootInfo.reset();
ctx->setRoot(shared_ptr<DirNode>()); ctx->setRoot(std::shared_ptr<DirNode>());
MemoryPool::destroyAll(); MemoryPool::destroyAll();
openssl_shutdown(encfsArgs->isThreaded); openssl_shutdown(encfsArgs->isThreaded);
@ -721,7 +715,7 @@ static bool unmountFS(EncFS_Context *ctx);
static void *idleMonitor(void *_arg) { static void *idleMonitor(void *_arg) {
EncFS_Context *ctx = (EncFS_Context *)_arg; EncFS_Context *ctx = (EncFS_Context *)_arg;
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;
int idleCycles = 0; int idleCycles = 0;
@ -744,10 +738,11 @@ static void *idleMonitor(void *_arg) {
break; break;
} }
rDebug("num open files: %i", openCount); VLOG(1) << "num open files: " << openCount;
} }
rDebug("idle cycle count: %i, timeout after %i", idleCycles, timeoutCycles); VLOG(1) << "idle cycle count: " << idleCycles << ", timeout after "
<< timeoutCycles;
struct timeval currentTime; struct timeval currentTime;
gettimeofday(&currentTime, 0); gettimeofday(&currentTime, 0);
@ -759,24 +754,23 @@ static void *idleMonitor(void *_arg) {
pthread_mutex_unlock(&ctx->wakeupMutex); pthread_mutex_unlock(&ctx->wakeupMutex);
rDebug("Idle monitoring thread exiting"); VLOG(1) << "Idle monitoring thread exiting";
return 0; return 0;
} }
static bool unmountFS(EncFS_Context *ctx) { static bool unmountFS(EncFS_Context *ctx) {
shared_ptr<EncFS_Args> arg = ctx->args; std::shared_ptr<EncFS_Args> arg = ctx->args;
if (arg->opts->mountOnDemand) { if (arg->opts->mountOnDemand) {
rDebug("Detaching filesystem %s due to inactivity", VLOG(1) << "Detaching filesystem due to inactivity: "
arg->opts->mountPoint.c_str()); << arg->opts->mountPoint;
ctx->setRoot(shared_ptr<DirNode>()); ctx->setRoot(std::shared_ptr<DirNode>());
return false; return false;
} else { } else {
// Time to unmount! // Time to unmount!
// xgroup(diag) RLOG(WARNING) << "Unmounting filesystem due to inactivity: "
rWarning(_("Unmounting filesystem %s due to inactivity"), << arg->opts->mountPoint;
arg->opts->mountPoint.c_str());
fuse_unmount(arg->opts->mountPoint.c_str()); fuse_unmount(arg->opts->mountPoint.c_str());
return true; return true;
} }

View File

@ -18,19 +18,22 @@
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdlib.h>
#include <unistd.h>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <stdlib.h>
#include <string> #include <string>
#include <unistd.h>
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "openssl.h" #include "openssl.h"
using namespace std; using namespace std;
using namespace encfs;
void genKey(const shared_ptr<Cipher> &cipher) { INITIALIZE_EASYLOGGINGPP
void genKey(const std::shared_ptr<Cipher> &cipher) {
CipherKey key = cipher->newRandomKey(); CipherKey key = cipher->newRandomKey();
// encode with itself // encode with itself
@ -54,7 +57,7 @@ int main(int argc, char **argv) {
openssl_init(false); openssl_init(false);
// get a list of the available algorithms // get a list of the available algorithms
shared_ptr<Cipher> cipher = Cipher::New(type, size); std::shared_ptr<Cipher> cipher = Cipher::New(type, size);
genKey(cipher); genKey(cipher);
// openssl_shutdown(false); // openssl_shutdown(false);

View File

@ -22,7 +22,6 @@
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <pthread.h> #include <pthread.h>
#include <rlog/rlog.h>
#include <stdlib.h> #include <stdlib.h>
#define NO_DES #define NO_DES
@ -32,6 +31,10 @@
#include <openssl/engine.h> #include <openssl/engine.h>
#endif #endif
#include "Error.h"
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 = NULL;
@ -41,7 +44,7 @@ void pthreads_locking_callback(int mode, int n, const char *caller_file,
(void)caller_line; (void)caller_line;
if (!crypto_locks) { if (!crypto_locks) {
rDebug("Allocating %i locks for OpenSSL", CRYPTO_num_locks()); 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, 0);
@ -94,3 +97,5 @@ void openssl_shutdown(bool threaded) {
if (threaded) pthreads_locking_cleanup(); if (threaded) pthreads_locking_cleanup();
} }
} // namespace encfs

View File

@ -21,7 +21,11 @@
#ifndef _openssl_incl_ #ifndef _openssl_incl_
#define _openssl_incl_ #define _openssl_incl_
namespace encfs {
void openssl_init(bool isThreaded); void openssl_init(bool isThreaded);
void openssl_shutdown(bool isThreaded); void openssl_shutdown(bool isThreaded);
} // namespace encfs
#endif #endif

View File

@ -37,16 +37,16 @@ static const char rcsid[] =
#ifndef HAVE_READPASSPHRASE #ifndef HAVE_READPASSPHRASE
#include <fcntl.h>
#include <paths.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <cctype> #include <cctype>
#include <cerrno> #include <cerrno>
#include <csignal> #include <csignal>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <fcntl.h>
#include <paths.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include "readpassphrase.h" #include "readpassphrase.h"

View File

@ -1,29 +0,0 @@
/*****************************************************************************
* Author: Valient Gough <vgough@pobox.com>
*
*****************************************************************************
* Copyright (c) 2012 Valient Gough
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SHARED_PTR_incl_
#define _SHARED_PTR_incl_
#include <memory>
using std::shared_ptr;
using std::dynamic_pointer_cast;
#endif

View File

@ -16,8 +16,6 @@
* *
*/ */
#include <time.h>
#include <unistd.h>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
@ -25,16 +23,14 @@
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <time.h>
#include <rlog/Error.h> #include <unistd.h>
#include <rlog/RLogChannel.h>
#include <rlog/StdioNode.h>
#include <rlog/rlog.h>
#include "BlockNameIO.h" #include "BlockNameIO.h"
#include "Cipher.h" #include "Cipher.h"
#include "CipherKey.h" #include "CipherKey.h"
#include "DirNode.h" #include "DirNode.h"
#include "Error.h"
#include "FSConfig.h" #include "FSConfig.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "Interface.h" #include "Interface.h"
@ -42,6 +38,7 @@
#include "NameIO.h" #include "NameIO.h"
#include "Range.h" #include "Range.h"
#include "StreamNameIO.h" #include "StreamNameIO.h"
#include "internal/easylogging++.h"
#define NO_DES #define NO_DES
#include <openssl/ssl.h> #include <openssl/ssl.h>
@ -50,13 +47,15 @@
#endif #endif
using namespace std; using namespace std;
using namespace rel; using namespace encfs;
using namespace rlog;
INITIALIZE_EASYLOGGINGPP
const int FSBlockSize = 256; const int FSBlockSize = 256;
static int checkErrorPropogation(const shared_ptr<Cipher> &cipher, int size, static int checkErrorPropogation(const std::shared_ptr<Cipher> &cipher,
int byteToChange, const CipherKey &key) { int size, int byteToChange,
const CipherKey &key) {
MemBlock orig = MemoryPool::allocate(size); MemBlock orig = MemoryPool::allocate(size);
MemBlock data = MemoryPool::allocate(size); MemBlock data = MemoryPool::allocate(size);
@ -132,7 +131,7 @@ static bool testNameCoding(DirNode &dirNode, bool verbose) {
return true; return true;
} }
bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) { bool runTests(const std::shared_ptr<Cipher> &cipher, bool verbose) {
// create a random key // create a random key
if (verbose) { if (verbose) {
cerr << "Generating new key, output will be different on each run\n\n"; cerr << "Generating new key, output will be different on each run\n\n";
@ -143,7 +142,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
{ {
CipherKey encodingKey = cipher->newRandomKey(); CipherKey encodingKey = cipher->newRandomKey();
int encodedKeySize = cipher->encodedKeySize(); int encodedKeySize = cipher->encodedKeySize();
unsigned char *keyBuf = new unsigned char[encodedKeySize]; unsigned char keyBuf[encodedKeySize];
cipher->writeKey(key, keyBuf, encodingKey); cipher->writeKey(key, keyBuf, encodingKey);
CipherKey key2 = cipher->readKey(keyBuf, encodingKey); CipherKey key2 = cipher->readKey(keyBuf, encodingKey);
@ -164,7 +163,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
{ {
CipherKey encodingKey = cipher->newRandomKey(); CipherKey encodingKey = cipher->newRandomKey();
int encodedKeySize = cipher->encodedKeySize(); int encodedKeySize = cipher->encodedKeySize();
unsigned char *keyBuf = new unsigned char[encodedKeySize]; unsigned char keyBuf[encodedKeySize];
cipher->writeKey(key, keyBuf, encodingKey); cipher->writeKey(key, keyBuf, encodingKey);
@ -266,7 +265,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
if (!verbose) { if (!verbose) {
{ {
// test stream mode, this time without IV chaining // test stream mode, this time without IV chaining
fsCfg->nameCoding = shared_ptr<NameIO>( fsCfg->nameCoding = std::shared_ptr<NameIO>(
new StreamNameIO(StreamNameIO::CurrentInterface(), cipher, key)); new StreamNameIO(StreamNameIO::CurrentInterface(), cipher, key));
fsCfg->nameCoding->setChainedNameIV(false); fsCfg->nameCoding->setChainedNameIV(false);
@ -277,7 +276,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
{ {
// test block mode, this time without IV chaining // test block mode, this time without IV chaining
fsCfg->nameCoding = shared_ptr<NameIO>( fsCfg->nameCoding = std::shared_ptr<NameIO>(
new BlockNameIO(BlockNameIO::CurrentInterface(), cipher, key, new BlockNameIO(BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize())); cipher->cipherBlockSize()));
fsCfg->nameCoding->setChainedNameIV(false); fsCfg->nameCoding->setChainedNameIV(false);
@ -331,7 +330,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
if (verbose) { if (verbose) {
cerr << "modification of 1 byte affected between " << minChanges cerr << "modification of 1 byte affected between " << minChanges
<< " and " << maxChanges << " decoded bytes\n"; << " and " << maxChanges << " decoded bytes\n";
cerr << "minimum change at byte " << minAt << " and maximum at byte " cerr << "minimum change at byte " << minAt << " and maximum at byte "
<< maxAt << "\n"; << maxAt << "\n";
} }
} }
@ -357,7 +356,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
if (verbose) { if (verbose) {
cerr << "modification of 1 byte affected between " << minChanges cerr << "modification of 1 byte affected between " << minChanges
<< " and " << maxChanges << " decoded bytes\n"; << " and " << maxChanges << " decoded bytes\n";
cerr << "minimum change at byte " << minAt << " and maximum at byte " cerr << "minimum change at byte " << minAt << " and maximum at byte "
<< maxAt << "\n"; << maxAt << "\n";
} }
} }
@ -370,7 +369,7 @@ static bool testCipherSize(const string &name, int keySize, int blockSize,
cerr << name << ", key length " << keySize << ", block size " << blockSize cerr << name << ", key length " << keySize << ", block size " << blockSize
<< ": "; << ": ";
shared_ptr<Cipher> cipher = Cipher::New(name, keySize); std::shared_ptr<Cipher> cipher = Cipher::New(name, keySize);
if (!cipher) { if (!cipher) {
cerr << "FAILED TO CREATE\n"; cerr << "FAILED TO CREATE\n";
return false; return false;
@ -382,7 +381,7 @@ static bool testCipherSize(const string &name, int keySize, int blockSize,
cerr << "FAILED\n"; cerr << "FAILED\n";
return false; return false;
} }
} catch (rlog::Error &er) { } catch (encfs::Error &er) {
cerr << "Error: " << er.what() << "\n"; cerr << "Error: " << er.what() << "\n";
return false; return false;
} }
@ -391,14 +390,8 @@ static bool testCipherSize(const string &name, int keySize, int blockSize,
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
RLogInit(argc, argv); START_EASYLOGGINGPP(argc, argv);
encfs::initLogging();
StdioNode stdLog(STDERR_FILENO);
stdLog.subscribeTo(RLOG_CHANNEL("error"));
stdLog.subscribeTo(RLOG_CHANNEL("warning"));
#ifndef NO_DEBUG
stdLog.subscribeTo(RLOG_CHANNEL("debug"));
#endif
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
@ -442,7 +435,7 @@ int main(int argc, char *argv[]) {
} }
// run one test with verbose output too.. // run one test with verbose output too..
shared_ptr<Cipher> cipher = Cipher::New("AES", 192); std::shared_ptr<Cipher> cipher = Cipher::New("AES", 192);
if (!cipher) { if (!cipher) {
cerr << "\nNo AES cipher found, skipping verbose test.\n"; cerr << "\nNo AES cipher found, skipping verbose test.\n";
} else { } else {

6663
internal/easylogging++.h Executable file

File diff suppressed because it is too large Load Diff