Skip to content

Commit

Permalink
fix copy remaining from file
Browse files Browse the repository at this point in the history
fix examples doc
  • Loading branch information
radumarias committed May 2, 2024
1 parent 9291fc2 commit 709dfa1
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 142 deletions.
26 changes: 25 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "rencfs"
description = "An encrypted file system that mounts with FUSE on Linux. It can be used to create encrypted directories."
version = "0.3.1"
version = "0.3.2"
edition = "2021"
license = "Apache-2.0"
authors = ["Radu Marias <[email protected]>"]
Expand Down Expand Up @@ -33,6 +33,7 @@ bytes = "1.5"
tracing = { version = "0.1.40", features = ["max_level_trace", "release_max_level_info"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tracing-appender = "0.2.3"
tracing-test = "0.2.4"
ctrlc = { version = "3.1.9", features = ["termination"] }
sha2 = "0.11.0-pre.3"
strum = "0.26.2"
Expand Down
13 changes: 13 additions & 0 deletions examples/change_password.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use std::str::FromStr;
use secrecy::SecretString;
use rencfs::encryptedfs::{Cipher, EncryptedFs, FsError};

#[tokio::main]
async fn main() {
match EncryptedFs::change_password("/tmp/rencfs_data", SecretString::from_str("old-pass").unwrap(), SecretString::from_str("new-pass").unwrap(), Cipher::ChaCha20).await {
Ok(_) => println!("Password changed successfully"),
Err(FsError::InvalidPassword) => println!("Invalid old password"),
Err(FsError::InvalidDataDirStructure) => println!("Invalid structure of data directory"),
Err(err) => println!("Error: {err}"),
}
}
33 changes: 7 additions & 26 deletions src/encryptedfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ impl EncryptedFs {
Self::copy_remaining_of_file(&mut ctx, file_size, &self.cipher, &*self.key.get().await?, self.data_dir.join(CONTENTS_DIR).join(ino_str))?;
}

debug!("finishing encryptwarnor");
debug!("finishing encryptor");
ctx.encryptor.take().unwrap().finish()?;
// if we are in tmp file move it to actual file
let mut recreate_readers = false;
Expand Down Expand Up @@ -1221,8 +1221,7 @@ impl EncryptedFs {
let tmp_path = self.data_dir.join(CONTENTS_DIR).join(tmp_path_str);
let tmp_file = OpenOptions::new().write(true).create(true).truncate(true).open(tmp_path.clone())?;

let encryptor =
crypto_util::create_encryptor(tmp_file, &self.cipher, &*self.key.get().await?);
let encryptor = crypto_util::create_encryptor(tmp_file, &self.cipher, &*self.key.get().await?);
debug!("recreating encryptor");
ctx.encryptor.replace(encryptor);
ctx.pos = 0;
Expand Down Expand Up @@ -1270,15 +1269,10 @@ impl EncryptedFs {
}

#[instrument(skip(ctx, key))]
fn copy_remaining_of_file(ctx: &mut MutexGuard<WriteHandleContext>, mut end_offset: u64, cipher: &Cipher, key: &SecretVec<u8>, file: PathBuf) -> Result<(), FsError> {
fn copy_remaining_of_file(ctx: &mut MutexGuard<WriteHandleContext>, end_offset: u64, cipher: &Cipher, key: &SecretVec<u8>, file: PathBuf) -> Result<(), FsError> {
debug!("copy_remaining_of_file from file {}", file.to_str().unwrap());
let actual_file_size = fs::metadata(ctx.path.clone())?.len();
debug!("copy_remaining_of_file from {} to {}, file size {} actual file size {}", ctx.pos.to_formatted_string(&Locale::en), end_offset.to_formatted_string(&Locale::en), ctx.attr.size.to_formatted_string(&Locale::en), actual_file_size.to_formatted_string(&Locale::en));
// keep offset in file size bounds
if end_offset > ctx.attr.size {
debug!("end offset {} is bigger than file size {}", end_offset.to_formatted_string(&Locale::en), ctx.attr.size.to_formatted_string(&Locale::en));
end_offset = ctx.attr.size;
}
let actual_file_size = fs::metadata(file.clone())?.len();
debug!("copy_remaining_of_file from {} to {}, ctx file size {} actual file size {}", ctx.pos.to_formatted_string(&Locale::en), end_offset.to_formatted_string(&Locale::en), ctx.attr.size.to_formatted_string(&Locale::en), actual_file_size.to_formatted_string(&Locale::en));
if ctx.pos == end_offset {
debug!("no need to copy, pos {} end_offset {}", ctx.pos.to_formatted_string(&Locale::en), end_offset.to_formatted_string(&Locale::en));
// no-op
Expand All @@ -1289,7 +1283,7 @@ impl EncryptedFs {
// move read position to the write position
if ctx.pos > 0 {
let mut buffer = vec![0; BUF_SIZE];
let mut read_pos = 0u64;
let mut read_pos = 0_u64;
loop {
let len = min(buffer.len(), (ctx.pos - read_pos) as usize);
decryptor.read_exact(&mut buffer[..len]).map_err(|err| {
Expand All @@ -1307,6 +1301,7 @@ impl EncryptedFs {
// copy the rest of the file
let mut buffer = vec![0; BUF_SIZE];
loop {
debug!("reading from file pos {} end_offset {}", ctx.pos.to_formatted_string(&Locale::en), end_offset.to_formatted_string(&Locale::en));
let len = min(buffer.len(), (end_offset - ctx.pos) as usize);
decryptor.read_exact(&mut buffer[..len]).map_err(|err| {
debug!("error reading from file pos {} len {} {end_offset} file size {} actual file size {}",
Expand Down Expand Up @@ -1970,17 +1965,3 @@ fn merge_attr(attr: &mut FileAttr, set_attr: SetFileAttr) {
attr.flags = flags;
}
}

fn check_password(data_dir: &PathBuf, password: &SecretString, cipher: &Cipher) -> FsResult<()> {
let salt = crypto_util::hash_secret(password);
let initial_key = crypto_util::derive_key(password, cipher, salt)?;
let enc_file = data_dir.join(SECURITY_DIR).join(KEY_ENC_FILENAME);
let decryptor = crypto_util::create_decryptor(File::open(enc_file.clone())?, cipher, &initial_key);
let key_store: KeyStore = bincode::deserialize_from(decryptor).map_err(|_| FsError::InvalidPassword)?;
// check hash
if key_store.hash != crypto_util::hash(key_store.key.expose_secret()) {
return Err(FsError::InvalidPassword);
}

Ok(())
}
35 changes: 16 additions & 19 deletions src/encryptedfs/moved_test.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use tracing_test::traced_test;
use std::{fs, io};
use std::fs::OpenOptions;
use std::io::Read;
Expand All @@ -9,7 +10,7 @@ use std::sync::Arc;
use secrecy::{ExposeSecret, SecretString};
use tokio::sync::Mutex;

use crate::encryptedfs::{Cipher, CONTENTS_DIR, DirectoryEntry, DirectoryEntryPlus, EncryptedFs, FileAttr, FileType, FsError, FsResult, ROOT_INODE};
use crate::encryptedfs::{Cipher, CONTENTS_DIR, CreateFileAttr, DirectoryEntry, DirectoryEntryPlus, EncryptedFs, FileType, FsError, FsResult, PasswordProvider, ROOT_INODE};

const TESTS_DATA_DIR: &str = "/tmp/rencfs-test-data/";

Expand All @@ -29,7 +30,15 @@ async fn setup(setup: TestSetup) -> FsResult<SetupResult> {
fs::remove_dir_all(path)?;
}
fs::create_dir_all(path)?;
let fs = EncryptedFs::new(path, SecretString::from_str("pass-42").unwrap(), Cipher::ChaCha20).await?;

struct PasswordProviderImpl {}
impl PasswordProvider for PasswordProviderImpl {
fn get_password(&self) -> Option<SecretString> {
Some(SecretString::from_str("password").unwrap())
}
}

let fs = EncryptedFs::new(path, Box::new(PasswordProviderImpl {}), Cipher::ChaCha20).await?;

Ok(SetupResult {
fs: Some(fs),
Expand Down Expand Up @@ -71,30 +80,17 @@ async fn run_test<T>(init: TestSetup, t: T) -> FsResult<()>

thread_local!(static SETUP_RESULT: Arc<Mutex<Option<SetupResult>>> = Arc::new(Mutex::new(None)));

fn create_attr(ino: u64, file_type: FileType) -> FileAttr {
FileAttr {
ino,
size: 0,
blocks: 0,
atime: std::time::SystemTime::now(),
mtime: std::time::SystemTime::now(),
ctime: std::time::SystemTime::now(),
crtime: std::time::SystemTime::now(),
kind: file_type,
perm: if file_type == FileType::Directory { 0o755 } else { 0o644 },
nlink: if file_type == FileType::Directory { 2 } else { 1 },
fn create_attr_from_type(kind: FileType) -> CreateFileAttr {
CreateFileAttr {
kind,
perm: 0,
uid: 0,
gid: 0,
rdev: 0,
blksize: 0,
flags: 0,
}
}

fn create_attr_from_type(file_type: FileType) -> FileAttr {
create_attr(0, file_type)
}

async fn read_to_string(path: PathBuf, fs: &EncryptedFs) -> String {
let mut buf: Vec<u8> = vec![];
fs.create_decryptor(OpenOptions::new().read(true).write(true).open(path).unwrap()).await.unwrap().read_to_end(&mut buf).unwrap();
Expand Down Expand Up @@ -325,6 +321,7 @@ async fn test_truncate() -> FsResult<()> {
}

#[tokio::test]
#[traced_test]
async fn test_copy_file_range() -> FsResult<()> {
run_test(TestSetup { data_path: format!("{TESTS_DATA_DIR}test_copy_file_range") }, async {
let fs = SETUP_RESULT.with(|s| Arc::clone(s));
Expand Down
Loading

0 comments on commit 709dfa1

Please sign in to comment.