main.c: Treat non-existing upload dir as non-fatal
When a user attempts to upload a file into a non-existing directory, slcl would not check whether the directory exists. Then, rename(3) would fail and slcl would treat this as a fatal error, effectively closing itself. Since this is an example of ill-formed user input, it must be treated as a non-fatal error, and instead slcl should return a bad request page.
This commit is contained in:
parent
0854bc0030
commit
daffea4660
56
main.c
56
main.c
|
@ -1131,12 +1131,43 @@ static int rename_or_move(const char *const old, const char *const new)
|
|||
return res;
|
||||
}
|
||||
|
||||
static int check_upload_dir(const char *const dir)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (stat(dir, &sb))
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case ENOENT:
|
||||
/* Fall through. */
|
||||
case ENOTDIR:
|
||||
fprintf(stderr, "%s: cannot upload to non-existing dir %s\n",
|
||||
__func__, dir);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s: stat(2) %s: %s\n",
|
||||
__func__, dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (!S_ISDIR(sb.st_mode))
|
||||
{
|
||||
fprintf(stderr, "%s: %s not a dir\n", __func__, dir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upload_file(const struct http_post_file *const f,
|
||||
const char *const user, const char *const root, const char *const dir)
|
||||
{
|
||||
int ret = -1;
|
||||
struct dynstr d;
|
||||
struct dynstr dird, d;
|
||||
|
||||
dynstr_init(&dird);
|
||||
dynstr_init(&d);
|
||||
|
||||
if (!root)
|
||||
|
@ -1144,9 +1175,21 @@ static int upload_file(const struct http_post_file *const f,
|
|||
fprintf(stderr, "%s: auth_dir failed\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
else if (dynstr_append(&d, "%s/user/%s/%s%s", root, user, dir, f->filename))
|
||||
else if (dynstr_append(&dird, "%s/user/%s/%s", root, user, dir))
|
||||
{
|
||||
fprintf(stderr, "%s: dynstr_append failed\n", __func__);
|
||||
fprintf(stderr, "%s: dynstr_append dird failed\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
else if ((ret = check_upload_dir(dird.str)))
|
||||
{
|
||||
if (ret < 0)
|
||||
fprintf(stderr, "%s: check_upload_dir failed\n", __func__);
|
||||
|
||||
goto end;
|
||||
}
|
||||
else if (dynstr_append(&d, "%s%s", dird.str, f->filename))
|
||||
{
|
||||
fprintf(stderr, "%s: dynstr_append d failed\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
else if (rename_or_move(f->tmpname, d.str))
|
||||
|
@ -1158,6 +1201,7 @@ static int upload_file(const struct http_post_file *const f,
|
|||
ret = 0;
|
||||
|
||||
end:
|
||||
dynstr_free(&dird);
|
||||
dynstr_free(&d);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1257,11 +1301,15 @@ static int upload_files(const struct http_payload *const p,
|
|||
|
||||
for (size_t i = 0; i < po->nfiles; i++)
|
||||
{
|
||||
if (upload_file(&po->files[i], user, root, dir))
|
||||
const int ret = upload_file(&po->files[i], user, root, dir);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: upload_file failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (ret)
|
||||
return page_bad_request(r);
|
||||
}
|
||||
|
||||
return redirect_to_dir(dir, r);
|
||||
|
|
Loading…
Reference in New Issue