From f5d8b38bd0d4c88ab73c6713daa59fbd7c357a34 Mon Sep 17 00:00:00 2001 From: feiniks <36756310+feiniks@users.noreply.github.com> Date: Wed, 16 Oct 2024 20:11:40 +0800 Subject: [PATCH] Support password hash (#2783) * Support password hash * Add rpc signature and verify pwd hash --------- Co-authored-by: yangheran --- common/commit-mgr.c | 27 +++++- common/commit-mgr.h | 3 + common/password-hash.c | 167 +++++++++++++++++++++++++++++++++++++ common/password-hash.h | 23 ++++++ common/rpc-service.c | 12 ++- common/seafile-crypt.c | 65 +++++++++++++++ common/seafile-crypt.h | 18 ++++ configure.ac | 4 + daemon/Makefile.am | 3 +- daemon/clone-mgr.c | 111 +++++++++++++++++++++---- daemon/repo-mgr.c | 28 +++++-- daemon/repo-mgr.h | 3 + daemon/seaf-daemon.c | 2 +- daemon/sync-mgr.c | 5 ++ include/seafile-rpc.h | 2 + lib/repo.vala | 1 + lib/rpc_table.py | 1 + lib/searpc-marshal.h | 25 +++++- lib/searpc-signature.h | 183 +++++++++++++++++++++-------------------- 19 files changed, 565 insertions(+), 118 deletions(-) create mode 100644 common/password-hash.c create mode 100644 common/password-hash.h diff --git a/common/commit-mgr.c b/common/commit-mgr.c index dc1e2b56..bb76a1ad 100644 --- a/common/commit-mgr.c +++ b/common/commit-mgr.c @@ -165,6 +165,9 @@ seaf_commit_free (SeafCommit *commit) g_free (commit->client_version); g_free (commit->magic); g_free (commit->random_key); + g_free (commit->pwd_hash); + g_free (commit->pwd_hash_algo); + g_free (commit->pwd_hash_params); g_free (commit); } @@ -630,12 +633,17 @@ commit_to_json_object (SeafCommit *commit) if (commit->encrypted) { json_object_set_int_member (object, "enc_version", commit->enc_version); - if (commit->enc_version >= 1) + if (commit->enc_version >= 1 && !commit->pwd_hash) json_object_set_string_member (object, "magic", commit->magic); if (commit->enc_version >= 2) json_object_set_string_member (object, "key", commit->random_key); if (commit->enc_version >= 3) json_object_set_string_member (object, "salt", commit->salt); + if (commit->pwd_hash) { + json_object_set_string_member (object, "pwd_hash", commit->pwd_hash); + json_object_set_string_member (object, "pwd_hash_algo", commit->pwd_hash_algo); + json_object_set_string_member (object, "pwd_hash_params", commit->pwd_hash_params); + } } if (commit->no_local_history) json_object_set_int_member (object, "no_local_history", 1); @@ -672,6 +680,9 @@ commit_from_json_object (const char *commit_id, json_t *object) const char *magic = NULL; const char *random_key = NULL; const char *salt = NULL; + const char *pwd_hash = NULL; + const char *pwd_hash_algo = NULL; + const char *pwd_hash_params = NULL; int no_local_history = 0; int version = 0; int conflict = 0, new_merge = 0; @@ -706,6 +717,9 @@ commit_from_json_object (const char *commit_id, json_t *object) && json_object_has_member (object, "enc_version")) { enc_version = json_object_get_int_member (object, "enc_version"); magic = json_object_get_string_member (object, "magic"); + pwd_hash = json_object_get_string_member (object, "pwd_hash"); + pwd_hash_algo = json_object_get_string_member (object, "pwd_hash_algo"); + pwd_hash_params = json_object_get_string_member (object, "pwd_hash_params"); } if (enc_version >= 2) @@ -736,6 +750,10 @@ commit_from_json_object (const char *commit_id, json_t *object) (second_parent_id && !is_object_id_valid(second_parent_id))) return commit; + // If pwd_hash is set, the magic field is no longer included in the commit of the newly created repo. + if (!magic) + magic = pwd_hash; + switch (enc_version) { case 0: break; @@ -791,12 +809,17 @@ commit_from_json_object (const char *commit_id, json_t *object) if (commit->encrypted) { commit->enc_version = enc_version; - if (enc_version >= 1) + if (enc_version >= 1 && !pwd_hash) commit->magic = g_strdup(magic); if (enc_version >= 2) commit->random_key = g_strdup (random_key); if (enc_version >= 3) commit->salt = g_strdup(salt); + if (pwd_hash) { + commit->pwd_hash = g_strdup (pwd_hash); + commit->pwd_hash_algo = g_strdup (pwd_hash_algo); + commit->pwd_hash_params = g_strdup (pwd_hash_params); + } } if (no_local_history) commit->no_local_history = TRUE; diff --git a/common/commit-mgr.h b/common/commit-mgr.h index 7c237528..936af4a6 100644 --- a/common/commit-mgr.h +++ b/common/commit-mgr.h @@ -36,6 +36,9 @@ struct _SeafCommit { char *magic; char *random_key; char *salt; + char *pwd_hash; + char *pwd_hash_algo; + char *pwd_hash_params; gboolean no_local_history; int version; diff --git a/common/password-hash.c b/common/password-hash.c new file mode 100644 index 00000000..27e2bfa9 --- /dev/null +++ b/common/password-hash.c @@ -0,0 +1,167 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#include +#include +#include +#include "password-hash.h" +#include "seafile-crypt.h" +#include + +#include "utils.h" +#include "log.h" + +// pbkdf2 +typedef struct Pbkdf2Params { + int iteration; +} Pbkdf2Params; + +static Pbkdf2Params * +parse_pbkdf2_sha256_params (const char *params_str) +{ + Pbkdf2Params *params = NULL; + if (!params_str) { + params = g_new0 (Pbkdf2Params, 1); + params->iteration = 1000; + return params; + } + int iteration; + iteration = atoi (params_str); + if (iteration <= 0) { + iteration = 1000; + } + + params = g_new0 (Pbkdf2Params, 1); + params->iteration = iteration; + return params; +} + +static int +pbkdf2_sha256_derive_key (const char *data_in, int in_len, + const char *salt, + Pbkdf2Params *params, + unsigned char *key) +{ + int iteration = params->iteration; + + unsigned char salt_bin[32] = {0}; + hex_to_rawdata (salt, salt_bin, 32); + + PKCS5_PBKDF2_HMAC (data_in, in_len, + salt_bin, sizeof(salt_bin), + iteration, + EVP_sha256(), + 32, key); + return 0; +} + +// argon2id +typedef struct Argon2idParams{ + gint64 time_cost; + gint64 memory_cost; + gint64 parallelism; +} Argon2idParams; + +// The arguments to argon2 are separated by commas. +// Example arguments format: +// 2,102400,8 +// The parameters are time_cost, memory_cost, parallelism from left to right. +static Argon2idParams * +parse_argon2id_params (const char *params_str) +{ + char **params; + Argon2idParams *argon2_params = g_new0 (Argon2idParams, 1); + if (params_str) + params = g_strsplit (params_str, ",", 3); + if (!params_str || g_strv_length(params) != 3) { + if (params_str) + g_strfreev (params); + argon2_params->time_cost = 2; // 2-pass computation + argon2_params->memory_cost = 102400; // 100 mebibytes memory usage + argon2_params->parallelism = 8; // number of threads and lanes + return argon2_params; + } + + char *p = NULL; + p = g_strstrip (params[0]); + argon2_params->time_cost = atoll (p); + if (argon2_params->time_cost <= 0) { + argon2_params->time_cost = 2; + } + + p = g_strstrip (params[1]); + argon2_params->memory_cost = atoll (p); + if (argon2_params->memory_cost <= 0) { + argon2_params->memory_cost = 102400; + } + + p = g_strstrip (params[2]); + argon2_params->parallelism = atoll (p); + if (argon2_params->parallelism <= 0) { + argon2_params->parallelism = 8; + } + + g_strfreev (params); + return argon2_params; +} + +static int +argon2id_derive_key (const char *data_in, int in_len, + const char *salt, + Argon2idParams *params, + unsigned char *key) +{ + unsigned char salt_bin[32] = {0}; + hex_to_rawdata (salt, salt_bin, 32); + + argon2id_hash_raw(params->time_cost, params->memory_cost, params->parallelism, + data_in, in_len, + salt_bin, sizeof(salt_bin), + key, 32); + + return 0; +} + +// parse_pwd_hash_params is used to parse default pwd hash algorithms. +void +parse_pwd_hash_params (const char *algo, const char *params_str, PwdHashParams *params) +{ + if (g_strcmp0 (algo, PWD_HASH_PDKDF2) == 0) { + params->algo = g_strdup (PWD_HASH_PDKDF2); + if (params_str) + params->params_str = g_strdup (params_str); + else + params->params_str = g_strdup ("1000"); + } else if (g_strcmp0 (algo, PWD_HASH_ARGON2ID) == 0) { + params->algo = g_strdup (PWD_HASH_ARGON2ID); + if (params_str) + params->params_str = g_strdup (params_str); + else + params->params_str = g_strdup ("2,102400,8"); + } else { + params->algo = NULL; + } + + seaf_message ("password hash algorithms: %s, params: %s\n ", params->algo, params->params_str); +} + +int +pwd_hash_derive_key (const char *data_in, int in_len, + const char *salt, + const char *algo, const char *params_str, + unsigned char *key) +{ + int ret = 0; + if (g_strcmp0 (algo, PWD_HASH_ARGON2ID) == 0) { + Argon2idParams *algo_params = parse_argon2id_params (params_str); + ret = argon2id_derive_key (data_in, in_len, + salt, algo_params, key); + g_free (algo_params); + return ret; + } else { + Pbkdf2Params *algo_params = parse_pbkdf2_sha256_params (params_str); + ret = pbkdf2_sha256_derive_key (data_in, in_len, + salt, algo_params, key); + g_free (algo_params); + return ret; + } +} diff --git a/common/password-hash.h b/common/password-hash.h new file mode 100644 index 00000000..a0ffc492 --- /dev/null +++ b/common/password-hash.h @@ -0,0 +1,23 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#ifndef _PASSWORD_HASH_H +#define _PASSWORD_HASH_H + +#define PWD_HASH_PDKDF2 "pbkdf2_sha256" +#define PWD_HASH_ARGON2ID "argon2id" + +typedef struct _PwdHashParams { + char *algo; + char *params_str; +} PwdHashParams; + +void +parse_pwd_hash_params (const char *algo, const char *params_str, PwdHashParams *params); + +int +pwd_hash_derive_key (const char *data_in, int in_len, + const char *repo_salt, + const char *algo, const char *params_str, + unsigned char *key); + +#endif diff --git a/common/rpc-service.c b/common/rpc-service.c index b2439967..fc4bdf3f 100644 --- a/common/rpc-service.c +++ b/common/rpc-service.c @@ -19,6 +19,7 @@ #include "seafile-config.h" #include "seafile-object.h" #include "seafile-error-impl.h" +#include "password-hash.h" #define DEBUG_FLAG SEAFILE_DEBUG_OTHER #include "log.h" @@ -863,6 +864,8 @@ GObject * seafile_generate_magic_and_random_key(int enc_version, const char* repo_id, const char *passwd, + const char *pwd_hash_algo, + const char *pwd_hash_params, GError **error) { if (!repo_id || !passwd) { @@ -872,13 +875,19 @@ seafile_generate_magic_and_random_key(int enc_version, gchar salt[65] = {0}; gchar magic[65] = {0}; + gchar pwd_hash[65] = {0}; gchar random_key[97] = {0}; if (enc_version >= 3 && seafile_generate_repo_salt (salt) < 0) { return NULL; } - seafile_generate_magic (enc_version, repo_id, passwd, salt, magic); + if (g_strcmp0 (pwd_hash_algo, PWD_HASH_PDKDF2) == 0 || + g_strcmp0 (pwd_hash_algo, PWD_HASH_ARGON2ID) == 0) { + seafile_generate_pwd_hash (enc_version, repo_id, passwd, salt, pwd_hash_algo, pwd_hash_params, pwd_hash); + } else { + seafile_generate_magic (enc_version, repo_id, passwd, salt, magic); + } if (seafile_generate_random_key (passwd, enc_version, salt, random_key) < 0) { return NULL; } @@ -889,6 +898,7 @@ seafile_generate_magic_and_random_key(int enc_version, "passwd", passwd, "enc_version", enc_version, "magic", magic, + "pwd_hash", pwd_hash, "random_key", random_key, NULL); diff --git a/common/seafile-crypt.c b/common/seafile-crypt.c index 6b3adb5b..be50de95 100644 --- a/common/seafile-crypt.c +++ b/common/seafile-crypt.c @@ -5,6 +5,7 @@ #include #include #include "seafile-crypt.h" +#include "password-hash.h" #ifdef USE_GPL_CRYPTO #include @@ -194,6 +195,37 @@ seafile_generate_magic (int version, const char *repo_id, rawdata_to_hex (key, magic, 32); } +void +seafile_generate_pwd_hash (int version, + const char *repo_id, + const char *passwd, + const char *repo_salt, + const char *algo, + const char *params_str, + char *pwd_hash) +{ + GString *buf = g_string_new (NULL); + unsigned char key[32]; + + /* Compute a "pwd_hash" string from repo_id and passwd. + * This is used to verify the password given by user before decrypting + * data. + */ + g_string_append_printf (buf, "%s%s", repo_id, passwd); + + if (version <= 2) { + // use fixed repo salt + char fixed_salt[64] = {0}; + rawdata_to_hex(salt, fixed_salt, 8); + pwd_hash_derive_key (buf->str, buf->len, fixed_salt, algo, params_str, key); + } else { + pwd_hash_derive_key (buf->str, buf->len, repo_salt, algo, params_str, key); + } + + g_string_free (buf, TRUE); + rawdata_to_hex (key, pwd_hash, 32); +} + int seafile_verify_repo_passwd (const char *repo_id, const char *passwd, @@ -228,6 +260,39 @@ seafile_verify_repo_passwd (const char *repo_id, return -1; } +int +seafile_pwd_hash_verify_repo_passwd (int version, + const char *repo_id, + const char *passwd, + const char *repo_salt, + const char *pwd_hash, + const char *algo, + const char *params_str) +{ + GString *buf = g_string_new (NULL); + unsigned char key[32]; + char hex[65]; + + g_string_append_printf (buf, "%s%s", repo_id, passwd); + + if (version <= 2) { + // use fixed repo salt + char fixed_salt[64] = {0}; + rawdata_to_hex(salt, fixed_salt, 8); + pwd_hash_derive_key (buf->str, buf->len, fixed_salt, algo, params_str, key); + } else { + pwd_hash_derive_key (buf->str, buf->len, repo_salt, algo, params_str, key); + } + + g_string_free (buf, TRUE); + rawdata_to_hex (key, hex, 32); + + if (g_strcmp0 (hex, pwd_hash) == 0) + return 0; + else + return -1; +} + int seafile_decrypt_repo_enc_key (int enc_version, const char *passwd, const char *random_key, diff --git a/common/seafile-crypt.h b/common/seafile-crypt.h index a001eedf..82aeb577 100644 --- a/common/seafile-crypt.h +++ b/common/seafile-crypt.h @@ -65,6 +65,15 @@ seafile_generate_magic (int version, const char *repo_id, const char *passwd, char *magic); +void +seafile_generate_pwd_hash (int version, + const char *repo_id, + const char *passwd, + const char *repo_salt, + const char *algo, + const char *params_str, + char *pwd_hash); + int seafile_verify_repo_passwd (const char *repo_id, const char *passwd, @@ -72,6 +81,15 @@ seafile_verify_repo_passwd (const char *repo_id, int version, const char *repo_salt); +int +seafile_pwd_hash_verify_repo_passwd (int version, + const char *repo_id, + const char *passwd, + const char *repo_salt, + const char *pwd_hash, + const char *algo, + const char *params_str); + int seafile_decrypt_repo_enc_key (int enc_version, const char *passwd, const char *random_key, diff --git a/configure.ac b/configure.ac index e4e24752..886cf301 100644 --- a/configure.ac +++ b/configure.ac @@ -189,6 +189,10 @@ PKG_CHECK_MODULES(CURL, [libcurl >= $CURL_REQUIRED]) AC_SUBST(CURL_CFLAGS) AC_SUBST(CURL_LIBS) +PKG_CHECK_MODULES(ARGON2, [libargon2]) +AC_SUBST(ARGON2_CFLAGS) +AC_SUBST(ARGON2_LIBS) + AC_ARG_ENABLE(ws, AC_HELP_STRING([--enable-ws], [enable build websockets]), [compile_linux_ws=$enableval],[compile_linux_ws="yes"]) AM_CONDITIONAL([COMPILE_LINUX_WS], [test "${compile_linux_ws}" = "yes"]) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 0011a7f6..42a44207 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -83,6 +83,7 @@ common_src = \ ../common/block-backend-fs.c \ ../common/mq-mgr.c \ ../common/curl-init.c \ + ../common/password-hash.c \ sync-status-tree.c \ filelock-mgr.c \ set-perm.c \ @@ -98,6 +99,6 @@ seaf_daemon_LDADD = $(top_builddir)/lib/libseafile_common.la \ $(top_builddir)/common/cdc/libcdc.la \ $(top_builddir)/common/index/libindex.la @LIB_WS32@ @LIB_CRYPT32@ \ @SEARPC_LIBS@ @JANSSON_LIBS@ @LIB_MAC@ @ZLIB_LIBS@ @CURL_LIBS@ @BPWRAPPER_LIBS@ \ - @WS_LIBS@ + @WS_LIBS@ @ARGON2_LIBS@ seaf_daemon_LDFLAGS = @CONSOLE@ diff --git a/daemon/clone-mgr.c b/daemon/clone-mgr.c index 55b36c0b..803ba5dc 100644 --- a/daemon/clone-mgr.c +++ b/daemon/clone-mgr.c @@ -1105,6 +1105,40 @@ check_encryption_args (const char *magic, int enc_version, const char *random_ke return TRUE; } +static gboolean +check_pwd_hash_encryption_args (const char *pwd_hash, int enc_version, + const char *random_key, + const char *repo_salt, + GError **error) +{ + if (!pwd_hash) { + g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, + "Password hash must be specified"); + return FALSE; + } + + if (enc_version != 1 && enc_version != 2 && enc_version != 3 && enc_version != 4) { + g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, + "Unsupported enc version"); + return FALSE; + } + + if (enc_version >= 2) { + if (!random_key || strlen(random_key) != 96) { + g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, + "Random key not specified"); + return FALSE; + } + if (enc_version >= 3 && (!(repo_salt) || strlen(repo_salt) != 64) ) { + g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, + "Repo salt not specified"); + return FALSE; + } + } + + return TRUE; +} + static gboolean is_wt_repo_name_same (const char *worktree, const char *repo_name) { @@ -1135,6 +1169,9 @@ seaf_clone_manager_add_task (SeafCloneManager *mgr, char *ret = NULL; gboolean sync_wt_name = FALSE; char *repo_salt = NULL; + char *algo = NULL; + char *params = NULL; + char *pwd_hash = NULL; gboolean resync_enc_repo = FALSE; if (!seaf->started) { @@ -1165,10 +1202,22 @@ seaf_clone_manager_add_task (SeafCloneManager *mgr, repo_salt = g_strdup (json_string_value (string)); json_t *integer = json_object_get (object, "resync_enc_repo"); resync_enc_repo = json_integer_value (integer); + string = json_object_get (object, "pwd_hash_algo"); + if (string) + algo = g_strdup (json_string_value (string)); + string = json_object_get (object, "pwd_hash_params"); + if (string) + params = g_strdup (json_string_value (string)); + string = json_object_get (object, "pwd_hash"); + if (string) + pwd_hash = g_strdup (json_string_value (string)); json_decref (object); } - if (passwd && + if (passwd && algo && + !check_pwd_hash_encryption_args (pwd_hash, enc_version, random_key, repo_salt, error)) { + goto out; + } else if (passwd && !check_encryption_args (magic, enc_version, random_key, repo_salt, error)) { goto out; } @@ -1198,7 +1247,13 @@ seaf_clone_manager_add_task (SeafCloneManager *mgr, goto out; } - if (passwd && + if (passwd && algo) { + if (seafile_pwd_hash_verify_repo_passwd(enc_version, repo_id, passwd, repo_salt, pwd_hash, algo, params) < 0) { + g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, + "Incorrect password"); + goto out; + } + } else if (passwd && seafile_verify_repo_passwd(repo_id, passwd, magic, enc_version, repo_salt) < 0) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Incorrect password"); @@ -1242,6 +1297,9 @@ seaf_clone_manager_add_task (SeafCloneManager *mgr, out: g_free (worktree); g_free (repo_salt); + g_free (algo); + g_free (params); + g_free (pwd_hash); return ret; } @@ -1287,6 +1345,9 @@ seaf_clone_manager_add_download_task (SeafCloneManager *mgr, char *worktree = NULL; char *ret = NULL; char *repo_salt = NULL; + char *algo = NULL; + char *params = NULL; + char *pwd_hash = NULL; if (!seaf->started) { seaf_message ("System not started, skip adding clone task.\n"); @@ -1303,19 +1364,28 @@ seaf_clone_manager_add_download_task (SeafCloneManager *mgr, #endif if (more_info) { - json_error_t jerror; - json_t *object; - - object = json_loads (more_info, 0, &jerror); - if (!object) { - seaf_warning ("Failed to load more sync info from json: %s.\n", jerror.text); - goto out; - } - json_t *string = json_object_get (object, "repo_salt"); - if (string) - repo_salt = g_strdup (json_string_value (string)); - json_decref (object); - } + json_error_t jerror; + json_t *object; + + object = json_loads (more_info, 0, &jerror); + if (!object) { + seaf_warning ("Failed to load more sync info from json: %s.\n", jerror.text); + goto out; + } + json_t *string = json_object_get (object, "repo_salt"); + if (string) + repo_salt = g_strdup (json_string_value (string)); + string = json_object_get (object, "pwd_hash_algo"); + if (string) + algo = g_strdup (json_string_value (string)); + string = json_object_get (object, "pwd_hash_params"); + if (string) + params = g_strdup (json_string_value (string)); + string = json_object_get (object, "pwd_hash"); + if (string) + pwd_hash = g_strdup (json_string_value (string)); + json_decref (object); + } if (passwd && !check_encryption_args (magic, enc_version, random_key, repo_salt, error)) { @@ -1348,7 +1418,13 @@ seaf_clone_manager_add_download_task (SeafCloneManager *mgr, goto out; } - if (passwd && + if (passwd && algo) { + if (seafile_pwd_hash_verify_repo_passwd(enc_version, repo_id, passwd, repo_salt, pwd_hash, algo, params) < 0) { + g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, + "Incorrect password"); + goto out; + } + } else if (passwd && seafile_verify_repo_passwd(repo_id, passwd, magic, enc_version, repo_salt) < 0) { g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Incorrect password"); @@ -1394,6 +1470,9 @@ out: g_free (worktree); g_free (wt_tmp); g_free (repo_salt); + g_free (algo); + g_free (params); + g_free (pwd_hash); return ret; } diff --git a/daemon/repo-mgr.c b/daemon/repo-mgr.c index 35d5a797..69bb3687 100644 --- a/daemon/repo-mgr.c +++ b/daemon/repo-mgr.c @@ -1190,6 +1190,8 @@ seaf_repo_free (SeafRepo *repo) g_free (repo->email); g_free (repo->username); g_free (repo->token); + g_free (repo->pwd_hash_algo); + g_free (repo->pwd_hash_params); g_free (repo); } @@ -1244,22 +1246,27 @@ seaf_repo_from_commit (SeafRepo *repo, SeafCommit *commit) memcpy (repo->root_id, commit->root_id, 40); if (repo->encrypted) { repo->enc_version = commit->enc_version; - if (repo->enc_version == 1) + if (repo->enc_version == 1 && !commit->pwd_hash_algo) memcpy (repo->magic, commit->magic, 32); else if (repo->enc_version == 2) { - memcpy (repo->magic, commit->magic, 64); memcpy (repo->random_key, commit->random_key, 96); } else if (repo->enc_version == 3) { - memcpy (repo->magic, commit->magic, 64); memcpy (repo->random_key, commit->random_key, 96); memcpy (repo->salt, commit->salt, 64); } else if (repo->enc_version == 4) { - memcpy (repo->magic, commit->magic, 64); memcpy (repo->random_key, commit->random_key, 96); memcpy (repo->salt, commit->salt, 64); } + if (repo->enc_version >= 2 && !commit->pwd_hash_algo) { + memcpy (repo->magic, commit->magic, 64); + } + if (commit->pwd_hash_algo) { + memcpy (repo->pwd_hash, commit->pwd_hash, 64); + repo->pwd_hash_algo = g_strdup (commit->pwd_hash_algo); + repo->pwd_hash_params = g_strdup (commit->pwd_hash_params); + } } repo->no_local_history = commit->no_local_history; repo->version = commit->version; @@ -1273,22 +1280,27 @@ seaf_repo_to_commit (SeafRepo *repo, SeafCommit *commit) commit->encrypted = repo->encrypted; if (commit->encrypted) { commit->enc_version = repo->enc_version; - if (commit->enc_version == 1) + if (commit->enc_version == 1 && !repo->pwd_hash_algo) commit->magic = g_strdup (repo->magic); else if (commit->enc_version == 2) { - commit->magic = g_strdup (repo->magic); commit->random_key = g_strdup (repo->random_key); } else if (commit->enc_version == 3) { - commit->magic = g_strdup (repo->magic); commit->random_key = g_strdup (repo->random_key); commit->salt = g_strdup (repo->salt); } else if (commit->enc_version == 4) { - commit->magic = g_strdup (repo->magic); commit->random_key = g_strdup (repo->random_key); commit->salt = g_strdup (repo->salt); } + if (commit->enc_version >= 2 && !repo->pwd_hash_algo) { + commit->magic = g_strdup (repo->magic); + } + if (repo->pwd_hash_algo) { + commit->pwd_hash = g_strdup (repo->pwd_hash); + commit->pwd_hash_algo = g_strdup (repo->pwd_hash_algo); + commit->pwd_hash_params = g_strdup (repo->pwd_hash_params); + } } commit->no_local_history = repo->no_local_history; commit->version = repo->version; diff --git a/daemon/repo-mgr.h b/daemon/repo-mgr.h index 2d0f64ce..d101bec5 100644 --- a/daemon/repo-mgr.h +++ b/daemon/repo-mgr.h @@ -46,6 +46,9 @@ struct _SeafRepo { int enc_version; gchar salt[65]; gchar magic[65]; /* hash(repo_id + passwd), key stretched. */ + gchar pwd_hash[65]; /* hash(repo_id + passwd), key stretched. */ + gchar *pwd_hash_algo; + gchar *pwd_hash_params; gchar random_key[97]; /* key length is 48 after encryption */ gboolean no_local_history; gint64 last_modify; diff --git a/daemon/seaf-daemon.c b/daemon/seaf-daemon.c index 7a44bee1..b3d1d7f3 100644 --- a/daemon/seaf-daemon.c +++ b/daemon/seaf-daemon.c @@ -255,7 +255,7 @@ register_rpc_service () searpc_server_register_function ("seafile-rpcserver", seafile_generate_magic_and_random_key, "seafile_generate_magic_and_random_key", - searpc_signature_object__int_string_string()); + searpc_signature_object__int_string_string_string_string()); searpc_server_register_function ("seafile-rpcserver", seafile_get_server_property, diff --git a/daemon/sync-mgr.c b/daemon/sync-mgr.c index b0126dd5..08e32216 100644 --- a/daemon/sync-mgr.c +++ b/daemon/sync-mgr.c @@ -1401,6 +1401,11 @@ resync_repo (SeafRepo *repo) rawdata_to_hex (repo->enc_iv, iv, 16); } json_object_set_int_member (obj, "resync_enc_repo", TRUE); + if (repo->pwd_hash_algo) { + json_object_set_string_member (obj, "pwd_hash_algo", repo->pwd_hash_algo); + json_object_set_string_member (obj, "pwd_hash_params", repo->pwd_hash_params); + json_object_set_string_member (obj, "pwd_hash", repo->pwd_hash); + } } more_info = json_dumps (obj, 0); diff --git a/include/seafile-rpc.h b/include/seafile-rpc.h index 518fe3aa..11bce41a 100644 --- a/include/seafile-rpc.h +++ b/include/seafile-rpc.h @@ -208,6 +208,8 @@ GObject * seafile_generate_magic_and_random_key(int enc_version, const char* repo_id, const char *passwd, + const char *pwd_hash_algo, + const char *pwd_hash_params, GError **error); json_t * seafile_get_sync_notification (GError **error); diff --git a/lib/repo.vala b/lib/repo.vala index 4fe77889..e11fb220 100644 --- a/lib/repo.vala +++ b/lib/repo.vala @@ -121,6 +121,7 @@ public class EncryptionInfo: Object { public string passwd { get; set; } public int enc_version { get; set; } public string magic { get; set; } + public string pwd_hash { get; set; } public string random_key { get; set; } public string salt { get; set; } } diff --git a/lib/rpc_table.py b/lib/rpc_table.py index 122cde05..fd90a7db 100644 --- a/lib/rpc_table.py +++ b/lib/rpc_table.py @@ -89,6 +89,7 @@ func_table = [ [ "object", ["string", "string", "string"] ], [ "object", ["string", "int", "string"] ], [ "object", ["int", "string", "string"] ], + [ "object", ["int", "string", "string", "string", "string"] ], [ "object", ["string", "string", "string", "string", "string", "string", "string", "int", "int"] ], [ "object", ["string", "string", "string", "string", "string", "string", "int", "string", "int", "int"] ], [ "json", [] ], diff --git a/lib/searpc-marshal.h b/lib/searpc-marshal.h index c4db5f0b..52bd9b33 100644 --- a/lib/searpc-marshal.h +++ b/lib/searpc-marshal.h @@ -1405,6 +1405,24 @@ marshal_object__int_string_string (void *func, json_t *param_array, gsize *ret_l } +static char * +marshal_object__int_string_string_string_string (void *func, json_t *param_array, gsize *ret_len) +{ + GError *error = NULL; + int param1 = json_array_get_int_element (param_array, 1); + const char* param2 = json_array_get_string_or_null_element (param_array, 2); + const char* param3 = json_array_get_string_or_null_element (param_array, 3); + const char* param4 = json_array_get_string_or_null_element (param_array, 4); + const char* param5 = json_array_get_string_or_null_element (param_array, 5); + + GObject* ret = ((GObject* (*)(int, const char*, const char*, const char*, const char*, GError **))func) (param1, param2, param3, param4, param5, &error); + + json_t *object = json_object (); + searpc_set_object_to_ret_object (object, ret); + return searpc_marshal_set_ret_common (object, ret_len, error); +} + + static char * marshal_object__string_string_string_string_string_string_string_int_int (void *func, json_t *param_array, gsize *ret_len) { @@ -1462,7 +1480,7 @@ marshal_json__void (void *func, json_t *param_array, gsize *ret_len) return searpc_marshal_set_ret_common (object, ret_len, error); } -static void register_marshals() +static void register_marshals(void) { { @@ -1890,6 +1908,11 @@ static void register_marshals() } + { + searpc_server_register_marshal (searpc_signature_object__int_string_string_string_string(), marshal_object__int_string_string_string_string); + } + + { searpc_server_register_marshal (searpc_signature_object__string_string_string_string_string_string_string_int_int(), marshal_object__string_string_string_string_string_string_string_int_int); } diff --git a/lib/searpc-signature.h b/lib/searpc-signature.h index c3819c8d..e545e7ca 100644 --- a/lib/searpc-signature.h +++ b/lib/searpc-signature.h @@ -1,615 +1,622 @@ inline static gchar * -searpc_signature_int__void() +searpc_signature_int__void(void) { return searpc_compute_signature ("int", 0); } inline static gchar * -searpc_signature_int__int() +searpc_signature_int__int(void) { return searpc_compute_signature ("int", 1, "int"); } inline static gchar * -searpc_signature_int__int_int() +searpc_signature_int__int_int(void) { return searpc_compute_signature ("int", 2, "int", "int"); } inline static gchar * -searpc_signature_int__int_string() +searpc_signature_int__int_string(void) { return searpc_compute_signature ("int", 2, "int", "string"); } inline static gchar * -searpc_signature_int__int_string_int() +searpc_signature_int__int_string_int(void) { return searpc_compute_signature ("int", 3, "int", "string", "int"); } inline static gchar * -searpc_signature_int__int_string_string() +searpc_signature_int__int_string_string(void) { return searpc_compute_signature ("int", 3, "int", "string", "string"); } inline static gchar * -searpc_signature_int__int_string_int_int() +searpc_signature_int__int_string_int_int(void) { return searpc_compute_signature ("int", 4, "int", "string", "int", "int"); } inline static gchar * -searpc_signature_int__int_int_string_string() +searpc_signature_int__int_int_string_string(void) { return searpc_compute_signature ("int", 4, "int", "int", "string", "string"); } inline static gchar * -searpc_signature_int__string() +searpc_signature_int__string(void) { return searpc_compute_signature ("int", 1, "string"); } inline static gchar * -searpc_signature_int__string_int() +searpc_signature_int__string_int(void) { return searpc_compute_signature ("int", 2, "string", "int"); } inline static gchar * -searpc_signature_int__string_int_int() +searpc_signature_int__string_int_int(void) { return searpc_compute_signature ("int", 3, "string", "int", "int"); } inline static gchar * -searpc_signature_int__string_int_string() +searpc_signature_int__string_int_string(void) { return searpc_compute_signature ("int", 3, "string", "int", "string"); } inline static gchar * -searpc_signature_int__string_int_string_string() +searpc_signature_int__string_int_string_string(void) { return searpc_compute_signature ("int", 4, "string", "int", "string", "string"); } inline static gchar * -searpc_signature_int__string_int_int_string_string() +searpc_signature_int__string_int_int_string_string(void) { return searpc_compute_signature ("int", 5, "string", "int", "int", "string", "string"); } inline static gchar * -searpc_signature_int__string_string() +searpc_signature_int__string_string(void) { return searpc_compute_signature ("int", 2, "string", "string"); } inline static gchar * -searpc_signature_int__string_string_string() +searpc_signature_int__string_string_string(void) { return searpc_compute_signature ("int", 3, "string", "string", "string"); } inline static gchar * -searpc_signature_int__string_string_int_int() +searpc_signature_int__string_string_int_int(void) { return searpc_compute_signature ("int", 4, "string", "string", "int", "int"); } inline static gchar * -searpc_signature_int__string_string_string_int() +searpc_signature_int__string_string_string_int(void) { return searpc_compute_signature ("int", 4, "string", "string", "string", "int"); } inline static gchar * -searpc_signature_int__string_string_string_int_string() +searpc_signature_int__string_string_string_int_string(void) { return searpc_compute_signature ("int", 5, "string", "string", "string", "int", "string"); } inline static gchar * -searpc_signature_int__string_string_string_string() +searpc_signature_int__string_string_string_string(void) { return searpc_compute_signature ("int", 4, "string", "string", "string", "string"); } inline static gchar * -searpc_signature_int__string_string_string_string_string() +searpc_signature_int__string_string_string_string_string(void) { return searpc_compute_signature ("int", 5, "string", "string", "string", "string", "string"); } inline static gchar * -searpc_signature_int__string_string_string_string_string_string() +searpc_signature_int__string_string_string_string_string_string(void) { return searpc_compute_signature ("int", 6, "string", "string", "string", "string", "string", "string"); } inline static gchar * -searpc_signature_int__string_string_string_int_string_string() +searpc_signature_int__string_string_string_int_string_string(void) { return searpc_compute_signature ("int", 6, "string", "string", "string", "int", "string", "string"); } inline static gchar * -searpc_signature_int__string_string_string_string_string_string_string() +searpc_signature_int__string_string_string_string_string_string_string(void) { return searpc_compute_signature ("int", 7, "string", "string", "string", "string", "string", "string", "string"); } inline static gchar * -searpc_signature_int__string_int64() +searpc_signature_int__string_int64(void) { return searpc_compute_signature ("int", 2, "string", "int64"); } inline static gchar * -searpc_signature_int__int_int64() +searpc_signature_int__int_int64(void) { return searpc_compute_signature ("int", 2, "int", "int64"); } inline static gchar * -searpc_signature_int__int_string_int64() +searpc_signature_int__int_string_int64(void) { return searpc_compute_signature ("int", 3, "int", "string", "int64"); } inline static gchar * -searpc_signature_int64__void() +searpc_signature_int64__void(void) { return searpc_compute_signature ("int64", 0); } inline static gchar * -searpc_signature_int64__string() +searpc_signature_int64__string(void) { return searpc_compute_signature ("int64", 1, "string"); } inline static gchar * -searpc_signature_int64__int() +searpc_signature_int64__int(void) { return searpc_compute_signature ("int64", 1, "int"); } inline static gchar * -searpc_signature_int64__int_string() +searpc_signature_int64__int_string(void) { return searpc_compute_signature ("int64", 2, "int", "string"); } inline static gchar * -searpc_signature_int64__string_int_string() +searpc_signature_int64__string_int_string(void) { return searpc_compute_signature ("int64", 3, "string", "int", "string"); } inline static gchar * -searpc_signature_string__void() +searpc_signature_string__void(void) { return searpc_compute_signature ("string", 0); } inline static gchar * -searpc_signature_string__int() +searpc_signature_string__int(void) { return searpc_compute_signature ("string", 1, "int"); } inline static gchar * -searpc_signature_string__int_int() +searpc_signature_string__int_int(void) { return searpc_compute_signature ("string", 2, "int", "int"); } inline static gchar * -searpc_signature_string__int_string() +searpc_signature_string__int_string(void) { return searpc_compute_signature ("string", 2, "int", "string"); } inline static gchar * -searpc_signature_string__int_int_string() +searpc_signature_string__int_int_string(void) { return searpc_compute_signature ("string", 3, "int", "int", "string"); } inline static gchar * -searpc_signature_string__string() +searpc_signature_string__string(void) { return searpc_compute_signature ("string", 1, "string"); } inline static gchar * -searpc_signature_string__string_int() +searpc_signature_string__string_int(void) { return searpc_compute_signature ("string", 2, "string", "int"); } inline static gchar * -searpc_signature_string__string_int_int() +searpc_signature_string__string_int_int(void) { return searpc_compute_signature ("string", 3, "string", "int", "int"); } inline static gchar * -searpc_signature_string__string_string() +searpc_signature_string__string_string(void) { return searpc_compute_signature ("string", 2, "string", "string"); } inline static gchar * -searpc_signature_string__string_string_int() +searpc_signature_string__string_string_int(void) { return searpc_compute_signature ("string", 3, "string", "string", "int"); } inline static gchar * -searpc_signature_string__string_string_int_int() +searpc_signature_string__string_string_int_int(void) { return searpc_compute_signature ("string", 4, "string", "string", "int", "int"); } inline static gchar * -searpc_signature_string__string_string_string() +searpc_signature_string__string_string_string(void) { return searpc_compute_signature ("string", 3, "string", "string", "string"); } inline static gchar * -searpc_signature_string__string_string_string_string() +searpc_signature_string__string_string_string_string(void) { return searpc_compute_signature ("string", 4, "string", "string", "string", "string"); } inline static gchar * -searpc_signature_string__string_string_string_string_int() +searpc_signature_string__string_string_string_string_int(void) { return searpc_compute_signature ("string", 5, "string", "string", "string", "string", "int"); } inline static gchar * -searpc_signature_string__string_string_string_string_string() +searpc_signature_string__string_string_string_string_string(void) { return searpc_compute_signature ("string", 5, "string", "string", "string", "string", "string"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_int() +searpc_signature_string__string_string_string_string_string_int(void) { return searpc_compute_signature ("string", 6, "string", "string", "string", "string", "string", "int"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_string_int() +searpc_signature_string__string_string_string_string_string_string_int(void) { return searpc_compute_signature ("string", 7, "string", "string", "string", "string", "string", "string", "int"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_string_int_int() +searpc_signature_string__string_string_string_string_string_string_int_int(void) { return searpc_compute_signature ("string", 8, "string", "string", "string", "string", "string", "string", "int", "int"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_string() +searpc_signature_string__string_string_string_string_string_string(void) { return searpc_compute_signature ("string", 6, "string", "string", "string", "string", "string", "string"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_string_int64() +searpc_signature_string__string_string_string_string_string_string_int64(void) { return searpc_compute_signature ("string", 7, "string", "string", "string", "string", "string", "string", "int64"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_string_int64_int() +searpc_signature_string__string_string_string_string_string_string_int64_int(void) { return searpc_compute_signature ("string", 8, "string", "string", "string", "string", "string", "string", "int64", "int"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_string_string() +searpc_signature_string__string_string_string_string_string_string_string(void) { return searpc_compute_signature ("string", 7, "string", "string", "string", "string", "string", "string", "string"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_string_string_int64() +searpc_signature_string__string_string_string_string_string_string_string_int64(void) { return searpc_compute_signature ("string", 8, "string", "string", "string", "string", "string", "string", "string", "int64"); } inline static gchar * -searpc_signature_string__string_string_string_string_string_string_string_string_string() +searpc_signature_string__string_string_string_string_string_string_string_string_string(void) { return searpc_compute_signature ("string", 9, "string", "string", "string", "string", "string", "string", "string", "string", "string"); } inline static gchar * -searpc_signature_string__string_int_string_string_string_string_string_string_string_int_string() +searpc_signature_string__string_int_string_string_string_string_string_string_string_int_string(void) { return searpc_compute_signature ("string", 11, "string", "int", "string", "string", "string", "string", "string", "string", "string", "int", "string"); } inline static gchar * -searpc_signature_string__string_int_string_int_int() +searpc_signature_string__string_int_string_int_int(void) { return searpc_compute_signature ("string", 5, "string", "int", "string", "int", "int"); } inline static gchar * -searpc_signature_string__string_int_string_string_string() +searpc_signature_string__string_int_string_string_string(void) { return searpc_compute_signature ("string", 5, "string", "int", "string", "string", "string"); } inline static gchar * -searpc_signature_objlist__void() +searpc_signature_objlist__void(void) { return searpc_compute_signature ("objlist", 0); } inline static gchar * -searpc_signature_objlist__int() +searpc_signature_objlist__int(void) { return searpc_compute_signature ("objlist", 1, "int"); } inline static gchar * -searpc_signature_objlist__int_int() +searpc_signature_objlist__int_int(void) { return searpc_compute_signature ("objlist", 2, "int", "int"); } inline static gchar * -searpc_signature_objlist__int_string() +searpc_signature_objlist__int_string(void) { return searpc_compute_signature ("objlist", 2, "int", "string"); } inline static gchar * -searpc_signature_objlist__int_int_int() +searpc_signature_objlist__int_int_int(void) { return searpc_compute_signature ("objlist", 3, "int", "int", "int"); } inline static gchar * -searpc_signature_objlist__string() +searpc_signature_objlist__string(void) { return searpc_compute_signature ("objlist", 1, "string"); } inline static gchar * -searpc_signature_objlist__string_int() +searpc_signature_objlist__string_int(void) { return searpc_compute_signature ("objlist", 2, "string", "int"); } inline static gchar * -searpc_signature_objlist__string_int_int() +searpc_signature_objlist__string_int_int(void) { return searpc_compute_signature ("objlist", 3, "string", "int", "int"); } inline static gchar * -searpc_signature_objlist__string_int_string() +searpc_signature_objlist__string_int_string(void) { return searpc_compute_signature ("objlist", 3, "string", "int", "string"); } inline static gchar * -searpc_signature_objlist__string_string() +searpc_signature_objlist__string_string(void) { return searpc_compute_signature ("objlist", 2, "string", "string"); } inline static gchar * -searpc_signature_objlist__string_string_string() +searpc_signature_objlist__string_string_string(void) { return searpc_compute_signature ("objlist", 3, "string", "string", "string"); } inline static gchar * -searpc_signature_objlist__string_string_int() +searpc_signature_objlist__string_string_int(void) { return searpc_compute_signature ("objlist", 3, "string", "string", "int"); } inline static gchar * -searpc_signature_objlist__string_string_string_int() +searpc_signature_objlist__string_string_string_int(void) { return searpc_compute_signature ("objlist", 4, "string", "string", "string", "int"); } inline static gchar * -searpc_signature_objlist__string_string_int_int() +searpc_signature_objlist__string_string_int_int(void) { return searpc_compute_signature ("objlist", 4, "string", "string", "int", "int"); } inline static gchar * -searpc_signature_objlist__string_string_int_int_int() +searpc_signature_objlist__string_string_int_int_int(void) { return searpc_compute_signature ("objlist", 5, "string", "string", "int", "int", "int"); } inline static gchar * -searpc_signature_objlist__int_string_string_int_int() +searpc_signature_objlist__int_string_string_int_int(void) { return searpc_compute_signature ("objlist", 5, "int", "string", "string", "int", "int"); } inline static gchar * -searpc_signature_objlist__string_int_string_string_string() +searpc_signature_objlist__string_int_string_string_string(void) { return searpc_compute_signature ("objlist", 5, "string", "int", "string", "string", "string"); } inline static gchar * -searpc_signature_objlist__string_int_string_int_int() +searpc_signature_objlist__string_int_string_int_int(void) { return searpc_compute_signature ("objlist", 5, "string", "int", "string", "int", "int"); } inline static gchar * -searpc_signature_objlist__string_int_string_string_int() +searpc_signature_objlist__string_int_string_string_int(void) { return searpc_compute_signature ("objlist", 5, "string", "int", "string", "string", "int"); } inline static gchar * -searpc_signature_objlist__string_string_string_string_int_int() +searpc_signature_objlist__string_string_string_string_int_int(void) { return searpc_compute_signature ("objlist", 6, "string", "string", "string", "string", "int", "int"); } inline static gchar * -searpc_signature_object__int() +searpc_signature_object__int(void) { return searpc_compute_signature ("object", 1, "int"); } inline static gchar * -searpc_signature_object__string() +searpc_signature_object__string(void) { return searpc_compute_signature ("object", 1, "string"); } inline static gchar * -searpc_signature_object__string_string() +searpc_signature_object__string_string(void) { return searpc_compute_signature ("object", 2, "string", "string"); } inline static gchar * -searpc_signature_object__string_string_string() +searpc_signature_object__string_string_string(void) { return searpc_compute_signature ("object", 3, "string", "string", "string"); } inline static gchar * -searpc_signature_object__string_int_string() +searpc_signature_object__string_int_string(void) { return searpc_compute_signature ("object", 3, "string", "int", "string"); } inline static gchar * -searpc_signature_object__int_string_string() +searpc_signature_object__int_string_string(void) { return searpc_compute_signature ("object", 3, "int", "string", "string"); } inline static gchar * -searpc_signature_object__string_string_string_string_string_string_string_int_int() +searpc_signature_object__int_string_string_string_string(void) +{ + return searpc_compute_signature ("object", 5, "int", "string", "string", "string", "string"); +} + + +inline static gchar * +searpc_signature_object__string_string_string_string_string_string_string_int_int(void) { return searpc_compute_signature ("object", 9, "string", "string", "string", "string", "string", "string", "string", "int", "int"); } inline static gchar * -searpc_signature_object__string_string_string_string_string_string_int_string_int_int() +searpc_signature_object__string_string_string_string_string_string_int_string_int_int(void) { return searpc_compute_signature ("object", 10, "string", "string", "string", "string", "string", "string", "int", "string", "int", "int"); } inline static gchar * -searpc_signature_json__void() +searpc_signature_json__void(void) { return searpc_compute_signature ("json", 0); }