aboutsummaryrefslogtreecommitdiff
path: root/main.c
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 /main.c
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.
Diffstat (limited to 'main.c')
-rw-r--r--main.c41
1 files changed, 29 insertions, 12 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;
}