From 9752843329a257542c34798d65e829a6cff7764b Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Thu, 23 Jan 2025 23:21:44 +0100 Subject: main.c: Forbid sharing non-existing files So far, slcl would allow to share literally any directory or file, even if they did not exist, as long as valid credentials were given. Now, directories cannot be shared, since this is already restricted by the web interface. This is now considered an invalid request. On the other hand, attempting to share non-existing files shall now return a 404 Not Found response to the user. --- main.c | 41 +++++++++++++++++++++++++++++------------ page.c | 2 +- page.h | 1 + 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/main.c b/main.c index 3959295..aa57c5e 100644 --- a/main.c +++ b/main.c @@ -487,15 +487,13 @@ end: return ret; } -static char *create_symlink(const char *const username, const char *const dir, - const char *const path) +static char *create_symlink(const char *const dir, const char *user) { char *ret = NULL; unsigned char buf[16]; char dbuf[1 + 2 * sizeof buf]; - struct dynstr user, abs, rel; + struct dynstr abs, rel; - dynstr_init(&user); dynstr_init(&abs); dynstr_init(&rel); @@ -510,11 +508,6 @@ static char *create_symlink(const char *const username, const char *const dir, fprintf(stderr, "%s: hex_encode failed\n", __func__); goto end; } - else if (dynstr_append(&user, "%s/user/%s%s", dir, username, path)) - { - fprintf(stderr, "%s: dynstr_append user failed\n", __func__); - goto end; - } else if (dynstr_append(&rel, "/public/%s", dbuf)) { fprintf(stderr, "%s: dynstr_append rel failed\n", __func__); @@ -525,7 +518,7 @@ static char *create_symlink(const char *const username, const char *const dir, fprintf(stderr, "%s: dynstr_append abs failed\n", __func__); goto end; } - else if (symlink(user.str, abs.str)) + else if (symlink(user, abs.str)) { fprintf(stderr, "%s: symlink(2): %s\n", __func__, strerror(errno)); goto end; @@ -534,7 +527,6 @@ static char *create_symlink(const char *const username, const char *const dir, ret = rel.str; end: - dynstr_free(&user); dynstr_free(&abs); if (!ret) @@ -806,6 +798,9 @@ static int share(const struct http_payload *const p, struct form *forms = NULL; size_t n = 0; char *sympath = NULL; + struct dynstr userpath; + + dynstr_init(&userpath); if ((ret = get_forms(p, &forms, &n))) { @@ -824,6 +819,7 @@ static int share(const struct http_payload *const p, } const char *const path = forms->value, *const username = p->cookie.field; + struct stat sb; if (path_invalid(path)) { @@ -831,7 +827,27 @@ static int share(const struct http_payload *const p, ret = page_bad_request(r); goto end; } - else if (!(sympath = create_symlink(username, adir, path))) + else if (dynstr_append(&userpath, "%s/user/%s%s", adir, username, path)) + { + fprintf(stderr, "%s: dynstr_append user failed\n", __func__); + goto end; + } + else if (stat(userpath.str, &sb)) + { + fprintf(stderr, "%s: stat(2) %s: %s\n", __func__, userpath.str, + strerror(errno)); + + if (errno == ENOENT || errno == ENOTDIR) + ret = page_not_found(r); + + goto end; + } + else if (!S_ISREG(sb.st_mode)) + { + ret = page_bad_request(r); + goto end; + } + else if (!(sympath = create_symlink(adir, userpath.str))) { fprintf(stderr, "%s: create_symlink failed\n", __func__); goto end; @@ -847,6 +863,7 @@ static int share(const struct http_payload *const p, end: forms_free(forms, n); free(sympath); + dynstr_free(&userpath); return ret; } diff --git a/page.c b/page.c index 0d15473..c103f4a 100644 --- a/page.c +++ b/page.c @@ -1626,7 +1626,7 @@ end: return ret; } -static int page_not_found(struct http_response *const r) +int page_not_found(struct http_response *const r) { static const char body[] = DOCTYPE_TAG diff --git a/page.h b/page.h index 22658fd..ca7f3cc 100644 --- a/page.h +++ b/page.h @@ -42,6 +42,7 @@ int page_style(struct http_response *r, const char *path); int page_failed_login(struct http_response *r); int page_forbidden(struct http_response *r); int page_bad_request(struct http_response *r); +int page_not_found(struct http_response *r); int page_resource(const struct page_resource *r); int page_head_resource(struct http_response *r, const char *res); int page_public(struct http_response *r, const char *res); -- cgit v1.2.3