Construct full path of requested resource

Also detects .. in the selector string, as this could be used to see
files outside of srvroot, otherwise.
This commit is contained in:
Camden Dixie O'Brien 2022-10-13 17:56:41 +01:00
parent f6871a7922
commit a3cdde2c34

60
main.c
View File

@ -61,6 +61,26 @@ static int retrying_write(int fd, const char *buf, size_t len)
return n; return n;
} }
static int append_selector_part(const char *part, size_t partlen, char *buf,
size_t bufsize)
{
if (partlen == 0)
return 0;
if (strncmp(part, "..", partlen) == 0) {
fprintf(stderr, "Selector string contains \"..\"\n");
return -1;
} else if (partlen + 1 > bufsize) {
fprintf(stderr, "Path buffer too small\n");
return -1;
}
*buf++ = '/';
memcpy(buf, part, partlen);
return partlen + 1;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
(void)argc; (void)argc;
@ -190,9 +210,42 @@ int main(int argc, char *argv[])
} }
/* /*
* Open the requested resource. * Construct the full path to the requested resource.
* *
* For now, this is just opening srvroot. * This is needed in order to pass it to stat() and open() or
* opendir() later. It must be null-terminated. We also need
* to make sure that none of the path's parts are "..", as
* this could be used to escape the srvroot directory.
*/
char *sp = sbuf;
unsigned splen = 0, ppos = srvroot_len;
for (unsigned i = 0; i < slen; ++i) {
if (sbuf[i] != '/') {
++splen;
continue;
}
n = append_selector_part(sp, splen, &pbuf[ppos], PBUF_SIZE - ppos);
if (n == -1)
goto close_client_socket;
ppos += n;
sp = &sbuf[i + 1];
splen = 0;
}
n = append_selector_part(sp, splen, &pbuf[ppos], PBUF_SIZE - ppos);
if (n == -1)
goto close_client_socket;
ppos += n;
// UNSAFE!
pbuf[ppos] = '\0';
printf("Requested path: %s\n", pbuf);
/*
* Determine the resource's type.
*/
/*
* Open the resource.
*/ */
if (srvroot_len + 1 > PBUF_SIZE) { if (srvroot_len + 1 > PBUF_SIZE) {
fprintf(stderr, "Path buffer is too small\n"); fprintf(stderr, "Path buffer is too small\n");
@ -260,8 +313,7 @@ int main(int argc, char *argv[])
continue; continue;
} }
if (retrying_write(cfd, rbuf, n) != n) { if (retrying_write(cfd, rbuf, n) != n) {
fprintf(stderr, fprintf(stderr, "Error sending respose line to client\n");
"Error sending respose line to client\n");
continue; continue;
} }
} }