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_NAME "Encrypted Filesystem")
option(IWYU "Build with IWYU analyais." OFF)
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_SOURCE_DIR}/cmake")
@ -62,10 +64,6 @@ else ()
include_directories (${TINYXML_INCLUDE_DIR})
endif ()
find_package (RLog REQUIRED)
add_definitions (-DRLOG_COMPONENT="encfs")
include_directories (${RLOG_INCLUDE_DIR})
find_program (POD2MAN pod2man)
include (FindGettext)
@ -95,6 +93,14 @@ check_function_exists_glibc (lchmod HAVE_LCHMOD)
set (CMAKE_THREAD_PREFER_PTHREAD)
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.
set (CPACK_PACKAGE_NAME "encfs")
set (CPACK_PACKAGE_VERSION_MAJOR ${ENCFS_MAJOR})
@ -124,6 +130,7 @@ set(SOURCE_FILES
encfs/Context.cpp
encfs/DirNode.cpp
encfs/encfs.cpp
encfs/Error.cpp
encfs/FileIO.cpp
encfs/FileNode.cpp
encfs/FileUtils.cpp
@ -148,11 +155,21 @@ target_link_libraries(encfs
${FUSE_LIBRARIES}
${OPENSSL_LIBRARIES}
${TINYXML_LIBRARIES}
${RLOG_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
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(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

View File

@ -41,13 +41,16 @@ Dependencies
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
==============================
We use separate [Drone.io](https://drone.io/) and [CircleCi](https://circleci.com/) builds to automatically
test every commit. See the README.md file for current build status.
See the automated build static in README.md for current build status on Ubuntu systems.
The build configuration files (.drone.yml and circle.yml) therefore
always contains up-to-date instructions to build EncFS on Ubuntu distributions.
The build configuration files (.drone.yml and circle.yml) always contains up-to-date
instructions to build EncFS on Ubuntu distributions.

View File

@ -2,4 +2,4 @@ set -x
set -e
mkdir 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:
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
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 \
libfuse-dev \
libssl-dev \
librlog-dev \
gettext \
libgettextpo-dev \
&& apt-get clean

View File

@ -20,16 +20,15 @@
#include "BlockFileIO.h"
#include <inttypes.h>
#include <rlog/rlog.h>
#include <cstring>
#include <memory>
#include <cstring> // for memset, memcpy, NULL
#include "FSConfig.h"
#include "FileIO.h"
#include "FileUtils.h"
#include "MemoryPool.h"
#include "i18n.h"
#include "Error.h"
#include "FSConfig.h" // for FSConfigPtr
#include "FileIO.h" // for IORequest, FileIO
#include "FileUtils.h" // for EncFS_Opts
#include "MemoryPool.h" // for MemBlock, release, allocation
namespace encfs {
template <typename Type>
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)
: _blockSize(blockSize), _allowHoles(cfg->config->allowHoles) {
rAssert(_blockSize > 1);
CHECK(_blockSize > 1);
_cache.data = new unsigned char[_blockSize];
_noCache = cfg->opts->noCache;
}
@ -60,9 +59,8 @@ BlockFileIO::~BlockFileIO() {
* returned data as neccessary.
*/
ssize_t BlockFileIO::cacheReadOneBlock(const IORequest &req) const {
rAssert(req.dataLen <= _blockSize);
rAssert(req.offset % _blockSize == 0);
CHECK(req.dataLen <= _blockSize);
CHECK(req.offset % _blockSize == 0);
/* 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
@ -115,7 +113,7 @@ bool BlockFileIO::cacheWriteOneBlock(const IORequest &req) {
* lower layer.
*/
ssize_t BlockFileIO::read(const IORequest &req) const {
rAssert(_blockSize != 0);
CHECK(_blockSize != 0);
int partialOffset = 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);
if (unlikely(readSize <= partialOffset))
break; // didn't get enough bytes
if (readSize <= partialOffset) break; // didn't get enough bytes
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 (blockReq.data != out)
@ -165,7 +162,7 @@ ssize_t BlockFileIO::read(const IORequest &req) const {
++blockNum;
partialOffset = 0;
if (unlikely(readSize < _blockSize)) break;
if (readSize < _blockSize) break;
}
if (mb.data) MemoryPool::release(mb);
@ -175,11 +172,10 @@ ssize_t BlockFileIO::read(const IORequest &req) const {
}
bool BlockFileIO::write(const IORequest &req) {
rAssert(_blockSize != 0);
CHECK(_blockSize != 0);
off_t fileSize = getSize();
if (fileSize < 0)
return false;
if (fileSize < 0) return false;
// where write request begins
off_t blockNum = req.offset / _blockSize;
@ -301,7 +297,7 @@ void BlockFileIO::padFile(off_t oldSize, off_t newSize, bool forceWrite) {
cacheWriteOneBlock(req);
}
} else
rDebug("optimization: not padding last block");
VLOG(1) << "optimization: not padding last block";
} else {
mb = MemoryPool::allocate(_blockSize);
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
if (req.dataLen != 0) {
rDebug("padding block %" PRIi64, oldLastBlock);
VLOG(1) << "padding block " << oldLastBlock;
memset(mb.data, 0, _blockSize);
cacheReadOneBlock(req);
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
if (!_allowHoles) {
for (; oldLastBlock != newLastBlock; ++oldLastBlock) {
rDebug("padding block %" PRIi64, oldLastBlock);
VLOG(1) << "padding block " << oldLastBlock;
req.offset = oldLastBlock * _blockSize;
req.dataLen = _blockSize;
memset(mb.data, 0, req.dataLen);
@ -386,8 +382,8 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
if ((rdSz < 0) || (!wrRes)) {
// rwarning - unlikely to ever occur..
rWarning(_("truncate failure: read %i bytes, partial block of %i"),
(int)rdSz, partialBlock);
RLOG(WARNING) << "truncate failure: read " << rdSz
<< " bytes, partial block of " << partialBlock;
}
MemoryPool::release(mb);
@ -399,3 +395,5 @@ int BlockFileIO::truncateBase(off_t size, FileIO *base) {
return res;
}
} // namespace encfs

View File

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

View File

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

View File

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

View File

@ -18,10 +18,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <iostream>
#include <list>
#include <map>
#include <stddef.h>
#include <string>
#include <utility>
@ -36,7 +36,8 @@
#include "base64.h"
using namespace std;
using namespace rel;
namespace encfs {
#define REF_MODULE(TYPE) \
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));
return true;
}
shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
shared_ptr<Cipher> result;
std::shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
std::shared_ptr<Cipher> result;
if (gCipherMap) {
CipherMap_t::const_iterator it = gCipherMap->find(name);
@ -125,9 +125,8 @@ shared_ptr<Cipher> Cipher::New(const string &name, int keyLen) {
return result;
}
shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) {
shared_ptr<Cipher> result;
std::shared_ptr<Cipher> Cipher::New(const Interface &iface, int keyLen) {
std::shared_ptr<Cipher> result;
if (gCipherMap) {
CipherMap_t::const_iterator it;
CipherMap_t::const_iterator mapEnd = gCipherMap->end();
@ -199,3 +198,5 @@ string Cipher::encodeAsString(const CipherKey &key,
return string((const char *)b64Key);
}
} // namespace encfs

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,10 +20,12 @@
#include "ConfigVar.h"
#include <rlog/rlog.h>
#include "internal/easylogging++.h"
#include <cstring>
using namespace rlog;
#include "Error.h"
namespace encfs {
#ifndef MIN
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) {
rDebug("string encoded as size %i bytes, read %i", length, readLen);
VLOG(1) << "string encoded as size " << length << " bytes, read "
<< readLen;
}
rAssert(readLen == length);
return src;
}
} // namespace encfs

View File

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

View File

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

View File

@ -21,15 +21,16 @@
#ifndef _Context_incl_
#define _Context_incl_
#include <pthread.h>
#include <memory>
#include <pthread.h>
#include <set>
#include <string>
#include <unordered_map>
#include "encfs.h"
#include "shared_ptr.h"
namespace encfs {
class DirNode;
class FileNode;
@ -41,24 +42,24 @@ class EncFS_Context {
EncFS_Context();
~EncFS_Context();
shared_ptr<FileNode> getNode(void *ptr);
shared_ptr<FileNode> lookupNode(const char *path);
std::shared_ptr<FileNode> getNode(void *ptr);
std::shared_ptr<FileNode> lookupNode(const char *path);
int getAndResetUsageCounter();
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 renameNode(const char *oldName, const char *newName);
void setRoot(const shared_ptr<DirNode> &root);
shared_ptr<DirNode> getRoot(int *err);
void setRoot(const std::shared_ptr<DirNode> &root);
std::shared_ptr<DirNode> getRoot(int *err);
bool isMounted();
shared_ptr<EncFS_Args> args;
shared_ptr<EncFS_Opts> opts;
std::shared_ptr<EncFS_Args> args;
std::shared_ptr<EncFS_Opts> opts;
bool publicFilesystem;
// 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
* file is kept. Rather then doing reference counting in FileNode, we
* 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.
*/
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;
@ -92,9 +93,11 @@ class EncFS_Context {
FileMap openFiles;
int usageCount;
shared_ptr<DirNode> root;
std::shared_ptr<DirNode> root;
};
int remountFS(EncFS_Context *ctx);
} // namespace encfs
#endif

View File

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

View File

@ -23,13 +23,13 @@
#include <dirent.h>
#include <inttypes.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/types.h>
#include <list>
#include <map>
#include <memory>
#include <pthread.h>
#include <stdint.h>
#include <string>
#include <sys/types.h>
#include <vector>
#include "CipherKey.h"
@ -37,6 +37,8 @@
#include "FileNode.h"
#include "NameIO.h"
namespace encfs {
class Cipher;
class EncFS_Context;
class FileNode;
@ -46,8 +48,8 @@ struct RenameEl;
class DirTraverse {
public:
DirTraverse(const shared_ptr<DIR> &dirPtr, uint64_t iv,
const shared_ptr<NameIO> &naming);
DirTraverse(const std::shared_ptr<DIR> &dirPtr, uint64_t iv,
const std::shared_ptr<NameIO> &naming);
DirTraverse(const DirTraverse &src);
~DirTraverse();
@ -68,11 +70,11 @@ class DirTraverse {
std::string nextInvalid();
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
// more efficient to support filename IV chaining..
uint64_t iv;
shared_ptr<NameIO> naming;
std::shared_ptr<NameIO> naming;
};
inline bool DirTraverse::valid() const { return dir.get() != 0; }
@ -90,16 +92,16 @@ class DirNode {
bool touchesMountpoint(const char *realPath) const;
// find files
shared_ptr<FileNode> lookupNode(const char *plaintextName,
const char *requestor);
std::shared_ptr<FileNode> lookupNode(const char *plaintextName,
const char *requestor);
/*
Combined lookupNode + node->open() call. If the open fails, then the
node is not retained. If the open succeeds, then the node is returned.
*/
shared_ptr<FileNode> openNode(const char *plaintextName,
const char *requestor, int flags,
int *openResult);
std::shared_ptr<FileNode> openNode(const char *plaintextName,
const char *requestor, int flags,
int *openResult);
std::string cipherPath(const char *plaintextPath);
std::string cipherPathWithoutRoot(const char *plaintextPath);
@ -141,9 +143,9 @@ class DirNode {
this call has no effect.
Returns the FileNode if it was found.
*/
shared_ptr<FileNode> renameNode(const char *from, const char *to);
shared_ptr<FileNode> renameNode(const char *from, const char *to,
bool forwardMode);
std::shared_ptr<FileNode> renameNode(const char *from, const char *to);
std::shared_ptr<FileNode> renameNode(const char *from, const char *to,
bool forwardMode);
/*
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
to paths.
*/
shared_ptr<RenameOp> newRenameOp(const char *from, const char *to);
std::shared_ptr<RenameOp> newRenameOp(const char *from, const char *to);
private:
friend class RenameOp;
@ -159,7 +161,7 @@ class DirNode {
bool genRenameList(std::list<RenameEl> &list, const char *fromP,
const char *toP);
shared_ptr<FileNode> findOrCreate(const char *plainName);
std::shared_ptr<FileNode> findOrCreate(const char *plainName);
pthread_mutex_t mutex;
@ -169,7 +171,9 @@ class DirNode {
std::string rootDir;
FSConfigPtr fsConfig;
shared_ptr<NameIO> naming;
std::shared_ptr<NameIO> naming;
};
} // namespace encfs
#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_
#define _FSConfig_incl_
#include <memory>
#include <string>
#include <vector>
#include "encfs.h"
#include "Interface.h"
#include "CipherKey.h"
#include "shared_ptr.h"
#include "Interface.h"
#include "encfs.h"
namespace encfs {
enum ConfigType {
Config_None = 0,
@ -52,10 +54,10 @@ struct EncFSConfig {
int subVersion;
// interface of cipher
rel::Interface cipherIface;
Interface cipherIface;
// interface used for file name coding
rel::Interface nameIface;
Interface nameIface;
int keySize; // reported in bits
int blockSize; // reported in bytes
@ -93,7 +95,7 @@ struct EncFSConfig {
const std::string &rootDir);
CipherKey getNewUserKey();
shared_ptr<Cipher> getCipher() const;
std::shared_ptr<Cipher> getCipher() const;
// deprecated
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);
struct FSConfig {
shared_ptr<EncFSConfig> config;
shared_ptr<EncFS_Opts> opts;
std::shared_ptr<EncFSConfig> config;
std::shared_ptr<EncFS_Opts> opts;
shared_ptr<Cipher> cipher;
std::shared_ptr<Cipher> cipher;
CipherKey key;
shared_ptr<NameIO> nameCoding;
std::shared_ptr<NameIO> nameCoding;
bool forceDecode; // force decode on MAC block failures
bool reverseEncryption; // reverse encryption operation
@ -128,6 +130,8 @@ struct FSConfig {
: forceDecode(false), reverseEncryption(false), idleTracking(false) {}
};
typedef shared_ptr<FSConfig> FSConfigPtr;
typedef std::shared_ptr<FSConfig> FSConfigPtr;
} // namespace encfs
#endif

View File

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

View File

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

View File

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

View File

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

View File

@ -24,22 +24,21 @@
#endif
#define _BSD_SOURCE // pick up setenv on RH7.3
#include <fcntl.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 "internal/easylogging++.h"
#include <cctype>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include <list>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <tinyxml2.h>
#include <unistd.h>
#include <vector>
#include "BlockNameIO.h"
@ -49,6 +48,7 @@
#include "ConfigVar.h"
#include "Context.h"
#include "DirNode.h"
#include "Error.h"
#include "FSConfig.h"
#include "FileUtils.h"
#include "Interface.h"
@ -62,15 +62,11 @@
#include "intl/gettext.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 gnu::autosprintf;
namespace encfs {
static const int DefaultBlockSize = 1024;
// The maximum length of text passwords. If longer are needed,
// use the extpass option, as extpass can return arbitrary length binary data.
@ -109,18 +105,18 @@ struct ConfigInfo {
int currentSubVersion;
int defaultSubVersion;
} ConfigFileMapping[] = {
// current format
{".encfs6.xml", Config_V6, "ENCFS6_CONFIG", readV6Config, writeV6Config,
V6SubVersion, 0},
// backward compatible support for older versions
{".encfs5", Config_V5, "ENCFS5_CONFIG", readV5Config, writeV5Config,
V5SubVersion, V5SubVersionDefault},
{".encfs4", Config_V4, NULL, readV4Config, writeV4Config, 0, 0},
// no longer support earlier versions
{".encfs3", Config_V3, NULL, NULL, NULL, 0, 0},
{".encfs2", Config_Prehistoric, NULL, NULL, NULL, 0, 0},
{".encfs", Config_Prehistoric, NULL, NULL, NULL, 0, 0},
{NULL, Config_None, NULL, NULL, NULL, 0, 0}};
// current format
{".encfs6.xml", Config_V6, "ENCFS6_CONFIG", readV6Config, writeV6Config,
V6SubVersion, 0},
// backward compatible support for older versions
{".encfs5", Config_V5, "ENCFS5_CONFIG", readV5Config, writeV5Config,
V5SubVersion, V5SubVersionDefault},
{".encfs4", Config_V4, NULL, readV4Config, writeV4Config, 0, 0},
// no longer support earlier versions
{".encfs3", Config_V3, NULL, NULL, NULL, 0, 0},
{".encfs2", Config_Prehistoric, NULL, NULL, NULL, 0, 0},
{".encfs", Config_Prehistoric, NULL, NULL, NULL, 0, 0},
{NULL, Config_None, NULL, NULL, NULL, 0, 0}};
EncFS_Root::EncFS_Root() {}
@ -217,11 +213,12 @@ ConfigType readConfig_load(ConfigInfo *nm, const char *path,
config->cfgType = nm->type;
return nm->type;
}
} catch (rlog::Error &err) {
err.log(_RLWarningChannel);
} catch (encfs::Error &err) {
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);
} else {
// No load function - must be an unsupported type..
@ -242,9 +239,9 @@ ConfigType readConfig(const string &rootDir, EncFSConfig *config) {
char *envFile = getenv(nm->environmentOverride);
if (envFile != NULL) {
if (!fileExists(envFile)) {
rError(
"fatal: config file specified by environment does not exist: %s",
envFile);
RLOG(ERROR)
<< "fatal: config file specified by environment does not exist: "
<< envFile;
exit(1);
}
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"
* This format is in use since Apr 13, 2008 (commit 6d081f5c)
*/
// Read a boost::serialization config file using an Xml reader..
bool readV6Config(const char *configFile, EncFSConfig *cfg,
ConfigInfo *info) {
// Read a boost::serialization config file using an Xml reader..
bool readV6Config(const char *configFile, EncFSConfig *cfg, ConfigInfo *info) {
(void)info;
XmlReader rdr;
if (!rdr.load(configFile)) {
rError("Failed to load config file %s", configFile);
RLOG(ERROR) << "Failed to load config file " << configFile;
return false;
}
@ -282,34 +278,34 @@ bool readV6Config(const char *configFile, EncFSConfig *cfg,
config = (*serialization)["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;
}
int version;
if (!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;
}
// version numbering was complicated by boost::archive
if (version == 20 || version >= 20100713) {
rDebug("found new serialization format");
VLOG(1) << "found new serialization format";
cfg->subVersion = version;
} else if (version == 26800) {
rDebug("found 20080816 version");
VLOG(1) << "found 20080816 version";
cfg->subVersion = 20080816;
} else if (version == 26797) {
rDebug("found 20080813");
VLOG(1) << "found 20080813";
cfg->subVersion = 20080813;
} else if (version < V5SubVersion) {
rError("Invalid version %d - please fix config file", version);
RLOG(ERROR) << "Invalid version " << version << " - please fix config file";
} else {
rInfo("Boost <= 1.41 compatibility mode");
VLOG(1) << "Boost <= 1.41 compatibility mode";
cfg->subVersion = version;
}
rDebug("subVersion = %d", cfg->subVersion);
VLOG(1) << "subVersion = " << cfg->subVersion;
config->read("creator", &cfg->creator);
config->read("cipherAlg", &cfg->cipherIface);
@ -367,15 +363,14 @@ bool readV5Config(const char *configFile, EncFSConfig *config,
if (config->subVersion > info->currentSubVersion) {
/* config file specifies a version outside our supported
range.. */
rWarning(_("Config subversion %i found, but this version of"
" encfs only supports up to version %i."),
config->subVersion, info->currentSubVersion);
RLOG(WARNING) << "Config subversion " << config->subVersion
<< " found, which is newer than supported version "
<< info->currentSubVersion;
return false;
}
if (config->subVersion < 20040813) {
rError(
_("This version of EncFS doesn't support "
"filesystems created before 2004-08-13"));
RLOG(ERROR) << "This version of EncFS doesn't support "
"filesystems created before 2004-08-13";
return false;
}
@ -395,9 +390,9 @@ bool readV5Config(const char *configFile, EncFSConfig *config,
config->blockMACRandBytes = cfgRdr["blockMACRandBytes"].readInt(0);
ok = true;
} catch (rlog::Error &err) {
err.log(_RLWarningChannel);
rDebug("Error parsing data in config file %s", configFile);
} catch (encfs::Error &err) {
RLOG(WARNING) << err.what();
VLOG(1) << "Error parsing data in config file " << configFile;
ok = false;
}
}
@ -435,9 +430,9 @@ bool readV4Config(const char *configFile, EncFSConfig *config,
config->chainedNameIV = false;
ok = true;
} catch (rlog::Error &err) {
err.log(_RLWarningChannel);
rDebug("Error parsing config file %s", configFile);
} catch (encfs::Error &err) {
RLOG(WARNING) << err.what();
VLOG(1) << "Error parsing config file " << configFile;
ok = false;
}
}
@ -461,8 +456,8 @@ bool saveConfig(ConfigType type, const string &rootDir,
try {
ok = (*nm->saveFunc)(path.c_str(), config);
} catch (rlog::Error &err) {
err.log(_RLWarningChannel);
} catch (encfs::Error &err) {
RLOG(WARNING) << err.what();
ok = false;
}
break;
@ -558,8 +553,7 @@ bool writeV6Config(const char *configFile, const EncFSConfig *cfg) {
return err == tinyxml2::XML_SUCCESS;
}
bool writeV5Config(const char *configFile,
const EncFSConfig *config) {
bool writeV5Config(const char *configFile, const EncFSConfig *config) {
ConfigReader cfg;
cfg["creator"] << config->creator;
@ -580,8 +574,7 @@ bool writeV5Config(const char *configFile,
return cfg.save(configFile);
}
bool writeV4Config(const char *configFile,
const EncFSConfig *config) {
bool writeV4Config(const char *configFile, const EncFSConfig *config) {
ConfigReader cfg;
cfg["cipher"] << config->cipherIface;
@ -632,20 +625,23 @@ static Cipher::CipherAlgorithm selectCipherAlgorithm() {
// shown after algorithm name and description.
// xgroup(setup)
_(" -- 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()) {
cout << autosprintf(
// shown after algorithm name and description.
// xgroup(setup)
_(" -- block size %i bytes"), it->blockSize.min()) << "\n";
_(" -- block size %i bytes"), it->blockSize.min())
<< "\n";
} else {
cout << autosprintf(
// shown after algorithm name and description.
// xgroup(setup)
_(" -- 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(
// xgroup(setup)
_("Using filesystem block size of %i bytes"),
alg.blockSize.min()) << "\n";
alg.blockSize.min())
<< "\n";
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"
"within a block will be caught and will cause a read error."));
} else {
cout << "\n\n" << _("You specified --require-macs. "
"Enabling block authentication code headers...")
cout << "\n\n"
<< _("You specified --require-macs. "
"Enabling block authentication code headers...")
<< "\n\n";
addMAC = true;
}
@ -950,7 +948,8 @@ static bool selectZeroBlockPassThrough() {
"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;
bool enableIdleTracking = opts->idleTracking;
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 (reverseEncryption) {
rError(_("Paranoia configuration not supported for reverse encryption"));
cerr << _("Paranoia configuration not supported for reverse encryption");
return rootInfo;
}
@ -1022,7 +1021,7 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
blockSize = DefaultBlockSize;
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)
nameIOIface = BlockNameIO::CurrentInterface(true);
#else
@ -1042,7 +1041,7 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
blockSize = DefaultBlockSize;
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)
nameIOIface = BlockNameIO::CurrentInterface(true);
#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) {
rError(_("Unable to instanciate cipher %s, key size %i, block size %i"),
alg.name.c_str(), keySize, blockSize);
cerr << autosprintf(
_("Unable to instanciate cipher %s, key size %i, block size %i"),
alg.name.c_str(), keySize, blockSize);
return rootInfo;
} else {
rDebug("Using cipher %s, key size %i, block size %i", alg.name.c_str(),
keySize, blockSize);
VLOG(1) << "Using cipher " << alg.name << ", key size " << keySize
<< ", block size " << blockSize;
}
shared_ptr<EncFSConfig> config(new EncFSConfig);
std::shared_ptr<EncFSConfig> config(new EncFSConfig);
config->cfgType = Config_V6;
config->cipherIface = cipher->interface();
@ -1129,7 +1129,8 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
cout << "\n";
// xgroup(setup)
cout << _("Configuration finished. The filesystem to be created has\n"
"the following properties:") << endl;
"the following properties:")
<< endl;
showFSInfo(config.get());
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"
"more information, please see the encfs mailing list.\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;
}
@ -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
CipherKey userKey;
rDebug("useStdin: %i", useStdin);
VLOG(1) << "useStdin: " << useStdin;
if (useStdin) {
if (annotate) cerr << "$PROMPT$ new_passwd" << endl;
userKey = config->getUserKey(useStdin);
@ -1174,19 +1176,21 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
delete[] encodedKey;
if (!volumeKey) {
rWarning(
_("Failure generating new volume key! "
"Please report this error."));
cerr << _(
"Failure generating new volume key! "
"Please report this error.");
return rootInfo;
}
if (!saveConfig(Config_V6, rootDir, config.get())) return rootInfo;
if (!saveConfig(Config_V6, rootDir, config.get())) {
return rootInfo;
}
// fill in config struct
shared_ptr<NameIO> nameCoder =
std::shared_ptr<NameIO> nameCoder =
NameIO::New(config->nameIface, cipher, volumeKey);
if (!nameCoder) {
rWarning(_("Name coding interface not supported"));
cerr << _("Name coding interface not supported");
cout << _("The filename encoding interface requested is not available")
<< endl;
return rootInfo;
@ -1208,13 +1212,14 @@ RootPtr createV6Config(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
rootInfo = RootPtr(new EncFS_Root);
rootInfo->cipher = cipher;
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;
}
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(
// xgroup(diag)
@ -1243,7 +1248,7 @@ void showFSInfo(const EncFSConfig *config) {
config->nameIface.revision(), config->nameIface.age());
// check if we support the filename encoding interface..
shared_ptr<NameIO> nameCoder =
std::shared_ptr<NameIO> nameCoder =
NameIO::New(config->nameIface, cipher, CipherKey());
if (!nameCoder) {
// xgroup(diag)
@ -1269,7 +1274,8 @@ void showFSInfo(const EncFSConfig *config) {
}
if (config->kdfIterations > 0 && config->salt.size() > 0) {
cout << autosprintf(_("Using PBKDF2, with %i iterations"),
config->kdfIterations) << "\n";
config->kdfIterations)
<< "\n";
cout << autosprintf(_("Salt Size: %i bits"), (int)(8 * config->salt.size()))
<< "\n";
}
@ -1279,14 +1285,16 @@ void showFSInfo(const EncFSConfig *config) {
// xgroup(diag)
_("Block Size: %i bytes + %i byte MAC header"),
config->blockSize,
config->blockMACBytes + config->blockMACRandBytes) << endl;
config->blockMACBytes + config->blockMACRandBytes)
<< endl;
} else {
// new version stores the header as part of that block size..
cout << autosprintf(
// xgroup(diag)
_("Block Size: %i bytes, including %i byte MAC header"),
config->blockSize,
config->blockMACBytes + config->blockMACRandBytes) << endl;
config->blockMACBytes + config->blockMACRandBytes)
<< endl;
}
} else {
// xgroup(diag)
@ -1312,8 +1320,7 @@ void showFSInfo(const EncFSConfig *config) {
}
cout << "\n";
}
shared_ptr<Cipher> EncFSConfig::getCipher() const {
std::shared_ptr<Cipher> EncFSConfig::getCipher() const {
return Cipher::New(cipherIface, keySize);
}
@ -1339,7 +1346,7 @@ unsigned char *EncFSConfig::getSaltData() const {
CipherKey EncFSConfig::makeKey(const char *password, int passwdLen) {
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
// FS type, then initialize salt..
@ -1427,7 +1434,7 @@ CipherKey EncFSConfig::getUserKey(const std::string &passProg,
perror(_("Internal error: socketpair() failed"));
return result;
}
rDebug("getUserKey: fds = %i, %i", fds[0], fds[1]);
VLOG(1) << "getUserKey: fds = " << fds[0] << ", " << fds[1];
pid = fork();
if (pid == -1) {
@ -1518,9 +1525,9 @@ CipherKey EncFSConfig::getNewUserKey() {
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;
shared_ptr<EncFSConfig> config(new EncFSConfig);
std::shared_ptr<EncFSConfig> config(new EncFSConfig);
if (readConfig(opts->rootDir, config.get()) != Config_None) {
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.
shared_ptr<Cipher> cipher = config->getCipher();
std::shared_ptr<Cipher> cipher = config->getCipher();
if (!cipher) {
rError(_("Unable to find cipher %s, version %i:%i:%i"),
config->cipherIface.name().c_str(), config->cipherIface.current(),
config->cipherIface.revision(), config->cipherIface.age());
cerr << autosprintf(
_("Unable to find cipher %s, version %i:%i:%i"),
config->cipherIface.name().c_str(), config->cipherIface.current(),
config->cipherIface.revision(), config->cipherIface.age());
// xgroup(diag)
cout << _("The requested cipher interface is not available\n");
return rootInfo;
@ -1552,7 +1560,7 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
if (opts->delayMount) {
rootInfo = RootPtr(new EncFS_Root);
rootInfo->cipher = cipher;
rootInfo->root = shared_ptr<DirNode>();
rootInfo->root = std::shared_ptr<DirNode>();
return rootInfo;
}
@ -1560,7 +1568,7 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
CipherKey userKey;
if (opts->passwordProgram.empty()) {
rDebug("useStdin: %i", opts->useStdin);
VLOG(1) << "useStdin: " << opts->useStdin;
if (opts->annotate) cerr << "$PROMPT$ passwd" << endl;
userKey = config->getUserKey(opts->useStdin);
} else
@ -1568,7 +1576,7 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
if (!userKey) return rootInfo;
rDebug("cipher key size = %i", cipher->encodedKeySize());
VLOG(1) << "cipher key size = " << cipher->encodedKeySize();
// decode volume key..
CipherKey volumeKey =
cipher->readKey(config->getKeyData(), userKey, opts->checkKey);
@ -1580,12 +1588,13 @@ RootPtr initFS(EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts) {
return rootInfo;
}
shared_ptr<NameIO> nameCoder =
std::shared_ptr<NameIO> nameCoder =
NameIO::New(config->nameIface, cipher, volumeKey);
if (!nameCoder) {
rError(_("Unable to find nameio interface %s, version %i:%i:%i"),
config->nameIface.name().c_str(), config->nameIface.current(),
config->nameIface.revision(), config->nameIface.age());
cerr << autosprintf(
_("Unable to find nameio interface '%s', version %i:%i:%i"),
config->nameIface.name().c_str(), config->nameIface.current(),
config->nameIface.revision(), config->nameIface.age());
// xgroup(diag)
cout << _(
"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->volumeKey = volumeKey;
rootInfo->root =
shared_ptr<DirNode>(new DirNode(ctx, opts->rootDir, fsConfig));
std::shared_ptr<DirNode>(new DirNode(ctx, opts->rootDir, fsConfig));
} else {
if (opts->createIfNotFound) {
// 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) {
rDebug("Attempting to reinitialize filesystem");
VLOG(1) << "Attempting to reinitialize filesystem";
RootPtr rootInfo = initFS(ctx, ctx->opts);
if (rootInfo) {
ctx->setRoot(rootInfo->root);
return 0;
} else {
rInfo(_("Remount failed"));
RLOG(INFO) << "Remount failed";
return -EACCES;
}
}
} // namespace encfs

View File

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

View File

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

View File

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

View File

@ -20,29 +20,23 @@
#include "MACFileIO.h"
#include <inttypes.h>
#include <rlog/Error.h>
#include <rlog/rlog.h>
#include <sys/stat.h>
#include "internal/easylogging++.h"
#include <cstring>
#include <inttypes.h>
#include <sys/stat.h>
#include "BlockFileIO.h"
#include "Cipher.h"
#include "Error.h"
#include "FileIO.h"
#include "FileUtils.h"
#include "MemoryPool.h"
#include "i18n.h"
namespace rlog {
class RLogChannel;
} // namespace rlog
using namespace rlog;
using namespace rel;
using namespace std;
static RLogChannel *Info = DEF_CHANNEL("info/MACFileIO", Log_Info);
//
namespace encfs {
// Version 1.0 worked on blocks of size (blockSize + headerSize).
// That is, it took [blockSize] worth of user data and added headers.
// 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
// 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) {
return cfg->config->blockSize - cfg->config->blockMACBytes -
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),
base(_base),
cipher(cfg->cipher),
@ -72,14 +67,14 @@ MACFileIO::MACFileIO(const shared_ptr<FileIO> &_base, const FSConfigPtr &cfg)
warnOnly(cfg->opts->forceDecode) {
rAssert(macBytes >= 0 && macBytes <= 8);
rAssert(randBytes >= 0);
rLog(Info, "fs block size = %i, macBytes = %i, randBytes = %i",
cfg->config->blockSize, cfg->config->blockMACBytes,
cfg->config->blockMACRandBytes);
VLOG(1) << "fs block size = " << cfg->config->blockSize
<< ", macBytes = " << cfg->config->blockMACBytes
<< ", randBytes = " << cfg->config->blockMACRandBytes;
}
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); }
@ -192,10 +187,10 @@ ssize_t MACFileIO::readOneBlock(const IORequest &req) const {
if (fail > 0) {
// uh oh..
long blockNum = req.offset / bs;
rWarning(_("MAC comparison failure in block %li"), blockNum);
RLOG(WARNING) << "MAC comparison failure in block " << blockNum;
if (!warnOnly) {
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;
memcpy(req.data, tmp.data + headerSize, readSize);
} else {
rDebug("readSize %i at offset %" PRIi64, (int)readSize, req.offset);
VLOG(1) << "readSize " << readSize << " at offset " << req.offset;
if (readSize > 0) readSize = 0;
}
@ -264,3 +259,5 @@ int MACFileIO::truncate(off_t size) {
}
bool MACFileIO::isWritable() const { return base->isWritable(); }
} // namespace encfs

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,15 +24,17 @@
#include <memory>
#include "CipherKey.h"
#include "Error.h"
#include "NameIO.h"
namespace encfs {
class Cipher;
using namespace rel;
static shared_ptr<NameIO> NewNNIO(const Interface &, const shared_ptr<Cipher> &,
const CipherKey &) {
return shared_ptr<NameIO>(new NullNameIO());
static std::shared_ptr<NameIO> NewNNIO(const Interface &,
const std::shared_ptr<Cipher> &,
const CipherKey &) {
return std::shared_ptr<NameIO>(new NullNameIO());
}
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; }
} // namespace encfs

View File

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

View File

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

View File

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

View File

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

View File

@ -18,6 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "internal/easylogging++.h"
#include <cstring>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/evp.h>
@ -25,27 +27,21 @@
#include <openssl/ossl_typ.h>
#include <openssl/rand.h>
#include <pthread.h>
#include <rlog/Error.h>
#include <rlog/rlog.h>
#include <string>
#include <sys/mman.h>
#include <sys/time.h>
#include <cstring>
#include <string>
#include "Cipher.h"
#include "Error.h"
#include "Interface.h"
#include "Mutex.h"
#include "Range.h"
#include "SSL_Cipher.h"
#include "intl/gettext.h"
namespace rlog {
class RLogChannel;
} // namespace rlog
using namespace std;
using namespace rel;
using namespace rlog;
namespace encfs {
const int MAX_KEYLENGTH = 32; // in bytes (256 bit)
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 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;
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 *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));
}
@ -186,7 +182,8 @@ static bool BF_Cipher_registered =
static Range AESKeyRange(128, 256, 64);
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;
keyLen = AESKeyRange.closest(keyLen);
@ -212,8 +209,8 @@ static shared_ptr<Cipher> NewAESCipher(const Interface &iface, int keyLen) {
break;
}
return shared_ptr<Cipher>(new SSL_Cipher(iface, AESInterface, blockCipher,
streamCipher, keyLen / 8));
return std::shared_ptr<Cipher>(new SSL_Cipher(
iface, AESInterface, blockCipher, streamCipher, keyLen / 8));
}
static bool AES_Cipher_registered =
@ -275,14 +272,14 @@ SSLKey::~SSLKey() {
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;
}
inline unsigned char *IVData(const shared_ptr<SSLKey> &key) {
inline unsigned char *IVData(const std::shared_ptr<SSLKey> &key) {
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) {
Lock lock(key->mutex);
// 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);
}
static RLogChannel *CipherInfo = DEF_CHANNEL("info/cipher", Log_Info);
SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_,
const EVP_CIPHER *blockCipher,
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);
rLog(CipherInfo, "allocated cipher %s, keySize %i, ivlength %i",
iface.name().c_str(), _keySize, _ivLength);
VLOG(1) << "allocated cipher " << iface.name() << ", keySize " << _keySize
<< ", ivlength " << _ivLength;
if ((EVP_CIPHER_key_length(_blockCipher) != (int)_keySize) &&
iface.current() == 1) {
rWarning(
"Running in backward compatibilty mode for 1.0 - \n"
"key is really %i bits, not %i.\n"
"Consider creating a new filesystem and moving your data.",
EVP_CIPHER_key_length(_blockCipher) * 8, _keySize * 8);
RLOG(WARNING) << "Running in backward compatibilty mode for 1.0 - "
"key is really "
<< EVP_CIPHER_key_length(_blockCipher) * 8 << " bits, not "
<< _keySize * 8;
}
}
@ -357,7 +351,7 @@ Interface SSL_Cipher::interface() const { return realIface; }
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
int &iterationCount, long desiredDuration,
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) {
// 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,
KeyData(key), 1000 * desiredDuration);
if (res <= 0) {
rWarning("openssl error, PBKDF2 failed");
RLOG(WARNING) << "openssl error, PBKDF2 failed";
return CipherKey();
} else
iterationCount = res;
@ -374,7 +368,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
if (PKCS5_PBKDF2_HMAC_SHA1(
password, passwdLength, const_cast<unsigned char *>(salt), saltLen,
iterationCount, _keySize + _ivLength, KeyData(key)) != 1) {
rWarning("openssl error, PBKDF2 failed");
RLOG(WARNING) << "openssl error, PBKDF2 failed";
return CipherKey();
}
}
@ -385,7 +379,7 @@ 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;
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..
if (bytes != (int)_keySize) {
rWarning("newKey: BytesToKey returned %i, expecting %i key bytes", bytes,
_keySize);
RLOG(WARNING) << "newKey: BytesToKey returned " << bytes << ", expecting "
<< _keySize << " key bytes";
}
} else {
// 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))
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 reproducable..
if (PKCS5_PBKDF2_HMAC_SHA1((char *)tmpBuf, bufLen, saltBuf, saltLen, 1000,
_keySize + _ivLength, KeyData(key)) != 1) {
rWarning("openssl error, PBKDF2 failed");
RLOG(WARNING) << "openssl error, PBKDF2 failed";
return CipherKey();
}
@ -496,25 +490,28 @@ bool SSL_Cipher::randomize(unsigned char *buf, int len,
// to avoid warnings of uninitialized data from valgrind
memset(buf, 0, len);
int result;
if (strongRandom)
if (strongRandom) {
result = RAND_bytes(buf, len);
else
} else {
result = RAND_pseudo_bytes(buf, len);
}
if (result != 1) {
char errStr[120]; // specs require string at least 120 bytes long..
unsigned long errVal = 0;
if ((errVal = ERR_get_error()) != 0)
rWarning("openssl error: %s", ERR_error_string(errVal, errStr));
if ((errVal = ERR_get_error()) != 0) {
RLOG(WARNING) << "openssl error: " << ERR_error_string(errVal, errStr);
}
return false;
} else
} else {
return true;
}
}
uint64_t SSL_Cipher::MAC_64(const unsigned char *data, int len,
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);
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,
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);
unsigned char tmpBuf[MAX_KEYLENGTH + MAX_IVLENGTH];
@ -540,13 +537,14 @@ CipherKey SSL_Cipher::readKey(const unsigned char *data,
// check for success
unsigned int checksum2 = MAC_32(tmpBuf, _keySize + _ivLength, masterKey);
if (checksum2 != checksum && checkKey) {
rDebug("checksum mismatch: expected %u, got %u", checksum, checksum2);
rDebug("on decode of %i bytes", _keySize + _ivLength);
VLOG(1) << "checksum mismatch: expected " << checksum << ", got "
<< checksum2;
VLOG(1) << "on decode of " << _keySize + _ivLength << " bytes";
memset(tmpBuf, 0, sizeof(tmpBuf));
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);
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,
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->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->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 {
shared_ptr<SSLKey> key1 = dynamic_pointer_cast<SSLKey>(A);
shared_ptr<SSLKey> key2 = dynamic_pointer_cast<SSLKey>(B);
std::shared_ptr<SSLKey> key1 = dynamic_pointer_cast<SSLKey>(A);
std::shared_ptr<SSLKey> key2 = dynamic_pointer_cast<SSLKey>(B);
rAssert(key1->keySize == _keySize);
rAssert(key2->keySize == _keySize);
@ -625,7 +623,7 @@ int SSL_Cipher::cipherBlockSize() const {
* requirement for "seed" is that is must be unique.
*/
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) {
memcpy(ivec, IVData(key), _ivLength);
@ -657,7 +655,7 @@ void SSL_Cipher::setIVec(unsigned char *ivec, uint64_t seed,
decrypting the file).
*/
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)
Golumb rulers, the idea being to spread around the information in the
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,
const CipherKey &ckey) const {
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->ivLength == _ivLength);
@ -747,8 +745,8 @@ bool SSL_Cipher::streamEncode(unsigned char *buf, int size, uint64_t iv64,
dstLen += tmpLen;
if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen,
tmpLen);
RLOG(ERROR) << "encoding " << size << " bytes, got back " << dstLen << " ("
<< tmpLen << " in final_ex)";
}
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,
const CipherKey &ckey) const {
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->ivLength == _ivLength);
@ -783,8 +781,8 @@ bool SSL_Cipher::streamDecode(unsigned char *buf, int size, uint64_t iv64,
dstLen += tmpLen;
if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen,
tmpLen);
RLOG(ERROR) << "decoding " << size << " bytes, got back " << dstLen << " ("
<< tmpLen << " in final_ex)";
}
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,
const CipherKey &ckey) const {
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->ivLength == _ivLength);
// data must be integer number of blocks
const int blockMod = size % EVP_CIPHER_CTX_block_size(&key->block_enc);
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);
@ -815,8 +813,8 @@ bool SSL_Cipher::blockEncode(unsigned char *buf, int size, uint64_t iv64,
dstLen += tmpLen;
if (dstLen != size) {
rError("encoding %i bytes, got back %i (%i in final_ex)", size, dstLen,
tmpLen);
RLOG(ERROR) << "encoding " << size << " bytes, got back " << dstLen << " ("
<< tmpLen << " in final_ex)";
}
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,
const CipherKey &ckey) const {
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->ivLength == _ivLength);
// data must be integer number of blocks
const int blockMod = size % EVP_CIPHER_CTX_block_size(&key->block_dec);
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);
@ -847,11 +845,13 @@ bool SSL_Cipher::blockDecode(unsigned char *buf, int size, uint64_t iv64,
dstLen += tmpLen;
if (dstLen != size) {
rError("decoding %i bytes, got back %i (%i in final_ex)", size, dstLen,
tmpLen);
RLOG(ERROR) << "decoding " << size << " bytes, got back " << dstLen << " ("
<< tmpLen << " in final_ex)";
}
return true;
}
bool SSL_Cipher::Enabled() { return true; }
} // namespace encfs

View File

@ -21,20 +21,23 @@
#ifndef _SSL_Cipher_incl_
#define _SSL_Cipher_incl_
#include <stdint.h>
#include <memory>
#include <stdint.h>
#include "Cipher.h"
#include "CipherKey.h"
#include "Interface.h"
class SSLKey;
#ifndef EVP_CIPHER
struct evp_cipher_st;
typedef struct evp_cipher_st EVP_CIPHER;
#endif
namespace encfs {
class SSLKey;
/*
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.
*/
class SSL_Cipher : public Cipher {
rel::Interface iface;
rel::Interface realIface;
Interface iface;
Interface realIface;
const EVP_CIPHER *_blockCipher;
const EVP_CIPHER *_streamCipher;
unsigned int _keySize; // in bytes
unsigned int _ivLength;
public:
SSL_Cipher(const rel::Interface &iface, const rel::Interface &realIface,
SSL_Cipher(const Interface &iface, const Interface &realIface,
const EVP_CIPHER *blockCipher, const EVP_CIPHER *streamCipher,
int keyLength);
virtual ~SSL_Cipher();
// returns the real interface, not the one we're emulating (if any)..
virtual rel::Interface interface() const;
virtual Interface interface() const;
// create a new key based on a password
virtual CipherKey newKey(const char *password, int passwdLength,
@ -140,11 +143,13 @@ class SSL_Cipher : public Cipher {
private:
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
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,8 +21,10 @@
#ifndef _base64_incl_
#define _base64_incl_
#include <string>
#include <vector>
#include <string> // for string
#include <vector> // for vector
namespace encfs {
inline int B64ToB256Bytes(int numB64Bytes) {
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.
// Used only to decode legacy Boost XML serialized config format.
// 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);
} // namespace encfs
#endif

View File

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

View File

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

View File

@ -17,19 +17,16 @@
#include <fcntl.h>
#include <getopt.h>
#include <iostream>
#include <limits.h>
#include <rlog/RLogChannel.h>
#include <rlog/StdioNode.h>
#include <rlog/rlog.h>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#define NO_DES
@ -38,6 +35,7 @@
#include "Cipher.h"
#include "CipherKey.h"
#include "DirNode.h"
#include "Error.h"
#include "FSConfig.h"
#include "FileNode.h"
#include "FileUtils.h"
@ -51,9 +49,11 @@
#define PATH_MAX 4096
#endif
using namespace rlog;
using namespace std;
using gnu::autosprintf;
using namespace encfs;
INITIALIZE_EASYLOGGINGPP
static int showInfo(int argc, char **argv);
static int showVersion(int argc, char **argv);
@ -76,47 +76,45 @@ struct CommandOpts {
const char *argStr;
const char *usageStr;
} commands[] = {
{"info", 1, 1, showInfo, "(root dir)",
// xgroup(usage)
gettext_noop(" -- show information (Default command)")},
{"showKey", 1, 1, cmd_showKey, "(root dir)",
// xgroup(usage)
gettext_noop(" -- show key")},
{"passwd", 1, 1, chpasswd, "(root dir)",
// xgroup(usage)
gettext_noop(" -- change password for volume")},
{"autopasswd", 1, 1, chpasswdAutomaticly, "(root dir)",
// xgroup(usage)
gettext_noop(
" -- change password for volume, taking password"
" from standard input.\n\tNo prompts are issued.")},
{"autocheckpasswd", 1, 1, ckpasswdAutomaticly, "(root dir)",
// xgroup(usage)
gettext_noop(
" -- check password for volume, taking password"
" from standard input.\n\tNo prompts are issued.")},
{"ls", 1, 2, cmd_ls, 0, 0},
{"showcruft", 1, 1, cmd_showcruft, "(root dir)",
// xgroup(usage)
gettext_noop(" -- show undecodable filenames in the volume")},
{"cat", 2, 3, cmd_cat, "[--extpass=prog] (root dir) path",
// xgroup(usage)
gettext_noop(" -- decodes the file and cats it to standard out")},
{"decode", 1, 100, cmd_decode,
"[--extpass=prog] (root dir) [encoded-name ...]",
// xgroup(usage)
gettext_noop(" -- decodes name and prints plaintext version")},
{"encode", 1, 100, cmd_encode,
"[--extpass=prog] (root dir) [plaintext-name ...]",
// xgroup(usage)
gettext_noop(" -- encodes a filename and print result")},
{"export", 2, 2, cmd_export, "(root dir) path",
// xgroup(usage)
gettext_noop(" -- decrypts a volume and writes results to path")},
{"--version", 0, 0, showVersion, "",
// xgroup(usage)
gettext_noop(" -- print version number and exit")},
{0, 0, 0, 0, 0, 0}};
{"info", 1, 1, showInfo, "(root dir)",
// xgroup(usage)
gettext_noop(" -- show information (Default command)")},
{"showKey", 1, 1, cmd_showKey, "(root dir)",
// xgroup(usage)
gettext_noop(" -- show key")},
{"passwd", 1, 1, chpasswd, "(root dir)",
// xgroup(usage)
gettext_noop(" -- change password for volume")},
{"autopasswd", 1, 1, chpasswdAutomaticly, "(root dir)",
// xgroup(usage)
gettext_noop(" -- change password for volume, taking password"
" from standard input.\n\tNo prompts are issued.")},
{"autocheckpasswd", 1, 1, ckpasswdAutomaticly, "(root dir)",
// xgroup(usage)
gettext_noop(" -- check password for volume, taking password"
" from standard input.\n\tNo prompts are issued.")},
{"ls", 1, 2, cmd_ls, 0, 0},
{"showcruft", 1, 1, cmd_showcruft, "(root dir)",
// xgroup(usage)
gettext_noop(" -- show undecodable filenames in the volume")},
{"cat", 2, 3, cmd_cat, "[--extpass=prog] (root dir) path",
// xgroup(usage)
gettext_noop(" -- decodes the file and cats it to standard out")},
{"decode", 1, 100, cmd_decode,
"[--extpass=prog] (root dir) [encoded-name ...]",
// xgroup(usage)
gettext_noop(" -- decodes name and prints plaintext version")},
{"encode", 1, 100, cmd_encode,
"[--extpass=prog] (root dir) [plaintext-name ...]",
// xgroup(usage)
gettext_noop(" -- encodes a filename and print result")},
{"export", 2, 2, cmd_export, "(root dir) path",
// xgroup(usage)
gettext_noop(" -- decrypts a volume and writes results to path")},
{"--version", 0, 0, showVersion, "",
// xgroup(usage)
gettext_noop(" -- print version number and exit")},
{0, 0, 0, 0, 0, 0}};
static void usage(const char *name) {
cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n"
@ -167,7 +165,7 @@ static int showInfo(int argc, char **argv) {
string rootDir = argv[1];
if (!checkDir(rootDir)) return EXIT_FAILURE;
EncFSConfig* config = new EncFSConfig;
EncFSConfig *config = new EncFSConfig;
ConfigType type = readConfig(rootDir, config);
// show information stored in config..
@ -184,38 +182,43 @@ static int showInfo(int argc, char **argv) {
return EXIT_FAILURE;
case Config_V3:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 3 configuration; "
"created by %s\n"),
config->creator.c_str());
cout << "\n"
<< autosprintf(_("Version 3 configuration; "
"created by %s\n"),
config->creator.c_str());
break;
case Config_V4:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 4 configuration; "
"created by %s\n"),
config->creator.c_str());
cout << "\n"
<< autosprintf(_("Version 4 configuration; "
"created by %s\n"),
config->creator.c_str());
break;
case Config_V5:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 5 configuration; "
"created by %s (revision %i)\n"),
config->creator.c_str(), config->subVersion);
cout << "\n"
<< autosprintf(_("Version 5 configuration; "
"created by %s (revision %i)\n"),
config->creator.c_str(), config->subVersion);
break;
case Config_V6:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 6 configuration; "
"created by %s (revision %i)\n"),
config->creator.c_str(), config->subVersion);
cout << "\n"
<< autosprintf(_("Version 6 configuration; "
"created by %s (revision %i)\n"),
config->creator.c_str(), config->subVersion);
break;
}
showFSInfo(config);
delete config;
return EXIT_SUCCESS;
}
static RootPtr initRootInfo(int &argc, char **&argv) {
RootPtr result;
shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
std::shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
opts->createIfNotFound = false;
opts->checkKey = false;
@ -232,7 +235,7 @@ static RootPtr initRootInfo(int &argc, char **&argv) {
opts->passwordProgram.assign(optarg);
break;
default:
rWarning(_("getopt error: %i"), res);
RLOG(WARNING) << "getopt error: " << res;
break;
}
}
@ -262,7 +265,7 @@ static RootPtr initRootInfo(const char *crootDir) {
RootPtr result;
if (checkDir(rootDir)) {
shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
std::shared_ptr<EncFS_Opts> opts(new EncFS_Opts());
opts->rootDir = rootDir;
opts->createIfNotFound = false;
opts->checkKey = false;
@ -341,7 +344,7 @@ static int cmd_ls(int argc, char **argv) {
if (dt.valid()) {
for (string name = dt.nextPlaintextName(); !name.empty();
name = dt.nextPlaintextName()) {
shared_ptr<FileNode> fnode =
std::shared_ptr<FileNode> fnode =
rootInfo->root->lookupNode(name.c_str(), "encfsctl-ls");
struct stat 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
template <typename T>
int processContents(const shared_ptr<EncFS_Root> &rootInfo, const char *path,
T &op) {
int processContents(const std::shared_ptr<EncFS_Root> &rootInfo,
const char *path, T &op) {
int errCode = 0;
shared_ptr<FileNode> node =
std::shared_ptr<FileNode> node =
rootInfo->root->openNode(path, "encfsctl", O_RDONLY, &errCode);
if (!node) {
@ -421,8 +424,8 @@ static int cmd_cat(int argc, char **argv) {
}
static int copyLink(const struct stat &stBuf,
const shared_ptr<EncFS_Root> &rootInfo, const string &cpath,
const string &destName) {
const std::shared_ptr<EncFS_Root> &rootInfo,
const string &cpath, const string &destName) {
std::vector<char> buf(stBuf.st_size + 1, '\0');
int res = ::readlink(cpath.c_str(), buf.data(), stBuf.st_size);
if (res == -1) {
@ -442,9 +445,10 @@ static int copyLink(const struct stat &stBuf,
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) {
shared_ptr<FileNode> node = rootInfo->root->lookupNode(encfsName, "encfsctl");
std::shared_ptr<FileNode> node =
rootInfo->root->lookupNode(encfsName, "encfsctl");
if (!node) {
cerr << "unable to open " << encfsName << "\n";
@ -484,7 +488,7 @@ static bool endsWith(const string &str, char 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) {
if (!endsWith(volumeDir, '/')) volumeDir.append("/");
if (!endsWith(destDir, '/')) destDir.append("/");
@ -493,7 +497,7 @@ static int traverseDirs(const shared_ptr<EncFS_Root> &rootInfo,
// with the same permissions
{
struct stat st;
shared_ptr<FileNode> dirNode =
std::shared_ptr<FileNode> dirNode =
rootInfo->root->lookupNode(volumeDir.c_str(), "encfsctl");
if (dirNode->getAttr(&st)) return EXIT_FAILURE;
@ -547,7 +551,8 @@ static int cmd_export(int argc, char **argv) {
return traverseDirs(rootInfo, "/", destDir);
}
int showcruft(const shared_ptr<EncFS_Root> &rootInfo, const char *dirName) {
int showcruft(const std::shared_ptr<EncFS_Root> &rootInfo,
const char *dirName) {
int found = 0;
DirTraverse dt = rootInfo->root->openDir(dirName);
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.
cerr << autosprintf(ngettext("Found %i invalid file.",
"Found %i invalid files.", filesFound),
filesFound) << "\n";
filesFound)
<< "\n";
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;
string rootDir = argv[1];
if (!checkDir(rootDir)) return EXIT_FAILURE;
EncFSConfig* config = new EncFSConfig;
EncFSConfig *config = new EncFSConfig;
ConfigType cfgType = readConfig(rootDir, config);
if (cfgType == Config_None) {
@ -626,7 +633,8 @@ static int do_chpasswd(bool useStdin, bool annotate, bool checkOnly, int argc, c
}
// 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) {
cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"),
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;
}
if(checkOnly)
{
if (checkOnly) {
cout << _("Password is correct\n");
return EXIT_SUCCESS;
}
@ -708,7 +715,8 @@ static int ckpasswdAutomaticly(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)
setlocale(LC_ALL, "");
@ -719,15 +727,19 @@ int main(int argc, char **argv) {
SSL_load_error_strings();
SSL_library_init();
StdioNode *slog = new StdioNode(STDERR_FILENO);
slog->subscribeTo(GetGlobalChannel("error"));
slog->subscribeTo(GetGlobalChannel("warning"));
if (argc < 2) {
usage(argv[0]);
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) == '-')) {
// default command when only 1 argument given -- treat the argument as
// a directory..
@ -747,7 +759,8 @@ int main(int argc, char **argv) {
(argc - 2 > commands[offset].maxOptions)) {
cerr << autosprintf(
_("Incorrect number of arguments for command \"%s\""),
argv[1]) << "\n";
argv[1])
<< "\n";
} else
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 <cstdio>
#include <cstring>
#include <exception>
#include <getopt.h>
#include <iostream>
#include <memory>
#include <pthread.h>
#include <sstream>
#include <stdlib.h>
#include <string>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "Context.h"
#include "Error.h"
#include "FileUtils.h"
#include "MemoryPool.h"
#include "autosprintf.h"
@ -46,8 +43,6 @@
#include "i18n.h"
#include "openssl.h"
class DirNode;
// Fuse version >= 26 requires another argument to fuse_unmount, which we
// don't have. So use the backward compatible call instead..
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
using namespace std;
using namespace rlog;
using namespace rel;
using namespace encfs;
using gnu::autosprintf;
INITIALIZE_EASYLOGGINGPP
namespace encfs {
class DirNode;
// Maximum number of arguments that we're going to pass on to fuse. Doesn't
// affect how many arguments we can handle, just how many we can pass on..
const int MaxFuseArgs = 32;
@ -74,14 +74,14 @@ const int MaxFuseArgs = 32;
* derived from the arguments
*/
struct EncFS_Args {
bool isDaemon; // true == spawn in background, log to syslog
bool isThreaded; // true == threaded
bool isVerbose; // false == only enable warning/error messages
int idleTimeout; // 0 == idle time in minutes to trigger unmount
bool isDaemon; // true == spawn in background, log to syslog
bool isThreaded; // true == threaded
bool isVerbose; // false == only enable warning/error messages
int idleTimeout; // 0 == idle time in minutes to trigger unmount
const char *fuseArgv[MaxFuseArgs];
int fuseArgc;
shared_ptr<EncFS_Opts> opts;
std::shared_ptr<EncFS_Opts> opts;
// for debugging
// 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;
} // namespace encfs
static void usage(const char *name) {
// xgroup(usage)
cerr << autosprintf(_("Build: encfs version %s"), VERSION) << "\n\n"
@ -117,7 +119,8 @@ static void usage(const char *name) {
<< autosprintf(
_("Usage: %s [options] rootDir mountPoint [-- [FUSE Mount "
"Options]]"),
name) << "\n\n"
name)
<< "\n\n"
// xgroup(usage)
<< _("Common Options:\n"
" -H\t\t\t"
@ -141,8 +144,9 @@ static void usage(const char *name) {
"\t\t\t(for filesystems using MAC block headers)\n")
<< _(" --public\t\t"
"act as a typical multi-user filesystem\n"
"\t\t\t(encfs must be run as root)\n") << _(" --reverse\t\t"
"reverse encryption\n")
"\t\t\t(encfs must be run as root)\n")
<< _(" --reverse\t\t"
"reverse encryption\n")
// xgroup(usage)
<< _(" --extpass=program\tUse external program for password prompt\n"
@ -151,13 +155,15 @@ static void usage(const char *name) {
" encfs ~/.crypt ~/crypt\n"
"\n")
// xgroup(usage)
<< _("For more information, see the man page encfs(1)") << "\n" << endl;
<< _("For more information, see the man page encfs(1)") << "\n"
<< endl;
}
static void FuseUsage() {
// xgroup(usage)
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;
const char *argv[] = {"...", "-h"};
@ -177,7 +183,7 @@ static string slashTerminate(const string &src) {
}
static bool processArgs(int argc, char *argv[],
const shared_ptr<EncFS_Args> &out) {
const std::shared_ptr<EncFS_Args> &out) {
// set defaults
out->isDaemon = true;
out->isThreaded = true;
@ -337,7 +343,7 @@ static bool processArgs(int argc, char *argv[],
break;
case 'P':
if (geteuid() != 0)
rWarning(_("option '--public' ignored for non-root user"));
RLOG(WARNING) << "option '--public' ignored for non-root user";
else {
out->opts->ownerCreate = true;
// add 'allow_other' option
@ -362,7 +368,7 @@ static bool processArgs(int argc, char *argv[],
// missing parameter for option..
break;
default:
rWarning(_("getopt error: %i"), res);
RLOG(WARNING) << "getopt error: " << res;
break;
}
}
@ -378,7 +384,7 @@ static bool processArgs(int argc, char *argv[],
out->opts->mountPoint = slashTerminate(argv[optind++]);
} else {
// no mount point specified
rWarning(_("Missing one or more arguments, aborting."));
cerr << _("Missing one or more arguments, aborting.");
return false;
}
@ -426,7 +432,8 @@ static bool processArgs(int argc, char *argv[],
cerr <<
// xgroup(usage)
_("When specifying daemon mode, you must use absolute paths "
"(beginning with '/')") << endl;
"(beginning with '/')")
<< endl;
return false;
}
@ -439,7 +446,8 @@ static bool processArgs(int argc, char *argv[],
cerr <<
// xgroup(usage)
_("The raw directory may not be a subdirectory of the "
"mount point.") << endl;
"mount point.")
<< endl;
return false;
}
}
@ -462,13 +470,13 @@ static bool processArgs(int argc, char *argv[],
if (!isDirectory(out->opts->rootDir.c_str()) &&
!userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(),
0700)) {
rWarning(_("Unable to locate root directory, aborting."));
cerr << _("Unable to locate root directory, aborting.");
return false;
}
if (!isDirectory(out->opts->mountPoint.c_str()) &&
!userAllowMkdir(out->opts->annotate ? 2 : 0, out->opts->mountPoint.c_str(),
0700)) {
rWarning(_("Unable to locate mount point, aborting."));
!userAllowMkdir(out->opts->annotate ? 2 : 0,
out->opts->mountPoint.c_str(), 0700)) {
cerr << _("Unable to locate mount point, aborting.");
return false;
}
@ -486,23 +494,27 @@ void *encfs_init(fuse_conn_info *conn) {
// set fuse connection options
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
// filesystem.
if (ctx->args->idleTimeout > 0) {
rDebug("starting idle monitoring thread");
VLOG(1) << "starting idle monitoring thread";
ctx->running = true;
int res = pthread_create(&ctx->monitorThread, 0, idleMonitor, (void *)ctx);
if (res != 0) {
rError(
"error starting idle monitor thread, "
"res = %i, errno = %i",
res, errno);
RLOG(ERROR) << "error starting idle monitor thread, "
"res = "
<< res << ", errno = " << errno;
}
}
if (ctx->args->isDaemon && oldStderr >= 0) {
rInfo("Closing stderr");
VLOG(1) << "Closing stderr";
close(oldStderr);
oldStderr = -1;
}
@ -516,19 +528,18 @@ void encfs_destroy(void *_ctx) {
ctx->running = false;
// 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_cond_signal(&ctx->wakeupCond);
pthread_mutex_unlock(&ctx->wakeupMutex);
rDebug("joining with idle monitoring thread");
VLOG(1) << "joining with idle monitoring thread";
pthread_join(ctx->monitorThread, 0);
rDebug("join done");
VLOG(1) << "join done";
}
}
int main(int argc, char *argv[]) {
// initialize the logging library
RLogInit(argc, argv);
encfs::initLogging();
#if defined(ENABLE_NLS) && defined(LOCALEDIR)
setlocale(LC_ALL, "");
@ -536,17 +547,9 @@ int main(int argc, char *argv[]) {
textdomain(PACKAGE);
#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
// 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)
encfsArgs->fuseArgv[i] = NULL; // libfuse expects null args..
@ -556,13 +559,11 @@ int main(int argc, char *argv[]) {
}
if (encfsArgs->isVerbose) {
// subscribe to more logging channels..
slog->subscribeTo(GetGlobalChannel("info"));
slog->subscribeTo(GetGlobalChannel("debug"));
el::Loggers::setVerboseLevel(1);
}
rDebug("Root directory: %s", encfsArgs->opts->rootDir.c_str());
rDebug("Fuse arguments: %s", encfsArgs->toString().c_str());
VLOG(1) << "Root directory: " << encfsArgs->opts->rootDir;
VLOG(1) << "Fuse arguments: " << encfsArgs->toString();
fuse_operations encfs_oper;
// 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.lock = encfs_lock;
encfs_oper.utimens = encfs_utimens;
// encfs_oper.bmap = encfs_bmap;
// encfs_oper.bmap = encfs_bmap;
openssl_init(encfsArgs->isThreaded);
// context is not a smart pointer because it will live for the life of
// the filesystem.
EncFS_Context *ctx = new EncFS_Context;
auto ctx = std::shared_ptr<EncFS_Context>(new EncFS_Context);
ctx->publicFilesystem = encfsArgs->opts->ownerCreate;
RootPtr rootInfo = initFS(ctx, encfsArgs->opts);
RootPtr rootInfo = initFS(ctx.get(), encfsArgs->opts);
int returnCode = EXIT_FAILURE;
@ -637,7 +638,8 @@ int main(int argc, char *argv[]) {
cerr << _("Note: requested single-threaded mode, but an idle\n"
"timeout was specified. The filesystem will operate\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
@ -645,14 +647,6 @@ int main(int argc, char *argv[]) {
umask(0);
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
// report a fatal condition later (fuse_main exits unexpectedly)...
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..
int res = fuse_main(encfsArgs->fuseArgc,
const_cast<char **>(encfsArgs->fuseArgv), &encfs_oper,
(void *)ctx);
(void *)ctx.get());
time(&endTime);
@ -692,16 +686,16 @@ int main(int argc, char *argv[]) {
fclose(out);
}
} catch (std::exception &ex) {
rError(_("Internal error: Caught exception from main loop: %s"),
ex.what());
RLOG(ERROR) << "Internal error: Caught exception from main loop: "
<< ex.what();
} catch (...) {
rError(_("Internal error: Caught unexpected exception"));
RLOG(ERROR) << "Internal error: Caught unexpected exception";
}
}
// cleanup so that we can check for leaked resources..
rootInfo.reset();
ctx->setRoot(shared_ptr<DirNode>());
ctx->setRoot(std::shared_ptr<DirNode>());
MemoryPool::destroyAll();
openssl_shutdown(encfsArgs->isThreaded);
@ -721,7 +715,7 @@ static bool unmountFS(EncFS_Context *ctx);
static void *idleMonitor(void *_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;
int idleCycles = 0;
@ -744,10 +738,11 @@ static void *idleMonitor(void *_arg) {
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;
gettimeofday(&currentTime, 0);
@ -759,24 +754,23 @@ static void *idleMonitor(void *_arg) {
pthread_mutex_unlock(&ctx->wakeupMutex);
rDebug("Idle monitoring thread exiting");
VLOG(1) << "Idle monitoring thread exiting";
return 0;
}
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) {
rDebug("Detaching filesystem %s due to inactivity",
arg->opts->mountPoint.c_str());
VLOG(1) << "Detaching filesystem due to inactivity: "
<< arg->opts->mountPoint;
ctx->setRoot(shared_ptr<DirNode>());
ctx->setRoot(std::shared_ptr<DirNode>());
return false;
} else {
// Time to unmount!
// xgroup(diag)
rWarning(_("Unmounting filesystem %s due to inactivity"),
arg->opts->mountPoint.c_str());
RLOG(WARNING) << "Unmounting filesystem due to inactivity: "
<< arg->opts->mountPoint;
fuse_unmount(arg->opts->mountPoint.c_str());
return true;
}

View File

@ -18,19 +18,22 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <memory>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include "Cipher.h"
#include "CipherKey.h"
#include "openssl.h"
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();
// encode with itself
@ -54,7 +57,7 @@ int main(int argc, char **argv) {
openssl_init(false);
// 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);
// openssl_shutdown(false);

View File

@ -22,7 +22,6 @@
#include <openssl/crypto.h>
#include <pthread.h>
#include <rlog/rlog.h>
#include <stdlib.h>
#define NO_DES
@ -32,6 +31,10 @@
#include <openssl/engine.h>
#endif
#include "Error.h"
namespace encfs {
unsigned long pthreads_thread_id() { return (unsigned long)pthread_self(); }
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;
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()];
for (int i = 0; i < CRYPTO_num_locks(); ++i)
pthread_mutex_init(crypto_locks + i, 0);
@ -94,3 +97,5 @@ void openssl_shutdown(bool threaded) {
if (threaded) pthreads_locking_cleanup();
}
} // namespace encfs

View File

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

View File

@ -37,16 +37,16 @@ static const char rcsid[] =
#ifndef HAVE_READPASSPHRASE
#include <fcntl.h>
#include <paths.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <cctype>
#include <cerrno>
#include <csignal>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <paths.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.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 <cstdlib>
#include <iostream>
@ -25,16 +23,14 @@
#include <memory>
#include <sstream>
#include <string>
#include <rlog/Error.h>
#include <rlog/RLogChannel.h>
#include <rlog/StdioNode.h>
#include <rlog/rlog.h>
#include <time.h>
#include <unistd.h>
#include "BlockNameIO.h"
#include "Cipher.h"
#include "CipherKey.h"
#include "DirNode.h"
#include "Error.h"
#include "FSConfig.h"
#include "FileUtils.h"
#include "Interface.h"
@ -42,6 +38,7 @@
#include "NameIO.h"
#include "Range.h"
#include "StreamNameIO.h"
#include "internal/easylogging++.h"
#define NO_DES
#include <openssl/ssl.h>
@ -50,13 +47,15 @@
#endif
using namespace std;
using namespace rel;
using namespace rlog;
using namespace encfs;
INITIALIZE_EASYLOGGINGPP
const int FSBlockSize = 256;
static int checkErrorPropogation(const shared_ptr<Cipher> &cipher, int size,
int byteToChange, const CipherKey &key) {
static int checkErrorPropogation(const std::shared_ptr<Cipher> &cipher,
int size, int byteToChange,
const CipherKey &key) {
MemBlock orig = MemoryPool::allocate(size);
MemBlock data = MemoryPool::allocate(size);
@ -132,7 +131,7 @@ static bool testNameCoding(DirNode &dirNode, bool verbose) {
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
if (verbose) {
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();
int encodedKeySize = cipher->encodedKeySize();
unsigned char *keyBuf = new unsigned char[encodedKeySize];
unsigned char keyBuf[encodedKeySize];
cipher->writeKey(key, 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();
int encodedKeySize = cipher->encodedKeySize();
unsigned char *keyBuf = new unsigned char[encodedKeySize];
unsigned char keyBuf[encodedKeySize];
cipher->writeKey(key, keyBuf, encodingKey);
@ -266,7 +265,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
if (!verbose) {
{
// 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));
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
fsCfg->nameCoding = shared_ptr<NameIO>(
fsCfg->nameCoding = std::shared_ptr<NameIO>(
new BlockNameIO(BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize()));
fsCfg->nameCoding->setChainedNameIV(false);
@ -331,7 +330,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
if (verbose) {
cerr << "modification of 1 byte affected between " << minChanges
<< " and " << maxChanges << " decoded bytes\n";
cerr << "minimum change at byte " << minAt << " and maximum at byte "
cerr << "minimum change at byte " << minAt << " and maximum at byte "
<< maxAt << "\n";
}
}
@ -357,7 +356,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose) {
if (verbose) {
cerr << "modification of 1 byte affected between " << minChanges
<< " and " << maxChanges << " decoded bytes\n";
cerr << "minimum change at byte " << minAt << " and maximum at byte "
cerr << "minimum change at byte " << minAt << " and maximum at byte "
<< maxAt << "\n";
}
}
@ -370,7 +369,7 @@ static bool testCipherSize(const string &name, int keySize, int 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) {
cerr << "FAILED TO CREATE\n";
return false;
@ -382,7 +381,7 @@ static bool testCipherSize(const string &name, int keySize, int blockSize,
cerr << "FAILED\n";
return false;
}
} catch (rlog::Error &er) {
} catch (encfs::Error &er) {
cerr << "Error: " << er.what() << "\n";
return false;
}
@ -391,14 +390,8 @@ static bool testCipherSize(const string &name, int keySize, int blockSize,
}
int main(int argc, char *argv[]) {
RLogInit(argc, argv);
StdioNode stdLog(STDERR_FILENO);
stdLog.subscribeTo(RLOG_CHANNEL("error"));
stdLog.subscribeTo(RLOG_CHANNEL("warning"));
#ifndef NO_DEBUG
stdLog.subscribeTo(RLOG_CHANNEL("debug"));
#endif
START_EASYLOGGINGPP(argc, argv);
encfs::initLogging();
SSL_load_error_strings();
SSL_library_init();
@ -442,7 +435,7 @@ int main(int argc, char *argv[]) {
}
// 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) {
cerr << "\nNo AES cipher found, skipping verbose test.\n";
} else {

6663
internal/easylogging++.h Executable file

File diff suppressed because it is too large Load Diff