mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-09-01 23:46:53 +00:00
Support argon2id password hash algo (#637)
* Support argon2id password hash algo * CI install argon2 deps * Go support argonid algo * RPC add pwd_hash_algo and pwd_hash_params * Support password hash algo * Don't set magic when pwd_hash is set * Fix ci error --------- Co-authored-by: 杨赫然 <heran.yang@seafile.com>
This commit is contained in:
@@ -69,6 +69,7 @@ seaf_server_SOURCES = \
|
||||
../common/obj-store.c \
|
||||
../common/obj-backend-fs.c \
|
||||
../common/seafile-crypt.c \
|
||||
../common/password-hash.c \
|
||||
../common/diff-simple.c \
|
||||
../common/mq-mgr.c \
|
||||
../common/user-mgr.c \
|
||||
@@ -86,4 +87,4 @@ seaf_server_LDADD = $(top_builddir)/lib/libseafile_common.la \
|
||||
@SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \
|
||||
@LIBARCHIVE_LIBS@ @LIB_ICONV@ \
|
||||
@LDAP_LIBS@ @MYSQL_LIBS@ -lsqlite3 \
|
||||
@CURL_LIBS@ @JWT_LIBS@
|
||||
@CURL_LIBS@ @JWT_LIBS@ @ARGON2_LIBS@
|
||||
|
@@ -36,6 +36,7 @@ common_sources = \
|
||||
../../common/obj-store.c \
|
||||
../../common/obj-backend-fs.c \
|
||||
../../common/seafile-crypt.c \
|
||||
../../common/password-hash.c \
|
||||
../../common/config-mgr.c
|
||||
|
||||
seafserv_gc_SOURCES = \
|
||||
@@ -48,7 +49,7 @@ seafserv_gc_LDADD = $(top_builddir)/common/cdc/libcdc.la \
|
||||
$(top_builddir)/lib/libseafile_common.la \
|
||||
@GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \
|
||||
@SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \
|
||||
@MYSQL_LIBS@ -lsqlite3
|
||||
@MYSQL_LIBS@ -lsqlite3 @ARGON2_LIBS@
|
||||
|
||||
seaf_fsck_SOURCES = \
|
||||
seaf-fsck.c \
|
||||
@@ -59,4 +60,4 @@ seaf_fsck_LDADD = $(top_builddir)/common/cdc/libcdc.la \
|
||||
$(top_builddir)/lib/libseafile_common.la \
|
||||
@GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \
|
||||
@SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \
|
||||
@MYSQL_LIBS@ -lsqlite3
|
||||
@MYSQL_LIBS@ -lsqlite3 @ARGON2_LIBS@
|
||||
|
@@ -125,12 +125,23 @@ seaf_passwd_manager_set_passwd (SeafPasswdManager *mgr,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (seafile_verify_repo_passwd (repo->id, passwd,
|
||||
repo->magic, repo->enc_version, repo->salt) < 0) {
|
||||
seaf_repo_unref (repo);
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Incorrect password");
|
||||
return -1;
|
||||
if (repo->pwd_hash_algo) {
|
||||
if (seafile_pwd_hash_verify_repo_passwd (repo->id, passwd, repo->salt,
|
||||
repo->pwd_hash, repo->pwd_hash_algo, repo->pwd_hash_params) < 0) {
|
||||
seaf_repo_unref (repo);
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Incorrect password");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (seafile_verify_repo_passwd (repo->id, passwd,
|
||||
repo->magic,
|
||||
repo->enc_version, repo->salt) < 0) {
|
||||
seaf_repo_unref (repo);
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Incorrect password");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
crypt_key = g_new0 (DecryptKey, 1);
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "fs-mgr.h"
|
||||
#include "seafile-error.h"
|
||||
#include "seafile-crypt.h"
|
||||
#include "password-hash.h"
|
||||
|
||||
#include "seaf-db.h"
|
||||
#include "seaf-utils.h"
|
||||
@@ -89,6 +90,8 @@ seaf_repo_free (SeafRepo *repo)
|
||||
if (repo->virtual_info)
|
||||
seaf_virtual_repo_info_free (repo->virtual_info);
|
||||
g_free (repo->last_modifier);
|
||||
g_free (repo->pwd_hash_algo);
|
||||
g_free (repo->pwd_hash_params);
|
||||
g_free (repo);
|
||||
}
|
||||
|
||||
@@ -137,20 +140,25 @@ 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;
|
||||
@@ -166,20 +174,25 @@ seaf_repo_to_commit (SeafRepo *repo, SeafCommit *commit)
|
||||
commit->repaired = repo->repaired;
|
||||
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;
|
||||
@@ -3728,16 +3741,37 @@ seaf_repo_manager_is_valid_filename (SeafRepoManager *mgr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct _RepoCryptCompat {
|
||||
const char *magic;
|
||||
const char *pwd_hash;
|
||||
const char *pwd_hash_algo;
|
||||
const char *pwd_hash_params;
|
||||
} RepoCryptInfo;
|
||||
|
||||
static
|
||||
RepoCryptInfo *
|
||||
repo_crypt_info_new (const char *magic, const char *pwd_hash,
|
||||
const char *algo, const char *params)
|
||||
{
|
||||
RepoCryptInfo *crypt_info = g_new0 (RepoCryptInfo, 1);
|
||||
crypt_info->magic = magic;
|
||||
crypt_info->pwd_hash = pwd_hash;
|
||||
crypt_info->pwd_hash_algo = algo;
|
||||
crypt_info->pwd_hash_params = params;
|
||||
|
||||
return crypt_info;
|
||||
}
|
||||
|
||||
static int
|
||||
create_repo_common (SeafRepoManager *mgr,
|
||||
const char *repo_id,
|
||||
const char *repo_name,
|
||||
const char *repo_desc,
|
||||
const char *user,
|
||||
const char *magic,
|
||||
const char *random_key,
|
||||
const char *salt,
|
||||
int enc_version,
|
||||
RepoCryptInfo *crypt_info,
|
||||
GError **error)
|
||||
{
|
||||
SeafRepo *repo = NULL;
|
||||
@@ -3751,9 +3785,27 @@ create_repo_common (SeafRepoManager *mgr,
|
||||
"Unsupported encryption version");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (crypt_info && crypt_info->pwd_hash_algo) {
|
||||
if (g_strcmp0 (crypt_info->pwd_hash_algo, PWD_HASH_PDKDF2) != 0 &&
|
||||
g_strcmp0 (crypt_info->pwd_hash_algo, PWD_HASH_ARGON2ID) !=0)
|
||||
{
|
||||
seaf_warning ("Unsupported enc algothrims %s.\n", crypt_info->pwd_hash_algo);
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
|
||||
"Unsupported encryption algothrims");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!crypt_info->pwd_hash || strlen(crypt_info->pwd_hash) != 64) {
|
||||
seaf_warning ("Bad pwd_hash.\n");
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
|
||||
"Bad pwd_hash");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_version >= 2) {
|
||||
if (!magic || strlen(magic) != 64) {
|
||||
if (!crypt_info->pwd_hash_algo && (!crypt_info->magic || strlen(crypt_info->magic) != 64)) {
|
||||
seaf_warning ("Bad magic.\n");
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
|
||||
"Bad magic");
|
||||
@@ -3778,15 +3830,24 @@ create_repo_common (SeafRepoManager *mgr,
|
||||
repo = seaf_repo_new (repo_id, repo_name, repo_desc);
|
||||
|
||||
repo->no_local_history = TRUE;
|
||||
|
||||
if (enc_version >= 2) {
|
||||
repo->encrypted = TRUE;
|
||||
repo->enc_version = enc_version;
|
||||
memcpy (repo->magic, magic, 64);
|
||||
if (!crypt_info->pwd_hash_algo)
|
||||
memcpy (repo->magic, crypt_info->magic, 64);
|
||||
memcpy (repo->random_key, random_key, 96);
|
||||
}
|
||||
if (enc_version >= 3)
|
||||
memcpy (repo->salt, salt, 64);
|
||||
|
||||
if (crypt_info && crypt_info->pwd_hash_algo) {
|
||||
// set pwd_hash fields here.
|
||||
memcpy (repo->pwd_hash, crypt_info->pwd_hash, 64);
|
||||
repo->pwd_hash_algo = g_strdup (crypt_info->pwd_hash_algo);
|
||||
repo->pwd_hash_params = g_strdup (crypt_info->pwd_hash_params);
|
||||
}
|
||||
|
||||
repo->version = CURRENT_REPO_VERSION;
|
||||
memcpy (repo->store_id, repo_id, 36);
|
||||
|
||||
@@ -3851,7 +3912,9 @@ seaf_repo_manager_create_new_repo (SeafRepoManager *mgr,
|
||||
GError **error)
|
||||
{
|
||||
char *repo_id = NULL;
|
||||
char salt[65], magic[65], random_key[97];
|
||||
char salt[65], magic[65], pwd_hash[65], random_key[97];
|
||||
const char *algo = seafile_crypt_get_default_pwd_hash_algo ();
|
||||
const char *params = seafile_crypt_get_default_pwd_hash_params ();
|
||||
|
||||
repo_id = gen_uuid ();
|
||||
|
||||
@@ -3859,19 +3922,26 @@ seaf_repo_manager_create_new_repo (SeafRepoManager *mgr,
|
||||
if (seafile_generate_repo_salt (salt) < 0) {
|
||||
goto bad;
|
||||
}
|
||||
seafile_generate_magic (enc_version, repo_id, passwd, salt, magic);
|
||||
if (algo != NULL) {
|
||||
seafile_generate_pwd_hash (repo_id, passwd, salt, algo, 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) {
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
int rc;
|
||||
if (passwd)
|
||||
if (passwd) {
|
||||
RepoCryptInfo *crypt_info = repo_crypt_info_new (magic, pwd_hash, algo, params);
|
||||
rc = create_repo_common (mgr, repo_id, repo_name, repo_desc, owner_email,
|
||||
magic, random_key, salt, enc_version, error);
|
||||
random_key, salt, enc_version, crypt_info, error);
|
||||
g_free (crypt_info);
|
||||
}
|
||||
else
|
||||
rc = create_repo_common (mgr, repo_id, repo_name, repo_desc, owner_email,
|
||||
NULL, NULL, NULL, -1, error);
|
||||
NULL, NULL, -1, NULL, error);
|
||||
if (rc < 0)
|
||||
goto bad;
|
||||
|
||||
@@ -3900,6 +3970,9 @@ seaf_repo_manager_create_enc_repo (SeafRepoManager *mgr,
|
||||
const char *random_key,
|
||||
const char *salt,
|
||||
int enc_version,
|
||||
const char *pwd_hash,
|
||||
const char *pwd_hash_algo,
|
||||
const char *pwd_hash_params,
|
||||
GError **error)
|
||||
{
|
||||
if (!repo_id || !is_uuid_valid (repo_id)) {
|
||||
@@ -3916,9 +3989,13 @@ seaf_repo_manager_create_enc_repo (SeafRepoManager *mgr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RepoCryptInfo *crypt_info = repo_crypt_info_new (magic, pwd_hash, pwd_hash_algo, pwd_hash_params);
|
||||
if (create_repo_common (mgr, repo_id, repo_name, repo_desc, owner_email,
|
||||
magic, random_key, salt, enc_version, error) < 0)
|
||||
random_key, salt, enc_version, crypt_info, error) < 0) {
|
||||
g_free (crypt_info);
|
||||
return NULL;
|
||||
}
|
||||
g_free (crypt_info);
|
||||
|
||||
if (seaf_repo_manager_set_repo_owner (mgr, repo_id, owner_email) < 0) {
|
||||
seaf_warning ("Failed to set repo owner.\n");
|
||||
|
@@ -33,6 +33,9 @@ struct _SeafRepo {
|
||||
gboolean encrypted;
|
||||
int enc_version;
|
||||
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];
|
||||
gchar salt[65];
|
||||
gboolean no_local_history;
|
||||
@@ -513,6 +516,9 @@ seaf_repo_manager_create_enc_repo (SeafRepoManager *mgr,
|
||||
const char *random_key,
|
||||
const char *salt,
|
||||
int enc_version,
|
||||
const char *pwd_hash,
|
||||
const char *pwd_hash_algo,
|
||||
const char *pwd_hash_params,
|
||||
GError **error);
|
||||
|
||||
/* Give a repo and a path in this repo, returns a list of commits, where every
|
||||
|
@@ -227,7 +227,7 @@ static void start_rpc_service (const char *seafile_dir,
|
||||
searpc_server_register_function ("seafserv-threaded-rpcserver",
|
||||
seafile_create_enc_repo,
|
||||
"seafile_create_enc_repo",
|
||||
searpc_signature_string__string_string_string_string_string_string_string_int());
|
||||
searpc_signature_string__string_string_string_string_string_string_string_int_string_string_string());
|
||||
|
||||
searpc_server_register_function ("seafserv-threaded-rpcserver",
|
||||
seafile_get_commit,
|
||||
|
@@ -122,6 +122,8 @@ seafile_session_new(const char *central_config_dir,
|
||||
char *notif_server = NULL;
|
||||
int notif_port = 8083;
|
||||
char *private_key = NULL;
|
||||
char *pwd_hash_algo = NULL;
|
||||
char *pwd_hash_params = NULL;
|
||||
|
||||
abs_ccnet_dir = ccnet_expand_path (ccnet_dir);
|
||||
abs_seafile_dir = ccnet_expand_path (seafile_dir);
|
||||
@@ -208,6 +210,17 @@ seafile_session_new(const char *central_config_dir,
|
||||
session->private_key = private_key;
|
||||
}
|
||||
|
||||
pwd_hash_algo = g_key_file_get_string (config,
|
||||
"password_hash", "pwd_hash_algo",
|
||||
NULL);
|
||||
|
||||
pwd_hash_params = g_key_file_get_string (config,
|
||||
"password_hash", "pwd_hash_params",
|
||||
NULL);
|
||||
seafile_crypt_init (pwd_hash_algo, pwd_hash_params);
|
||||
g_free (pwd_hash_algo);
|
||||
g_free (pwd_hash_params);
|
||||
|
||||
if (load_database_config (session) < 0) {
|
||||
seaf_warning ("Failed to load database config.\n");
|
||||
goto onerror;
|
||||
@@ -309,6 +322,8 @@ onerror:
|
||||
free (abs_seafile_dir);
|
||||
free (abs_ccnet_dir);
|
||||
g_free (tmp_file_dir);
|
||||
g_free (pwd_hash_algo);
|
||||
g_free (pwd_hash_params);
|
||||
g_free (session);
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -85,7 +85,17 @@ do_create_virtual_repo (SeafRepoManager *mgr,
|
||||
repo->enc_version = origin_repo->enc_version;
|
||||
if (repo->enc_version >= 3)
|
||||
memcpy (repo->salt, origin_repo->salt, 64);
|
||||
seafile_generate_magic (repo->enc_version, repo_id, passwd, repo->salt, repo->magic);
|
||||
if (origin_repo->pwd_hash_algo)
|
||||
repo->pwd_hash_algo = g_strdup (origin_repo->pwd_hash_algo);
|
||||
if (origin_repo->pwd_hash_params)
|
||||
repo->pwd_hash_params = g_strdup (origin_repo->pwd_hash_params);
|
||||
if (repo->pwd_hash_algo) {
|
||||
seafile_generate_pwd_hash (repo_id, passwd, repo->salt,
|
||||
repo->pwd_hash_algo, repo->pwd_hash_params, repo->pwd_hash);
|
||||
memcpy (repo->magic, repo->pwd_hash, 32);
|
||||
} else
|
||||
seafile_generate_magic (repo->enc_version, repo_id, passwd, repo->salt,
|
||||
repo->magic);
|
||||
if (repo->enc_version >= 2)
|
||||
memcpy (repo->random_key, origin_repo->random_key, 96);
|
||||
}
|
||||
@@ -220,15 +230,29 @@ create_virtual_repo_common (SeafRepoManager *mgr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (seafile_verify_repo_passwd (origin_repo_id,
|
||||
passwd,
|
||||
origin_repo->magic,
|
||||
origin_repo->enc_version,
|
||||
origin_repo->salt) < 0) {
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Incorrect password");
|
||||
seaf_repo_unref (origin_repo);
|
||||
return NULL;
|
||||
if (origin_repo->pwd_hash_algo) {
|
||||
if (seafile_pwd_hash_verify_repo_passwd (origin_repo_id,
|
||||
passwd,
|
||||
origin_repo->salt,
|
||||
origin_repo->pwd_hash,
|
||||
origin_repo->pwd_hash_algo,
|
||||
origin_repo->pwd_hash_params) < 0) {
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Incorrect password");
|
||||
seaf_repo_unref (origin_repo);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (seafile_verify_repo_passwd (origin_repo_id,
|
||||
passwd,
|
||||
origin_repo->magic,
|
||||
origin_repo->enc_version,
|
||||
origin_repo->salt) < 0) {
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Incorrect password");
|
||||
seaf_repo_unref (origin_repo);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user