1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
#pragma once
#include "crypto.h"
#include "lite_stream.h"
#include "mystring.h"
#include "myutils.h"
#include "platform.h"
#include "thread_safety_annotations.hpp"
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <cryptopp/aes.h>
#include <cryptopp/gcm.h>
#include <cryptopp/secblock.h>
namespace securefs
{
namespace lite
{
class THREAD_ANNOTATION_CAPABILITY("mutex") File
{
DISABLE_COPY_MOVE(File)
private:
securefs::optional<lite::AESGCMCryptStream>
m_crypt_stream THREAD_ANNOTATION_GUARDED_BY(*this);
std::shared_ptr<securefs::FileStream> m_file_stream THREAD_ANNOTATION_GUARDED_BY(*this);
std::mutex m_lock;
public:
explicit File(std::shared_ptr<securefs::FileStream> file_stream,
const key_type& master_key,
unsigned block_size,
unsigned iv_size,
bool check);
~File();
length_type size() const THREAD_ANNOTATION_REQUIRES(*this)
{
return m_crypt_stream->size();
}
void flush() THREAD_ANNOTATION_REQUIRES(*this) { m_crypt_stream->flush(); }
bool is_sparse() const noexcept THREAD_ANNOTATION_REQUIRES(*this)
{
return m_crypt_stream->is_sparse();
}
void resize(length_type len) THREAD_ANNOTATION_REQUIRES(*this)
{
m_crypt_stream->resize(len);
}
length_type read(void* output, offset_type off, length_type len)
THREAD_ANNOTATION_REQUIRES(*this)
{
return m_crypt_stream->read(output, off, len);
}
void write(const void* input, offset_type off, length_type len)
THREAD_ANNOTATION_REQUIRES(*this)
{
return m_crypt_stream->write(input, off, len);
}
void fstat(struct fuse_stat* stat) THREAD_ANNOTATION_REQUIRES(*this);
void fsync() THREAD_ANNOTATION_REQUIRES(*this) { m_file_stream->fsync(); }
void utimens(const fuse_timespec ts[2]) THREAD_ANNOTATION_REQUIRES(*this)
{
m_file_stream->utimens(ts);
}
void lock(bool exclusive = true) THREAD_ANNOTATION_ACQUIRE()
{
m_lock.lock();
try
{
m_file_stream->lock(exclusive);
}
catch (...)
{
m_lock.unlock();
throw;
}
}
void unlock() noexcept THREAD_ANNOTATION_RELEASE()
{
m_file_stream->unlock();
m_lock.unlock();
}
};
class FileSystem;
typedef std::unique_ptr<File> AutoClosedFile;
std::string encrypt_path(AES_SIV& encryptor, StringRef path);
std::string decrypt_path(AES_SIV& decryptor, StringRef path);
class InvalidFilenameException : public VerificationException
{
private:
std::string m_filename;
public:
explicit InvalidFilenameException(std::string filename) : m_filename(filename) {}
~InvalidFilenameException();
std::string message() const override;
int error_number() const noexcept override { return EINVAL; }
};
class FileSystem
{
DISABLE_COPY_MOVE(FileSystem)
private:
AES_SIV m_name_encryptor;
key_type m_content_key;
CryptoPP::GCM<CryptoPP::AES>::Encryption m_xattr_enc;
CryptoPP::GCM<CryptoPP::AES>::Decryption m_xattr_dec;
std::shared_ptr<const securefs::OSService> m_root;
unsigned m_block_size, m_iv_size;
unsigned m_flags;
private:
std::string translate_path(StringRef path, bool preserve_leading_slash);
public:
FileSystem(std::shared_ptr<const securefs::OSService> root,
const key_type& name_key,
const key_type& content_key,
const key_type& xattr_key,
unsigned block_size,
unsigned iv_size,
unsigned flags);
~FileSystem();
AutoClosedFile open(StringRef path, int flags, fuse_mode_t mode);
bool stat(StringRef path, struct fuse_stat* buf);
void mkdir(StringRef path, fuse_mode_t mode);
void rmdir(StringRef path);
void chmod(StringRef path, fuse_mode_t mode);
void chown(StringRef path, fuse_uid_t uid, fuse_gid_t gid);
void rename(StringRef from, StringRef to);
void unlink(StringRef path);
void symlink(StringRef to, StringRef from);
void link(StringRef src, StringRef dest);
size_t readlink(StringRef path, char* buf, size_t size);
void utimens(StringRef path, const fuse_timespec tm[2]);
void statvfs(struct fuse_statvfs* buf);
std::unique_ptr<DirectoryTraverser> create_traverser(StringRef path);
#ifdef __APPLE__
// These APIs, unlike all others, report errors through negative error numbers as defined in
// <errno.h>
ssize_t listxattr(const char* path, char* buf, size_t size) noexcept
{
return m_root->listxattr(translate_path(path, false).c_str(), buf, size);
}
ssize_t getxattr(const char* path, const char* name, void* buf, size_t size) noexcept;
int
setxattr(const char* path, const char* name, void* buf, size_t size, int flags) noexcept;
int removexattr(const char* path, const char* name) noexcept
{
return m_root->removexattr(translate_path(path, false).c_str(), name);
}
#endif
};
} // namespace lite
} // namespace securefs
|