From 7708b5f493bf3057af331624d29664ad17a87dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Sat, 18 Sep 2021 23:10:23 +0200 Subject: Make nextparam work with non-NUL-terminated data At least on POST. --- README | 8 ++++---- cforum.c | 2 +- ctl.c | 37 ++++++++++++++++++------------------- query.c | 22 +++++++++++++++------- query.h | 3 ++- site.h | 2 +- 6 files changed, 41 insertions(+), 33 deletions(-) diff --git a/README b/README index 8030d7f..9472b04 100644 --- a/README +++ b/README @@ -9,14 +9,14 @@ It is also rather small: wc -l *.c *.h */*.t */*.lex 101 cforum.c - 223 ctl.c + 222 ctl.c 268 db.c 10 err.c - 113 query.c + 121 query.c 6 ctl.h 40 db.h 0 err.h - 14 query.h + 15 query.h 21 site.h 3 t/err.t 1 t/foot.t @@ -26,4 +26,4 @@ It is also rather small: 28 t/post.t 12 t/user.t 95 mktpl/mktpl.lex - 1012 total + 1020 total diff --git a/cforum.c b/cforum.c index feee431..999ae78 100644 --- a/cforum.c +++ b/cforum.c @@ -73,7 +73,7 @@ main(int argc, char *argv[]) /* Parse query string. */ new = NULL; attid = postid = userid = 0; - while(p = nextparam(GET, 128)){ + while(p = nextparam(GET, NULL, 128)){ v = split(p); if(!attid && strcmp(p, "att") == 0) attid = atoi(v); else if(!postid && strcmp(p, "post") == 0) postid = atoi(v); diff --git a/ctl.c b/ctl.c index e4b25a7..712b31a 100644 --- a/ctl.c +++ b/ctl.c @@ -37,12 +37,9 @@ newpost() void newuser() { - char *confirm, *hlite, *msg, *name, *full, *p, *pass, *v; + char *confirm, *hlite, msg[128], *name, *full, *p, *pass, *v; char title[] = "New User"; - if(!(msg = malloc(128))) - err(1, "malloc"); - *msg = 0; confirm = hlite = name = full = pass = NULL; @@ -52,7 +49,15 @@ newuser() return; } - while(p = nextparam(POST, MAXUSERPARAM)){ + if(query.length > MAXUSERDATA){ + snprintf(msg, 128, "Input exceeded server limitations"); + printf("Status: 431 Request Header Fields Too Large\n"); + printf("Content-Type: text/html\n\n"); + #include "t/newuser.tc" + return; + } + + while(p = nextparam(POST, NULL, MAXUSERDATA)){ if(!(v = split(p))) continue; if(!confirm && strcmp(p, "confirm") == 0) @@ -65,20 +70,6 @@ newuser() pass = strdup(v); else continue; - - if(TRUNCATED(p)){ - hlite = strdup(p); - snprintf(msg, 128, - "Input length exceeds server limitations"); - goto err; - } - } - - /* Ensure all required fields are there. */ - if(!name || !*name || !pass || !*pass){ - hlite = (!name || !*name)? strdup("name"): strdup("pass"); - snprintf(msg, 128, "Required field missing"); - goto err; } /* Decode URL-encoded fields. */ @@ -103,6 +94,13 @@ newuser() goto err; } + /* Ensure all required fields are there. */ + if(!name || !*name || !pass || !*pass){ + hlite = (!name || !*name)? strdup("name"): strdup("pass"); + snprintf(msg, 128, "Required field missing"); + goto err; + } + if(pass && confirm && strcmp(pass, confirm) != 0){ snprintf(msg, 128, "Passwords do not match"); goto err; @@ -112,6 +110,7 @@ newuser() printf("You are valid\n"); return; err: + printf("Status: 400 Bad Request\n"); printf("Content-Type: text/html\n\n"); #include "t/newuser.tc" return; diff --git a/query.c b/query.c index 370fa54..27770e4 100644 --- a/query.c +++ b/query.c @@ -5,14 +5,19 @@ #include "query.h" /* - * Return an allocated string containing the next query string parameter - * ("key=value"). The string is truncated to max characters (but is always - * NUL-terminated). If truncation occurred, the -1th character of the string - * is set to 1. + * Return an allocated string containing the next parameter ("key=value"). + * The method argument decides which data (GET or POST) to read from. + * + * If len is NULL, the string will be NUL-terminated; if len is non-NULL, + * the string will not be NUL-terminated, and len will be pointed to the + * length of the string. + * + * The string is truncated to max characters. If truncation occurred, the + * -1th character of the string is set to 1. */ char * -nextparam(enum method method, int max) -{ +nextparam(enum method method, int *len, int max) +{ char *buf; int i, sz; static int j = 0; @@ -73,7 +78,8 @@ rest: err(1, "realloc"); } } - buf[i] = 0; + if(len) *len = i; + else buf[i] = 0; return buf; } @@ -88,6 +94,8 @@ setquery() exit(1); } query.method = strcmp(getenv("REQUEST_METHOD"), "POST")? GET: POST; + if(query.method == POST) + query.length = atoi(getenv("CONTENT_LENGTH")); } /* diff --git a/query.h b/query.h index a5cb168..6a4c1cc 100644 --- a/query.h +++ b/query.h @@ -2,6 +2,7 @@ struct query{ int method; + int length; /* Content length. */ char *string; } query; @@ -10,6 +11,6 @@ enum method{ POST }; -char *nextparam(enum method, int); +char *nextparam(enum method, int *, int); void setquery(void); char *split(char *); \ No newline at end of file diff --git a/site.h b/site.h index 4e13319..800cdea 100644 --- a/site.h +++ b/site.h @@ -13,7 +13,7 @@ #define MAXUSERPARAM 512 /* Maximum size of user information, incl. NUL. */ -#define MAXUSERNAME 80 +#define MAXUSERNAME 40 #define MAXUSERFULL 128 #define MAXUSERPASS 128 -- cgit v1.2.3