mirror of
https://github.com/vgough/encfs.git
synced 2024-11-25 09:23:13 +01:00
Merge pull request #160 from vgough/glog
replace rlog with easylogging++
This commit is contained in:
commit
b70d4500bc
@ -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")
|
||||
|
||||
@ -53,19 +55,15 @@ include_directories (${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
if (USE_INTERNAL_TINYXML)
|
||||
message("-- Using local TinyXML2 copy")
|
||||
add_subdirectory(tinyxml2-3.0.0)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/tinyxml2-3.0.0)
|
||||
link_directories(${CMAKE_BINARY_DIR}/tinyxml2-3.0.0)
|
||||
add_subdirectory(internal/tinyxml2-3.0.0)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/internal/tinyxml2-3.0.0)
|
||||
link_directories(${CMAKE_BINARY_DIR}/internal/tinyxml2-3.0.0)
|
||||
set(TINYXML_LIBRARIES tinyxml2)
|
||||
else ()
|
||||
find_package (TinyXML REQUIRED)
|
||||
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")
|
||||
|
||||
|
55
COPYING
55
COPYING
@ -4,3 +4,58 @@ The main programs (encfs, encfsctl, etc) are licensed under the GPL.
|
||||
|
||||
For details of the licenses, see COPYING.LGPL and COPYING.GPL.
|
||||
|
||||
===========================================================================
|
||||
|
||||
The following 3rd party libraries are included in the EncFS source release
|
||||
from github:
|
||||
|
||||
* easylogging++ : a logging library, which is supplied with the following license
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 muflihun.com
|
||||
|
||||
https://github.com/easylogging/easyloggingpp
|
||||
http://easylogging.muflihun.com
|
||||
http://muflihun.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
* tinyxml2 : an XML reader / writer, which is supplied with the following license:
|
||||
|
||||
TinyXML-2 is released under the zlib license:
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
|
||||
|
13
INSTALL.md
13
INSTALL.md
@ -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.
|
||||
|
@ -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 ..
|
||||
|
@ -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:
|
||||
|
@ -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 )
|
@ -32,7 +32,6 @@ RUN apt-get -y upgrade \
|
||||
git \
|
||||
libfuse-dev \
|
||||
libssl-dev \
|
||||
librlog-dev \
|
||||
gettext \
|
||||
libgettextpo-dev \
|
||||
&& apt-get clean
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -20,6 +20,10 @@
|
||||
|
||||
#include "CipherKey.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
AbstractCipherKey::AbstractCipherKey() {}
|
||||
|
||||
AbstractCipherKey::~AbstractCipherKey() {}
|
||||
|
||||
} // namespace encfs
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
9
encfs/Error.cpp
Normal 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
44
encfs/Error.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -32,8 +32,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace gnu {
|
||||
/* A temporary object, usually allocated on the stack, representing
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
175
encfs/encfs.cpp
175
encfs/encfs.cpp
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
170
encfs/main.cpp
170
encfs/main.cpp
@ -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(¤tTime, 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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
@ -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
6663
internal/easylogging++.h
Executable file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user