aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2025-01-23 23:21:44 +0100
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2025-01-23 23:37:39 +0100
commit9752843329a257542c34798d65e829a6cff7764b (patch)
treeb834d2d3dd4c27cae03f3d2c663644ecae3d1a8d
parent5c4e226ddcd132c0dfa9a9cf096d3b3f8fc3c171 (diff)
downloadslcl-9752843329a257542c34798d65e829a6cff7764b.tar.gz
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.
-rw-r--r--main.c41
-rw-r--r--page.c2
-rw-r--r--page.h1
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);