From aee8be7942c8a0061305e29821686cbc8b6b80be Mon Sep 17 00:00:00 2001 From: feiniks <36756310+feiniks@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:13:23 +0800 Subject: [PATCH] Check if file or dir is .. (#711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Check if file or dir is .. * Diff and check name is .. * Go diff and check name is .. * Check if ignore new name or name --------- Co-authored-by: 杨赫然 <heran.yang@seafile.com> --- fileserver/fileop.go | 14 +++++++++++ fileserver/sync_api.go | 27 ++++++++++++++++++++ server/http-server.c | 56 ++++++++++++++++++++++++++++++++++++++++++ server/repo-mgr.c | 14 +++++++++++ 4 files changed, 111 insertions(+) diff --git a/fileserver/fileop.go b/fileserver/fileop.go index 38b684a..56ea7ff 100644 --- a/fileserver/fileop.go +++ b/fileserver/fileop.go @@ -2126,7 +2126,21 @@ func nameExists(entries []*fsmgr.SeafDirent, fileName string) bool { return false } +func shouldIgnore(fileName string) bool { + parts := strings.Split(fileName, "/") + for _, name := range parts { + if name == ".." { + return true + } + } + return false +} + func shouldIgnoreFile(fileName string) bool { + if shouldIgnore(fileName) { + return true + } + if !utf8.ValidString(fileName) { log.Printf("file name %s contains non-UTF8 characters, skip", fileName) return true diff --git a/fileserver/sync_api.go b/fileserver/sync_api.go index dd6c788..3490b26 100644 --- a/fileserver/sync_api.go +++ b/fileserver/sync_api.go @@ -1041,6 +1041,11 @@ func putUpdateBranchCB(rsp http.ResponseWriter, r *http.Request) *appError { return &appError{err, "", http.StatusInternalServerError} } + if includeInvalidPath(base, newCommit) { + msg := fmt.Sprintf("Dir or file name is ..") + return &appError{nil, msg, http.StatusBadRequest} + } + ret, err := checkQuota(repoID, 0) if err != nil { err := fmt.Errorf("Failed to check quota: %v", err) @@ -1064,6 +1069,28 @@ func putUpdateBranchCB(rsp http.ResponseWriter, r *http.Request) *appError { return nil } +func includeInvalidPath(baseCommit, newCommit *commitmgr.Commit) bool { + var results []*diff.DiffEntry + if err := diff.DiffCommits(baseCommit, newCommit, &results, true); err != nil { + log.Infof("Failed to diff commits: %v", err) + return false + } + + for _, entry := range results { + if entry.NewName != "" { + if shouldIgnore(entry.NewName) { + return true + } + } else { + if shouldIgnore(entry.Name) { + return true + } + } + } + + return false +} + func getHeadCommit(rsp http.ResponseWriter, r *http.Request) *appError { vars := mux.Vars(r) repoID := vars["repoid"] diff --git a/server/http-server.c b/server/http-server.c index 77c137b..cddee72 100644 --- a/server/http-server.c +++ b/server/http-server.c @@ -1028,6 +1028,57 @@ out: return ret; } +gboolean +should_ignore (const char *filename) +{ + char **components = g_strsplit (filename, "/", -1); + int n_comps = g_strv_length (components); + int j = 0; + char *file_name; + + for (; j < n_comps; ++j) { + file_name = components[j]; + if (g_strcmp0(file_name, "..") == 0) { + g_strfreev (components); + return TRUE; + } + } + g_strfreev (components); + + return FALSE; +} + +static gboolean +include_invalid_path (SeafCommit *base_commit, SeafCommit *new_commit) { + GList *diff_entries = NULL; + gboolean ret = FALSE; + + int rc = diff_commits (base_commit, new_commit, &diff_entries, TRUE); + if (rc < 0) { + seaf_warning ("Failed to check invalid path.\n"); + return FALSE; + } + + GList *ptr; + DiffEntry *diff_entry; + for (ptr = diff_entries; ptr; ptr = ptr->next) { + diff_entry = ptr->data; + if (diff_entry->new_name) { + if (should_ignore(diff_entry->new_name)) { + ret = TRUE; + break; + } + } else { + if (should_ignore(diff_entry->name)) { + ret = TRUE; + break; + } + } + } + + return ret; +} + static void put_update_branch_cb (evhtp_request_t *req, void *arg) { @@ -1084,6 +1135,11 @@ put_update_branch_cb (evhtp_request_t *req, void *arg) goto out; } + if (include_invalid_path (base, new_commit)) { + evhtp_send_reply (req, EVHTP_RES_BADREQ); + goto out; + } + if (seaf_quota_manager_check_quota (seaf->quota_mgr, repo_id) < 0) { evhtp_send_reply (req, SEAF_HTTP_RES_NOQUOTA); goto out; diff --git a/server/repo-mgr.c b/server/repo-mgr.c index 03acd42..566030c 100644 --- a/server/repo-mgr.c +++ b/server/repo-mgr.c @@ -242,6 +242,20 @@ should_ignore_file(const char *filename, void *data) { /* GPatternSpec **spec = ignore_patterns; */ + char **components = g_strsplit (filename, "/", -1); + int n_comps = g_strv_length (components); + int j = 0; + char *file_name; + + for (; j < n_comps; ++j) { + file_name = components[j]; + if (g_strcmp0(file_name, "..") == 0) { + g_strfreev (components); + return TRUE; + } + } + g_strfreev (components); + if (!g_utf8_validate (filename, -1, NULL)) { seaf_warning ("File name %s contains non-UTF8 characters, skip.\n", filename); return TRUE;