1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-09-02 07:54:27 +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:
feiniks
2024-05-22 18:49:57 +08:00
committed by GitHub
parent 9f5fcdfe4d
commit 96996b79e3
26 changed files with 611 additions and 76 deletions

View File

@@ -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");