Skip to content

Commit

Permalink
Updating the permissions: using default_permissions and using a mask …
Browse files Browse the repository at this point in the history
…for files and directories. Adding a dir_cache config
  • Loading branch information
silverdaz committed Nov 25, 2024
1 parent bd4b139 commit 7ae4a55
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 23 deletions.
3 changes: 2 additions & 1 deletion example/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ DAZ_SECKEY=$(shell pwd)/example.seckey
export C4GH_PASSPHRASE=hello

DAZ_OPTS+=ro,seckey=$(DAZ_SECKEY),passphrase_from_env=C4GH_PASSPHRASE
DAZ_OPTS+=allow_other
DAZ_OPTS+=allow_other,default_permissions
DAZ_OPTS+=file_cache,dir_cache

all: up

Expand Down
19 changes: 10 additions & 9 deletions src/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ crypt4gh_sqlite_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f

if( ino == FUSE_ROOT_ID ){ /* It's the root directory itself */
s.st_ino = ino;
s.st_mode = S_IFDIR | 0500;
s.st_mode = S_IFDIR | config.dperm;
s.st_nlink = 1;
s.st_size = 0;
time_t now = time(NULL);
Expand Down Expand Up @@ -105,9 +105,9 @@ crypt4gh_sqlite_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f
s.st_size = (uint64_t)sqlite3_column_int(stmt, 3);

if(sqlite3_column_int(stmt, 4)) // is_dir
s.st_mode = S_IFDIR | 0500;
s.st_mode = S_IFDIR | config.dperm;
else
s.st_mode = S_IFREG | 0400;
s.st_mode = S_IFREG | config.fperm;

time_t now = time(NULL);
struct timespec mt = { .tv_sec = mtime, .tv_nsec = 0L },
Expand Down Expand Up @@ -191,9 +191,9 @@ __attribute__((nonnull(3)))
e.attr.st_size = (uint64_t)sqlite3_column_int64(stmt, 4);

if(sqlite3_column_int(stmt, 5)) // is_dir
e.attr.st_mode = S_IFDIR | 0500;
e.attr.st_mode = S_IFDIR | config.dperm;
else
e.attr.st_mode = S_IFREG | 0400;
e.attr.st_mode = S_IFREG | config.fperm;
break;
}

Expand Down Expand Up @@ -238,7 +238,8 @@ crypt4gh_sqlite_opendir(fuse_req_t req, fuse_ino_t ino,
}

