1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-09-19 18:16:25 +00:00

Merge branch '8.0'

This commit is contained in:
杨赫然
2021-12-14 17:45:05 +08:00
2 changed files with 90 additions and 25 deletions

View File

@@ -8,10 +8,11 @@ SETUP_DIR=${TESTS_DIR}/ci
cd $SETUP_DIR cd $SETUP_DIR
sudo systemctl start mysql.service
sudo apt-get update sudo apt-get update
sudo apt-get install -y intltool libarchive-dev libcurl4-openssl-dev libevent-dev \ sudo apt-get install -y intltool libarchive-dev libcurl4-openssl-dev libevent-dev \
libfuse-dev libglib2.0-dev libjansson-dev libmysqlclient-dev libonig-dev \ libfuse-dev libglib2.0-dev libjansson-dev libmysqlclient-dev libonig-dev \
sqlite3 libsqlite3-dev libtool net-tools uuid-dev valac mysql-client sqlite3 libsqlite3-dev libtool net-tools uuid-dev valac
sudo service mysql start sudo systemctl start mysql.service
pip install -r requirements.txt pip install -r requirements.txt

View File

@@ -95,8 +95,11 @@ typedef struct TokenInfo {
gint64 expire_time; gint64 expire_time;
} TokenInfo; } TokenInfo;
// PermInfo caches the results from the last permission check for accessing a repo.
// They're cached in a hash table having "repo_Id:username:op" as key.
// The cached result is updated on the next call to get_check_permission_cb function, or when the cache expires.
// The result is only cached if the permission check passed.
typedef struct PermInfo { typedef struct PermInfo {
char *perm;
gint64 expire_time; gint64 expire_time;
} PermInfo; } PermInfo;
@@ -342,25 +345,31 @@ validate_token (HttpServer *htp_server, evhtp_request_t *req,
} }
static PermInfo * static PermInfo *
lookup_perm_cache (HttpServer *htp_server, const char *repo_id, const char *username) lookup_perm_cache (HttpServer *htp_server, const char *repo_id, const char *username, const char *op)
{ {
PermInfo *ret = NULL; PermInfo *ret = NULL;
char *key = g_strdup_printf ("%s:%s", repo_id, username); PermInfo *perm = NULL;
char *key = g_strdup_printf ("%s:%s:%s", repo_id, username, op);
pthread_mutex_lock (&htp_server->perm_cache_lock); pthread_mutex_lock (&htp_server->perm_cache_lock);
ret = g_hash_table_lookup (htp_server->perm_cache, key); ret = g_hash_table_lookup (htp_server->perm_cache, key);
if (ret) {
perm = g_new0 (PermInfo, 1);
perm->expire_time = ret->expire_time;
}
pthread_mutex_unlock (&htp_server->perm_cache_lock); pthread_mutex_unlock (&htp_server->perm_cache_lock);
g_free (key); g_free (key);
return ret; return perm;
} }
static void static void
insert_perm_cache (HttpServer *htp_server, insert_perm_cache (HttpServer *htp_server,
const char *repo_id, const char *username, const char *repo_id, const char *username,
const char *op,
PermInfo *perm) PermInfo *perm)
{ {
char *key = g_strdup_printf ("%s:%s", repo_id, username); char *key = g_strdup_printf ("%s:%s:%s", repo_id, username, op);
pthread_mutex_lock (&htp_server->perm_cache_lock); pthread_mutex_lock (&htp_server->perm_cache_lock);
g_hash_table_insert (htp_server->perm_cache, key, perm); g_hash_table_insert (htp_server->perm_cache, key, perm);
@@ -369,9 +378,10 @@ insert_perm_cache (HttpServer *htp_server,
static void static void
remove_perm_cache (HttpServer *htp_server, remove_perm_cache (HttpServer *htp_server,
const char *repo_id, const char *username) const char *repo_id, const char *username,
const char *op)
{ {
char *key = g_strdup_printf ("%s:%s", repo_id, username); char *key = g_strdup_printf ("%s:%s:%s", repo_id, username, op);
pthread_mutex_lock (&htp_server->perm_cache_lock); pthread_mutex_lock (&htp_server->perm_cache_lock);
g_hash_table_remove (htp_server->perm_cache, key); g_hash_table_remove (htp_server->perm_cache, key);
@@ -380,6 +390,8 @@ remove_perm_cache (HttpServer *htp_server,
g_free (key); g_free (key);
} }
static void perm_cache_value_free (gpointer data);
static int static int
check_permission (HttpServer *htp_server, const char *repo_id, const char *username, check_permission (HttpServer *htp_server, const char *repo_id, const char *username,
const char *op, gboolean skip_cache) const char *op, gboolean skip_cache)
@@ -387,14 +399,15 @@ check_permission (HttpServer *htp_server, const char *repo_id, const char *usern
PermInfo *perm_info = NULL; PermInfo *perm_info = NULL;
if (!skip_cache) if (!skip_cache)
perm_info = lookup_perm_cache (htp_server, repo_id, username); perm_info = lookup_perm_cache (htp_server, repo_id, username, op);
if (perm_info) { if (perm_info) {
if (strcmp(perm_info->perm, "r") == 0 && strcmp(op, "upload") == 0) perm_cache_value_free (perm_info);
return EVHTP_RES_FORBIDDEN;
return EVHTP_RES_OK; return EVHTP_RES_OK;
} }
remove_perm_cache (htp_server, repo_id, username, op);
if (strcmp(op, "upload") == 0) { if (strcmp(op, "upload") == 0) {
int status = seaf_repo_manager_get_repo_status(seaf->repo_mgr, repo_id); int status = seaf_repo_manager_get_repo_status(seaf->repo_mgr, repo_id);
if (status != REPO_STATUS_NORMAL && status != -1) if (status != REPO_STATUS_NORMAL && status != -1)
@@ -404,19 +417,20 @@ check_permission (HttpServer *htp_server, const char *repo_id, const char *usern
char *perm = seaf_repo_manager_check_permission (seaf->repo_mgr, char *perm = seaf_repo_manager_check_permission (seaf->repo_mgr,
repo_id, username, NULL); repo_id, username, NULL);
if (perm) { if (perm) {
if ((strcmp (perm, "r") == 0 && strcmp (op, "upload") == 0)) {
g_free (perm);
return EVHTP_RES_FORBIDDEN;
}
g_free (perm);
perm_info = g_new0 (PermInfo, 1); perm_info = g_new0 (PermInfo, 1);
/* Take the reference of perm. */ /* Take the reference of perm. */
perm_info->perm = perm;
perm_info->expire_time = (gint64)time(NULL) + PERM_EXPIRE_TIME; perm_info->expire_time = (gint64)time(NULL) + PERM_EXPIRE_TIME;
insert_perm_cache (htp_server, repo_id, username, perm_info); insert_perm_cache (htp_server, repo_id, username, op, perm_info);
if ((strcmp (perm, "r") == 0 && strcmp (op, "upload") == 0))
return EVHTP_RES_FORBIDDEN;
return EVHTP_RES_OK; return EVHTP_RES_OK;
} }
/* Invalidate cache if perm not found in db. */ /* Invalidate cache if perm not found in db. */
remove_perm_cache (htp_server, repo_id, username);
return EVHTP_RES_FORBIDDEN; return EVHTP_RES_FORBIDDEN;
} }
@@ -1268,13 +1282,21 @@ get_commit_info_cb (evhtp_request_t *req, void *arg)
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0); char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
char *repo_id = parts[1]; char *repo_id = parts[1];
char *commit_id = parts[3]; char *commit_id = parts[3];
char *username = NULL;
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE); int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) { if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status); evhtp_send_reply (req, token_status);
goto out; goto out;
} }
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
char *data = NULL; char *data = NULL;
int len; int len;
@@ -1291,6 +1313,7 @@ get_commit_info_cb (evhtp_request_t *req, void *arg)
g_free (data); g_free (data);
out: out:
g_free (username);
g_strfreev (parts); g_strfreev (parts);
} }
@@ -1475,6 +1498,7 @@ get_fs_obj_id_cb (evhtp_request_t *req, void *arg)
char *repo_id; char *repo_id;
SeafRepo *repo = NULL; SeafRepo *repo = NULL;
gboolean dir_only = FALSE; gboolean dir_only = FALSE;
char *username = NULL;
const char *server_head = evhtp_kv_find (req->uri->query, "server-head"); const char *server_head = evhtp_kv_find (req->uri->query, "server-head");
if (server_head == NULL || !is_object_id_valid (server_head)) { if (server_head == NULL || !is_object_id_valid (server_head)) {
@@ -1501,12 +1525,19 @@ get_fs_obj_id_cb (evhtp_request_t *req, void *arg)
parts = g_strsplit (req->uri->path->full + 1, "/", 0); parts = g_strsplit (req->uri->path->full + 1, "/", 0);
repo_id = parts[1]; repo_id = parts[1];
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE); int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) { if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status); evhtp_send_reply (req, token_status);
goto out; goto out;
} }
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
GList *list = NULL, *ptr; GList *list = NULL, *ptr;
repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id); repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
@@ -1537,6 +1568,7 @@ get_fs_obj_id_cb (evhtp_request_t *req, void *arg)
json_decref (obj_array); json_decref (obj_array);
out: out:
g_free (username);
g_strfreev (parts); g_strfreev (parts);
seaf_repo_unref (repo); seaf_repo_unref (repo);
} }
@@ -1848,6 +1880,13 @@ get_block_cb (evhtp_request_t *req, void *arg)
goto out; goto out;
} }
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
store_id = get_repo_store_id (htp_server, repo_id); store_id = get_repo_store_id (htp_server, repo_id);
if (!store_id) { if (!store_id) {
evhtp_send_reply (req, EVHTP_RES_SERVERR); evhtp_send_reply (req, EVHTP_RES_SERVERR);
@@ -2015,13 +2054,21 @@ post_check_exist_cb (evhtp_request_t *req, void *arg, CheckExistType type)
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0); char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
char *repo_id = parts[1]; char *repo_id = parts[1];
char *store_id = NULL; char *store_id = NULL;
char *username = NULL;
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE); int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) { if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status); evhtp_send_reply (req, token_status);
goto out; goto out;
} }
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
store_id = get_repo_store_id (htp_server, repo_id); store_id = get_repo_store_id (htp_server, repo_id);
if (!store_id) { if (!store_id) {
evhtp_send_reply (req, EVHTP_RES_SERVERR); evhtp_send_reply (req, EVHTP_RES_SERVERR);
@@ -2088,6 +2135,7 @@ post_check_exist_cb (evhtp_request_t *req, void *arg, CheckExistType type)
json_decref (obj_array); json_decref (obj_array);
out: out:
g_free (username);
g_free (store_id); g_free (store_id);
g_strfreev (parts); g_strfreev (parts);
} }
@@ -2122,7 +2170,7 @@ post_recv_fs_cb (evhtp_request_t *req, void *arg)
int perm_status = check_permission (htp_server, repo_id, username, int perm_status = check_permission (htp_server, repo_id, username,
"upload", FALSE); "upload", FALSE);
if (perm_status == EVHTP_RES_FORBIDDEN) { if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN); evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out; goto out;
} }
@@ -2208,13 +2256,20 @@ post_pack_fs_cb (evhtp_request_t *req, void *arg)
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0); char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
const char *repo_id = parts[1]; const char *repo_id = parts[1];
char *store_id = NULL; char *store_id = NULL;
char *username = NULL;
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE); int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) { if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status); evhtp_send_reply (req, token_status);
goto out; goto out;
} }
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
store_id = get_repo_store_id (htp_server, repo_id); store_id = get_repo_store_id (htp_server, repo_id);
if (!store_id) { if (!store_id) {
evhtp_send_reply (req, EVHTP_RES_SERVERR); evhtp_send_reply (req, EVHTP_RES_SERVERR);
@@ -2290,6 +2345,7 @@ post_pack_fs_cb (evhtp_request_t *req, void *arg)
json_decref (fs_id_array); json_decref (fs_id_array);
out: out:
g_free (username);
g_free (store_id); g_free (store_id);
g_strfreev (parts); g_strfreev (parts);
} }
@@ -2306,17 +2362,25 @@ get_block_map_cb (evhtp_request_t *req, void *arg)
BlockMetadata *blk_meta = NULL; BlockMetadata *blk_meta = NULL;
json_t *array = NULL; json_t *array = NULL;
char *data = NULL; char *data = NULL;
char *username = NULL;
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0); char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
repo_id = parts[1]; repo_id = parts[1];
file_id = parts[3]; file_id = parts[3];
int token_status = validate_token (htp_server, req, repo_id, NULL, FALSE); int token_status = validate_token (htp_server, req, repo_id, &username, FALSE);
if (token_status != EVHTP_RES_OK) { if (token_status != EVHTP_RES_OK) {
evhtp_send_reply (req, token_status); evhtp_send_reply (req, token_status);
goto out; goto out;
} }
int perm_status = check_permission (htp_server, repo_id, username,
"download", FALSE);
if (perm_status != EVHTP_RES_OK) {
evhtp_send_reply (req, EVHTP_RES_FORBIDDEN);
goto out;
}
store_id = get_repo_store_id (htp_server, repo_id); store_id = get_repo_store_id (htp_server, repo_id);
if (!store_id) { if (!store_id) {
evhtp_send_reply (req, EVHTP_RES_SERVERR); evhtp_send_reply (req, EVHTP_RES_SERVERR);
@@ -2351,6 +2415,7 @@ get_block_map_cb (evhtp_request_t *req, void *arg)
evhtp_send_reply (req, EVHTP_RES_OK); evhtp_send_reply (req, EVHTP_RES_OK);
out: out:
g_free (username);
g_free (store_id); g_free (store_id);
seafile_unref (file); seafile_unref (file);
if (array) if (array)
@@ -2719,7 +2784,6 @@ static void
perm_cache_value_free (gpointer data) perm_cache_value_free (gpointer data)
{ {
PermInfo *perm_info = data; PermInfo *perm_info = data;
g_free (perm_info->perm);
g_free (perm_info); g_free (perm_info);
} }