cgi-io: use dynamic memory for post decoding, support proc files
Allocate dynamic buffer memory for decoding post data and allow post requsts up to 128KB compared to the previos 1KB limit. Also support downloading /proc and /sys files by falling back to chunked transfer encoding when the file size cannot be determined. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
57dd0ca59b
commit
39087eba18
2 changed files with 98 additions and 46 deletions
|
@ -8,7 +8,7 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=cgi-io
|
||||
PKG_RELEASE:=16
|
||||
PKG_RELEASE:=17
|
||||
|
||||
PKG_LICENSE:=GPL-2.0-or-later
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "multipart_parser.h"
|
||||
|
||||
#define READ_BLOCK 4096
|
||||
#define POST_LIMIT 131072
|
||||
|
||||
enum part {
|
||||
PART_UNKNOWN,
|
||||
|
@ -223,55 +224,86 @@ urldecode(char *buf)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
static char *
|
||||
postdecode(char **fields, int n_fields)
|
||||
{
|
||||
char *p;
|
||||
const char *var;
|
||||
static char buf[1024];
|
||||
int i, len, field, found = 0;
|
||||
char *p, *postbuf;
|
||||
int i, field, found = 0;
|
||||
ssize_t len = 0, rlen = 0, content_length = 0;
|
||||
|
||||
var = getenv("CONTENT_TYPE");
|
||||
|
||||
if (!var || strncmp(var, "application/x-www-form-urlencoded", 33))
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
var = getenv("CONTENT_LENGTH");
|
||||
|
||||
if ((len = read(0, buf, sizeof(buf) - 1)) > 0)
|
||||
if (!var)
|
||||
return NULL;
|
||||
|
||||
content_length = strtol(var, &p, 10);
|
||||
|
||||
if (p == var || content_length <= 0 || content_length >= POST_LIMIT)
|
||||
return NULL;
|
||||
|
||||
postbuf = calloc(1, content_length + 1);
|
||||
|
||||
if (postbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
for (len = 0; len < content_length; )
|
||||
{
|
||||
for (p = buf, i = 0; i <= len; i++)
|
||||
{
|
||||
if (buf[i] == '=')
|
||||
{
|
||||
buf[i] = 0;
|
||||
rlen = read(0, postbuf + len, content_length - len);
|
||||
|
||||
for (field = 0; field < (n_fields * 2); field += 2)
|
||||
if (rlen <= 0)
|
||||
break;
|
||||
|
||||
len += rlen;
|
||||
}
|
||||
|
||||
if (len < content_length)
|
||||
{
|
||||
free(postbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (p = postbuf, i = 0; i <= len; i++)
|
||||
{
|
||||
if (postbuf[i] == '=')
|
||||
{
|
||||
postbuf[i] = 0;
|
||||
|
||||
for (field = 0; field < (n_fields * 2); field += 2)
|
||||
{
|
||||
if (!strcmp(p, fields[field]))
|
||||
{
|
||||
if (!strcmp(p, fields[field]))
|
||||
{
|
||||
fields[field + 1] = buf + i + 1;
|
||||
found++;
|
||||
}
|
||||
fields[field + 1] = postbuf + i + 1;
|
||||
found++;
|
||||
}
|
||||
}
|
||||
else if (buf[i] == '&' || buf[i] == '\0')
|
||||
{
|
||||
buf[i] = 0;
|
||||
}
|
||||
else if (postbuf[i] == '&' || postbuf[i] == '\0')
|
||||
{
|
||||
postbuf[i] = 0;
|
||||
|
||||
if (found >= n_fields)
|
||||
break;
|
||||
if (found >= n_fields)
|
||||
break;
|
||||
|
||||
p = buf + i + 1;
|
||||
}
|
||||
p = postbuf + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (field = 0; field < (n_fields * 2); field += 2)
|
||||
{
|
||||
if (!urldecode(fields[field + 1]))
|
||||
return false;
|
||||
{
|
||||
free(postbuf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (found >= n_fields);
|
||||
return postbuf;
|
||||
}
|
||||
|
||||
static char *
|
||||
|
@ -658,6 +690,14 @@ main_upload(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_charp(char **ptr)
|
||||
{
|
||||
free(*ptr);
|
||||
}
|
||||
|
||||
#define autochar __attribute__((__cleanup__(free_charp))) char
|
||||
|
||||
static int
|
||||
main_download(int argc, char **argv)
|
||||
{
|
||||
|
@ -668,7 +708,7 @@ main_download(int argc, char **argv)
|
|||
struct stat s;
|
||||
int rfd;
|
||||
|
||||
postdecode(fields, 4);
|
||||
autochar *post = postdecode(fields, 4);
|
||||
|
||||
if (!fields[1] || !session_access(fields[1], "cgi-io", "download", "read"))
|
||||
return failure(403, 0, "Download permission denied");
|
||||
|
@ -706,29 +746,39 @@ main_download(int argc, char **argv)
|
|||
if (fields[5])
|
||||
printf("Content-Disposition: attachment; filename=\"%s\"\r\n", fields[5]);
|
||||
|
||||
printf("Content-Length: %llu\r\n\r\n", size);
|
||||
fflush(stdout);
|
||||
if (size > 0) {
|
||||
printf("Content-Length: %llu\r\n\r\n", size);
|
||||
fflush(stdout);
|
||||
|
||||
while (size > 0) {
|
||||
len = sendfile(1, rfd, NULL, size);
|
||||
while (size > 0) {
|
||||
len = sendfile(1, rfd, NULL, size);
|
||||
|
||||
if (len == -1) {
|
||||
if (errno == ENOSYS || errno == EINVAL) {
|
||||
while ((len = read(rfd, buf, sizeof(buf))) > 0)
|
||||
fwrite(buf, len, 1, stdout);
|
||||
if (len == -1) {
|
||||
if (errno == ENOSYS || errno == EINVAL) {
|
||||
while ((len = read(rfd, buf, sizeof(buf))) > 0)
|
||||
fwrite(buf, len, 1, stdout);
|
||||
|
||||
fflush(stdout);
|
||||
break;
|
||||
fflush(stdout);
|
||||
break;
|
||||
}
|
||||
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
if (len <= 0)
|
||||
break;
|
||||
|
||||
size -= len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("\r\n");
|
||||
|
||||
if (len <= 0)
|
||||
break;
|
||||
while ((len = read(rfd, buf, sizeof(buf))) > 0)
|
||||
fwrite(buf, len, 1, stdout);
|
||||
|
||||
size -= len;
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
close(rfd);
|
||||
|
@ -749,7 +799,9 @@ main_backup(int argc, char **argv)
|
|||
char hostname[64] = { 0 };
|
||||
char *fields[] = { "sessionid", NULL };
|
||||
|
||||
if (!postdecode(fields, 1) || !session_access(fields[1], "cgi-io", "backup", "read"))
|
||||
autochar *post = postdecode(fields, 1);
|
||||
|
||||
if (!fields[1] || !session_access(fields[1], "cgi-io", "backup", "read"))
|
||||
return failure(403, 0, "Backup permission denied");
|
||||
|
||||
if (pipe(fds))
|
||||
|
@ -929,7 +981,7 @@ main_exec(int argc, char **argv)
|
|||
char *p, **args;
|
||||
pid_t pid;
|
||||
|
||||
postdecode(fields, 4);
|
||||
autochar *post = postdecode(fields, 4);
|
||||
|
||||
if (!fields[1] || !session_access(fields[1], "cgi-io", "exec", "read"))
|
||||
return failure(403, 0, "Exec permission denied");
|
||||
|
|
Loading…
Reference in a new issue