fi->fh = (uint64_t)stmt;
fi->cache_readdir = 1;
if (config.dir_cache)
fi->cache_readdir = 1;
D3("stmt: %s", sqlite3_sql(stmt)); /* sqlite3_finalize will free it */
fuse_reply_open(req, fi);
}
Expand Down Expand Up @@ -312,7 +313,7 @@ crypt4gh_sqlite_readdir_plus(fuse_req_t req, fuse_ino_t ino, size_t size,
e.attr.st_atim = at;
e.attr.st_nlink = 1;
e.attr.st_size = 0;
e.attr.st_mode = S_IFDIR | 0500;
e.attr.st_mode = S_IFDIR | config.dperm;

if(offset < 1){
e.ino = 2;
Expand Down Expand Up @@ -364,9 +365,9 @@ crypt4gh_sqlite_readdir_plus(fuse_req_t req, fuse_ino_t ino, size_t size,
e.attr.st_size = (uint64_t)sqlite3_column_int64(stmt, 5);

if(sqlite3_column_int(stmt, 6)) // is_dir
e.attr.st_mode = S_IFDIR | 0500;
e.attr.st_mode = S_IFDIR | config.dperm;
else
e.attr.st_mode = S_IFREG | 0400;
e.attr.st_mode = S_IFREG | config.fperm;

/* add the entry to the buffer and check size */
char* pe = (char*)sqlite3_column_text(stmt, 1);
Expand Down
5 changes: 5 additions & 0 deletions src/includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ struct fs_config {
time_t mounted_at;
int direct_io;

unsigned int fmask;
unsigned int dmask;
unsigned int dperm;
unsigned int fperm;

int debug; /* replace/overwrite the fuse debug */
int verbose;
int foreground;
Expand Down
5 changes: 3 additions & 2 deletions src/keys/kdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ crypt4gh_sqlite_kdf_derive_key(char* alg,
/* See https://www.rfc-editor.org/rfc/rfc7914.txt
and https://doc.libsodium.org/advanced/scrypt#notes */
if (!strncmp(alg, "scrypt", 6)){
D1("Deriving a shared key using scrypt");
D3("Deriving a shared key using scrypt");
return crypto_pwhash_scryptsalsa208sha256_ll((const uint8_t*)passphrase, passphrase_len,
salt, salt_len,
1<<14, 8, 1,
Expand All @@ -59,7 +59,7 @@ crypt4gh_sqlite_kdf_derive_key(char* alg,
/* See keys/bcrypt
and https://github.com/pyca/bcrypt/tree/master/src/_csrc */
if (!strncmp(alg, "bcrypt", 6)){
D1("Deriving a shared key using scrypt");
D3("Deriving a shared key using scrypt");
return bcrypt_pbkdf(passphrase, passphrase_len,
salt, salt_len,
key, key_len,
Expand All @@ -68,6 +68,7 @@ crypt4gh_sqlite_kdf_derive_key(char* alg,

/* See https://www.openssl.org/docs/man1.1.0/man3/PKCS5_PBKDF2_HMAC.html */
if (!strncmp(alg, "pbkdf2_hmac_sha256", 18)){
D3("Deriving a shared key using HMAC-SHA256");
const EVP_MD *digest = EVP_sha256();
if(digest == NULL) return 3;
int rc = PKCS5_PBKDF2_HMAC(passphrase, passphrase_len,
Expand Down
4 changes: 2 additions & 2 deletions src/keys/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ crypt4gh_sqlite_public_key_from_blob(const char* line,
int rc = 1;
char* end = (char*)line + len - 1; /* point at the end */
D3("Length: %lu", len);
D3("Last char: %c", *end);
//D3("Last char: %c", *end);

while(isspace(*line)){ line++; len--; }; /* skip leading white-space (or newline) */
while(isspace(*end)){ end--; len--; }; /* Discount trailing white-space or newline */
Expand Down Expand Up @@ -174,7 +174,7 @@ crypt4gh_sqlite_private_key_from_blob(char* line, size_t len,
/* we _can_ change "line" */
*(end+1) = '\0';

D2("base64 string: %s", line);
D3("base64 string: %s", line);

/* Decoded string will be NULL-terminated too */
tmp = (u_char*)malloc((len+1) * sizeof(char));
Expand Down
41 changes: 32 additions & 9 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

#define FS_NAME "crypt4gh-sqlite.fs"

#define DEFAULT_FILE_MASK 0337
#define DEFAULT_DIR_MASK 0227

/* global variable */
struct fs_config config;

Expand All @@ -35,7 +38,9 @@ static void usage(struct fuse_args *args)
" --debug=N debug level <N>\n"
" -o direct_io enable direct i/o\n"
" -o file_cache instructs the kernel to cache output data\n"
" -o file_cache instructs the kernel to cache output data\n"
" -o dir_cache instructs the kernel to cache directory listings\n"
" -o file_mask=N file permissions' mask [default: %o]\n"
" -o dir_mask=N directory permissions' mask [default: %o]\n"
" -o entry_timeout=S seconds for which lookup names are cached [default: one day]\n"
" -o attr_timeout=S seconds for which directories/files attributes are cached [default: one day]\n"
" -o dotdot Shows '.' and '..' directories [default: ignored]\n"
Expand All @@ -46,7 +51,7 @@ static void usage(struct fuse_args *args)
" -o seckey=<path> Absolute path to the Crypt4GH secret key\n"
" -o passphrase_from_env=<ENVVAR>\n"
" read passphrase from environment variable <ENVVAR>\n"
, args->argv[0]);
, args->argv[0], DEFAULT_FILE_MASK, DEFAULT_DIR_MASK);
}


Expand All @@ -68,13 +73,17 @@ static struct fuse_opt fs_opts[] = {

CRYPT4GH_SQLITE_OPT("direct_io", direct_io, 1),
CRYPT4GH_SQLITE_OPT("file_cache", file_cache, 1),
CRYPT4GH_SQLITE_OPT("dir_cache", dir_cache, 1),

CRYPT4GH_SQLITE_OPT("dotdot", show_dotdot, 1),

/* Mount group id */
CRYPT4GH_SQLITE_OPT("user_id=%u", uid, 0), // chill... it's not root
CRYPT4GH_SQLITE_OPT("group_id=%u", gid, 0),

CRYPT4GH_SQLITE_OPT("file_mask=%u", fmask, DEFAULT_FILE_MASK),
CRYPT4GH_SQLITE_OPT("dir_mask=%u", dmask, DEFAULT_DIR_MASK),

/* in case Crypt4GH is enabled */
CRYPT4GH_SQLITE_OPT("seckey=%s" , seckeypath , 0),
CRYPT4GH_SQLITE_OPT("passphrase_from_env=%s", passphrase_from_env, 0),
Expand Down Expand Up @@ -202,6 +211,8 @@ c4gh_init(void)
{
int res = 0;

D1("Initializing the file system");

if(!config.seckeypath || *config.seckeypath != '/'){
E("Missing secret key path, or non-absolute path");
res ++;
Expand All @@ -210,7 +221,7 @@ c4gh_init(void)

/* Get the passphrase to unlock the Crypt4GH secret key */
if (config.passphrase_from_env) {
D1("Getting the passphrase from envvar %s", config.passphrase_from_env);
D2("Getting the passphrase from envvar %s", config.passphrase_from_env);
config.passphrase = getenv(config.passphrase_from_env);
} else {
char prompt[PATH_MAX + sizeof("Enter the passphrase for the Crypt4GH key '': ")];
Expand All @@ -235,7 +246,7 @@ c4gh_init(void)
}

/* Load the private key */
D2("Loading secret key from %s", config.seckeypath);
D3("Loading secret key from %s", config.seckeypath);

if( crypt4gh_sqlite_private_key_from_file(config.seckeypath, config.passphrase,
config.seckey, config.pubkey) ){
Expand Down Expand Up @@ -292,6 +303,9 @@ int main(int argc, char *argv[])
config.uid = getuid(); /* current user */
config.gid = getgid(); /* current group */

config.fmask = DEFAULT_FILE_MASK;
config.dmask = DEFAULT_DIR_MASK;

/* General options */
if (fuse_opt_parse(&args, &config, fs_opts, fs_opt_proc) == -1)
exit(1);
Expand Down Expand Up @@ -332,6 +346,10 @@ int main(int argc, char *argv[])
exit(1);
}

/* File and Dir permissions */
config.dperm = 0777 & ~config.dmask;
config.fperm = 0666 & ~config.dmask;

fuse_opt_insert_arg(&args, 1, "-ofsname=" FS_NAME);

if(config.debug)
Expand Down Expand Up @@ -392,17 +410,22 @@ int main(int argc, char *argv[])
goto bailout_unmount;
}

D2("Mode: %s-threaded", (config.singlethread)?"single":"multi");
D2("PID: %d", getpid());

if (config.singlethread)
D2("File cache: %s | Dir cache: %s | File perm: o%o | Dir perm: o%o",
(config.file_cache)?"yes":"no",
(config.dir_cache)?"yes":"no",
config.fperm,
config.dperm);

if (config.singlethread){
D2("Mode: single-threaded");
res = fuse_session_loop(se);
else {
} else {
struct fuse_loop_config cf = {
.clone_fd = config.clone_fd,
.max_idle_threads = config.max_idle_threads,
};
D2("Max idle threads: %d", cf.max_idle_threads);
D2("Mode: multi-threaded (max idle threads: %d)", cf.max_idle_threads);
res = fuse_session_loop_mt(se, &cf);
}

Expand Down

0 comments on commit 7ae4a55

Please sign in to comment.