limit header size

This commit is contained in:
lxsang 2020-08-27 13:31:40 +02:00
parent 56806fb25b
commit 806a7ccc6a
3 changed files with 126 additions and 114 deletions

Binary file not shown.

View File

@ -18,26 +18,26 @@
#include "lib/ini.h" #include "lib/ini.h"
#include "lib/base64.h" #include "lib/base64.h"
#define HEADER_MAX_SIZE 8192
//define all basic mime here //define all basic mime here
static mime_t _mimes[] = { static mime_t _mimes[] = {
{"image/bmp","bmp"}, {"image/bmp", "bmp"},
{"image/jpeg","jpg,jpeg"}, {"image/jpeg", "jpg,jpeg"},
{"text/css","css"}, {"text/css", "css"},
{"text/markdown","md"}, {"text/markdown", "md"},
{"text/csv","csv"}, {"text/csv", "csv"},
{"application/pdf","pdf"}, {"application/pdf", "pdf"},
{"image/gif","gif"}, {"image/gif", "gif"},
{"text/html","html"}, {"text/html", "html"},
{"application/json","json"}, {"application/json", "json"},
{"application/javascript","js"}, {"application/javascript", "js"},
{"image/png","png"}, {"image/png", "png"},
{"text/plain","txt"}, {"text/plain", "txt"},
{"application/xhtml+xml","xhtml"}, {"application/xhtml+xml", "xhtml"},
{"application/xml","xml"}, {"application/xml", "xml"},
{"image/svg+xml","svg"}, {"image/svg+xml", "svg"},
{NULL,NULL} {NULL, NULL}};
};
static pthread_mutex_t server_mux = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t server_mux = PTHREAD_MUTEX_INITIALIZER;
config_t server_config; config_t server_config;
@ -56,24 +56,24 @@ void destroy_config()
free(server_config.db_path); free(server_config.db_path);
if (server_config.tmpdir) if (server_config.tmpdir)
free(server_config.tmpdir); free(server_config.tmpdir);
if(server_config.ssl_cipher) if (server_config.ssl_cipher)
free(server_config.ssl_cipher); free(server_config.ssl_cipher);
if(server_config.gzip_types) if (server_config.gzip_types)
list_free(&server_config.gzip_types); list_free(&server_config.gzip_types);
if(server_config.mimes) if (server_config.mimes)
freedict(server_config.mimes); freedict(server_config.mimes);
if(server_config.ports) if (server_config.ports)
{ {
chain_t it; chain_t it;
port_config_t* cnf; port_config_t *cnf;
for_each_assoc(it, server_config.ports) for_each_assoc(it, server_config.ports)
{ {
cnf = (port_config_t*)it->value; cnf = (port_config_t *)it->value;
if(cnf != NULL) if (cnf != NULL)
{ {
if(cnf->htdocs != NULL) if (cnf->htdocs != NULL)
free(cnf->htdocs); free(cnf->htdocs);
if(cnf->sock > 0) if (cnf->sock > 0)
{ {
close(cnf->sock); close(cnf->sock);
} }
@ -144,7 +144,7 @@ static int config_handler(void *conf, const char *section, const char *name,
} }
else if (MATCH("SERVER", "gzip_types")) else if (MATCH("SERVER", "gzip_types"))
{ {
pconfig->gzip_types = split(value,","); pconfig->gzip_types = split(value, ",");
} }
#endif #endif
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
@ -156,7 +156,7 @@ static int config_handler(void *conf, const char *section, const char *name,
{ {
pconfig->sslkey = strdup(value); pconfig->sslkey = strdup(value);
} }
else if(MATCH("SERVER","ssl.cipher")) else if (MATCH("SERVER", "ssl.cipher"))
{ {
pconfig->ssl_cipher = strdup(value); pconfig->ssl_cipher = strdup(value);
} }
@ -171,26 +171,26 @@ static int config_handler(void *conf, const char *section, const char *name,
// auto start plugin // auto start plugin
plugin_load((char *)value); plugin_load((char *)value);
} }
else if(strcmp(section, "MIMES") == 0) else if (strcmp(section, "MIMES") == 0)
{ {
dput(pconfig->mimes,name,strdup(value)); dput(pconfig->mimes, name, strdup(value));
} }
else if( regex_match("PORT:\\s*([0-9]+)", section, 2, port_matches) ) else if (regex_match("PORT:\\s*([0-9]+)", section, 2, port_matches))
{ {
char buf[20]; char buf[20];
memset(buf, '\0', sizeof(buf)); memset(buf, '\0', sizeof(buf));
memcpy(buf, section + port_matches[1].rm_so, port_matches[1].rm_eo - port_matches[1].rm_so); memcpy(buf, section + port_matches[1].rm_so, port_matches[1].rm_eo - port_matches[1].rm_so);
port_config_t* p = dvalue(pconfig->ports,buf); port_config_t *p = dvalue(pconfig->ports, buf);
if(!p) if (!p)
{ {
p = (port_config_t*) malloc( sizeof(port_config_t)); p = (port_config_t *)malloc(sizeof(port_config_t));
p->htdocs = NULL; p->htdocs = NULL;
p->sock = -1; p->sock = -1;
p->rules = dict(); p->rules = dict();
dput(pconfig->ports,buf, p); dput(pconfig->ports, buf, p);
p->port = atoi(buf); p->port = atoi(buf);
} }
if(strcmp(name, "htdocs") == 0) if (strcmp(name, "htdocs") == 0)
{ {
p->htdocs = strdup(value); p->htdocs = strdup(value);
if (stat(p->htdocs, &st) == -1) if (stat(p->htdocs, &st) == -1)
@ -198,10 +198,10 @@ static int config_handler(void *conf, const char *section, const char *name,
mkdirp(p->htdocs, 0755); mkdirp(p->htdocs, 0755);
} }
} }
else if(strcmp(name, "ssl.enable") == 0) else if (strcmp(name, "ssl.enable") == 0)
{ {
p->usessl = atoi(value); p->usessl = atoi(value);
if(p->usessl) if (p->usessl)
pconfig->enable_ssl = 1; pconfig->enable_ssl = 1;
} }
else else
@ -239,9 +239,9 @@ void load_config(const char *file)
server_config.gzip_enable = 0; server_config.gzip_enable = 0;
server_config.gzip_types = NULL; server_config.gzip_types = NULL;
// put it default mimes // put it default mimes
for(int i = 0; _mimes[i].type != NULL; i++) for (int i = 0; _mimes[i].type != NULL; i++)
{ {
dput(server_config.mimes,_mimes[i].type, strdup(_mimes[i].ext)); dput(server_config.mimes, _mimes[i].type, strdup(_mimes[i].ext));
} }
if (ini_parse(file, config_handler, &server_config) < 0) if (ini_parse(file, config_handler, &server_config) < 0)
{ {
@ -336,7 +336,7 @@ void *accept_request(void *data)
//server_config.connection++; //server_config.connection++;
read_buf(rq->client, buf, sizeof(buf)); read_buf(rq->client, buf, sizeof(buf));
line = buf; line = buf;
LOG("Request (%d): %s", rq->client->sock,line); LOG("Request (%d): %s", rq->client->sock, line);
// get the method string // get the method string
token = strsep(&line, " "); token = strsep(&line, " ");
if (!line) if (!line)
@ -414,7 +414,7 @@ void *resolve_request(void *data)
{ {
newurl = __s("%s/index.%s", url, it->key); newurl = __s("%s/index.%s", url, it->key);
memset(path, 0, sizeof(path)); memset(path, 0, sizeof(path));
htdocs(rq,path); htdocs(rq, path);
strcat(path, newurl); strcat(path, newurl);
if (stat(path, &st) != 0) if (stat(path, &st) != 0)
{ {
@ -471,20 +471,20 @@ void *resolve_request(void *data)
task->type = HEAVY; task->type = HEAVY;
// discard all request data // discard all request data
dictionary_t headers = (dictionary_t) dvalue(rq->request, "REQUEST_HEADER"); dictionary_t headers = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER");
if(headers) if (headers)
{ {
char * sclen = (char *)dvalue(headers, "Content-Length"); char *sclen = (char *)dvalue(headers, "Content-Length");
unsigned clen = 0; unsigned clen = 0;
unsigned read = 0; unsigned read = 0;
int count; int count;
if(sclen) if (sclen)
{ {
clen = atoi(sclen); clen = atoi(sclen);
while (read < clen) while (read < clen)
{ {
count = antd_recv(rq->client, path, sizeof(path) < clen ? sizeof(path): clen ); count = antd_recv(rq->client, path, sizeof(path) < clen ? sizeof(path) : clen);
if(count <= 0) if (count <= 0)
break; break;
read += count; read += count;
} }
@ -589,7 +589,7 @@ void *serve_file(void *data)
struct stat st; struct stat st;
int s = stat(path, &st); int s = stat(path, &st);
if(s == -1) if (s == -1)
{ {
antd_error(rq->client, 404, "File not found"); antd_error(rq->client, 404, "File not found");
} }
@ -597,33 +597,33 @@ void *serve_file(void *data)
{ {
// check if it is modified // check if it is modified
dictionary_t header = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER"); dictionary_t header = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER");
char * last_modif_since = (char*)dvalue(header, "If-Modified-Since"); char *last_modif_since = (char *)dvalue(header, "If-Modified-Since");
time_t t = st.st_ctime; time_t t = st.st_ctime;
struct tm tm; struct tm tm;
if(last_modif_since) if (last_modif_since)
{ {
strptime(last_modif_since, "%a, %d %b %Y %H:%M:%S GMT", &tm); strptime(last_modif_since, "%a, %d %b %Y %H:%M:%S GMT", &tm);
t = timegm(&tm); t = timegm(&tm);
//t = mktime(localtime(&t)); //t = mktime(localtime(&t));
} }
if(last_modif_since && st.st_ctime == t) if (last_modif_since && st.st_ctime == t)
{ {
// return the not changed // return the not changed
antd_error(rq->client,304, ""); antd_error(rq->client, 304, "");
} }
else else
{ {
int size = (int)st.st_size; int size = (int)st.st_size;
char ibuf[64]; char ibuf[64];
snprintf (ibuf, sizeof(ibuf), "%d",size); snprintf(ibuf, sizeof(ibuf), "%d", size);
antd_response_header_t rhd; antd_response_header_t rhd;
rhd.cookie = NULL; rhd.cookie = NULL;
rhd.status = 200; rhd.status = 200;
rhd.header = dict(); rhd.header = dict();
dput(rhd.header, "Content-Type", strdup(mime_type)); dput(rhd.header, "Content-Type", strdup(mime_type));
#ifdef USE_ZLIB #ifdef USE_ZLIB
if(!compressable(mime_type) || rq->client->z_level == ANTD_CNONE) if (!compressable(mime_type) || rq->client->z_level == ANTD_CNONE)
#endif #endif
dput(rhd.header, "Content-Length", strdup(ibuf)); dput(rhd.header, "Content-Length", strdup(ibuf));
gmtime_r(&st.st_ctime, &tm); gmtime_r(&st.st_ctime, &tm);
@ -691,12 +691,12 @@ char *apply_rules(dictionary_t rules, const char *host, char *url)
} }
//char* oldurl = strdup(url); //char* oldurl = strdup(url);
chain_t it; chain_t it;
char* k; char *k;
char* v; char *v;
for_each_assoc(it, rules) for_each_assoc(it, rules)
{ {
k = it->key; k = it->key;
v = (char*)it->value; v = (char *)it->value;
// 1 group // 1 group
if (rule_check(k, v, host, url, query_string, url)) if (rule_check(k, v, host, url, query_string, url))
{ {
@ -727,15 +727,19 @@ void *decode_request_header(void *data)
char *query = NULL; char *query = NULL;
char *host = NULL; char *host = NULL;
char buf[2 * BUFFLEN]; char buf[2 * BUFFLEN];
int header_size = 0;
int ret;
char *url = (char *)dvalue(rq->request, "REQUEST_QUERY"); char *url = (char *)dvalue(rq->request, "REQUEST_QUERY");
dictionary_t xheader = dvalue(rq->request, "REQUEST_HEADER"); dictionary_t xheader = dvalue(rq->request, "REQUEST_HEADER");
dictionary_t request = dvalue(rq->request, "REQUEST_DATA"); dictionary_t request = dvalue(rq->request, "REQUEST_DATA");
char* port_s = (char*) dvalue(xheader, "SERVER_PORT"); char *port_s = (char *)dvalue(xheader, "SERVER_PORT");
port_config_t* pcnf = (port_config_t*)dvalue(server_config.ports, port_s); port_config_t *pcnf = (port_config_t *)dvalue(server_config.ports, port_s);
// first real all header // first real all header
// this for check if web socket is enabled // this for check if web socket is enabled
while ((read_buf(rq->client, buf, sizeof(buf))) && strcmp("\r\n", buf))
while ((( ret = read_buf(rq->client, buf, sizeof(buf))) > 0) && strcmp("\r\n", buf))
{ {
header_size += ret;
line = buf; line = buf;
trim(line, '\n'); trim(line, '\n');
trim(line, '\r'); trim(line, '\r');
@ -749,7 +753,7 @@ void *decode_request_header(void *data)
} }
if (token != NULL && strcasecmp(token, "Cookie") == 0) if (token != NULL && strcasecmp(token, "Cookie") == 0)
{ {
if(!cookie) if (!cookie)
{ {
cookie = dict(); cookie = dict();
} }
@ -759,32 +763,37 @@ void *decode_request_header(void *data)
{ {
host = strdup(line); host = strdup(line);
} }
if(header_size > HEADER_MAX_SIZE)
{
antd_error(rq->client, 413, "Payload Too Large");
return antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
}
} }
// check for content length size // check for content length size
line = (char *)dvalue(xheader, "Content-Length"); line = (char *)dvalue(xheader, "Content-Length");
if (line) if (line)
{ {
int clen = atoi(line); int clen = atoi(line);
if(clen > server_config.max_upload_size) if (clen > server_config.max_upload_size)
{ {
antd_error(rq->client, 413, "Request body data is too large"); antd_error(rq->client, 413, "Request body data is too large");
// dirty fix, wait for message to be sent // dirty fix, wait for message to be sent
// 100 ms sleep // 100 ms sleep
usleep(100000); usleep(100000);
return antd_create_task(NULL, (void *)rq, NULL,rq->client->last_io); return antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
} }
} }
#ifdef USE_ZLIB #ifdef USE_ZLIB
// check for gzip // check for gzip
line = (char *)dvalue(xheader, "Accept-Encoding"); line = (char *)dvalue(xheader, "Accept-Encoding");
if(line) if (line)
{ {
if(regex_match("gzip",line,0, NULL)) if (regex_match("gzip", line, 0, NULL))
{ {
rq->client->z_level = ANTD_CGZ; rq->client->z_level = ANTD_CGZ;
} }
else if(regex_match("deflate", line, 0, NULL)) else if (regex_match("deflate", line, 0, NULL))
{ {
rq->client->z_level = ANTD_CDEFL; rq->client->z_level = ANTD_CDEFL;
} }
@ -815,7 +824,7 @@ void *decode_request_header(void *data)
if (host) if (host)
free(host); free(host);
// header ok, now checkmethod // header ok, now checkmethod
antd_task_t *task = antd_create_task(decode_request, (void *)rq, NULL,rq->client->last_io); antd_task_t *task = antd_create_task(decode_request, (void *)rq, NULL, rq->client->last_io);
return task; return task;
} }
@ -857,7 +866,7 @@ void *decode_request(void *data)
} }
else else
{ {
antd_error(rq->client,501, "Request Method Not Implemented"); antd_error(rq->client, 501, "Request Method Not Implemented");
return task; return task;
} }
} }
@ -905,7 +914,7 @@ void *decode_post_request(void *data)
key++; key++;
else else
key = ctype; key = ctype;
if(pquery) if (pquery)
{ {
dput(request, key, strdup(pquery)); dput(request, key, strdup(pquery));
free(pquery); free(pquery);
@ -986,7 +995,7 @@ void *decode_multi_part_request(void *data, const char *ctype)
{ {
char *boundary; char *boundary;
char line[BUFFLEN]; char line[BUFFLEN];
char *str_copy = (char*)ctype; char *str_copy = (char *)ctype;
int len; int len;
antd_request_t *rq = (antd_request_t *)data; antd_request_t *rq = (antd_request_t *)data;
antd_task_t *task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io); antd_task_t *task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
@ -999,7 +1008,8 @@ void *decode_multi_part_request(void *data, const char *ctype)
trim(boundary, ' '); trim(boundary, ' ');
dput(rq->request, "MULTI_PART_BOUNDARY", strdup(boundary)); dput(rq->request, "MULTI_PART_BOUNDARY", strdup(boundary));
//find first boundary //find first boundary
while (( (len = read_buf(rq->client, line, sizeof(line))) > 0 ) && !strstr(line, boundary)); while (((len = read_buf(rq->client, line, sizeof(line))) > 0) && !strstr(line, boundary))
;
if (len > 0) if (len > 0)
{ {
task->handle = decode_multi_part_request_data; task->handle = decode_multi_part_request_data;
@ -1026,7 +1036,9 @@ void *decode_multi_part_request_data(void *data)
char *boundary = (char *)dvalue(rq->request, "MULTI_PART_BOUNDARY"); char *boundary = (char *)dvalue(rq->request, "MULTI_PART_BOUNDARY");
dictionary_t dic = (dictionary_t)dvalue(rq->request, "REQUEST_DATA"); dictionary_t dic = (dictionary_t)dvalue(rq->request, "REQUEST_DATA");
// search for content disposition: // search for content disposition:
while ( ( (len = read_buf(rq->client, buf, sizeof(buf))) > 0 ) && !strstr(buf, "Content-Disposition:"));; while (((len = read_buf(rq->client, buf, sizeof(buf))) > 0) && !strstr(buf, "Content-Disposition:"))
;
;
if (len <= 0 || !strstr(buf, "Content-Disposition:")) if (len <= 0 || !strstr(buf, "Content-Disposition:"))
{ {
@ -1064,7 +1076,9 @@ void *decode_multi_part_request_data(void *data)
if (part_name != NULL) if (part_name != NULL)
{ {
// go to the beginning of data bock // go to the beginning of data bock
while ((len = read_buf(rq->client, buf, sizeof(buf))) > 0 && strcmp(buf, "\r\n") != 0);; while ((len = read_buf(rq->client, buf, sizeof(buf))) > 0 && strcmp(buf, "\r\n") != 0)
;
;
if (part_file == NULL) if (part_file == NULL)
{ {
@ -1075,7 +1089,7 @@ void *decode_multi_part_request_data(void *data)
* Need an efficient way to handle this * Need an efficient way to handle this
*/ */
len = read_buf(rq->client, buf, sizeof(buf)); len = read_buf(rq->client, buf, sizeof(buf));
if(len > 0) if (len > 0)
{ {
line = buf; line = buf;
trim(line, '\n'); trim(line, '\n');
@ -1088,7 +1102,6 @@ void *decode_multi_part_request_data(void *data)
{ {
line = buf; line = buf;
} }
} }
else else
{ {
@ -1288,29 +1301,28 @@ dictionary_t mimes_list()
return server_config.mimes; return server_config.mimes;
} }
void dbdir(char *dest)
void dbdir(char* dest)
{ {
strncpy(dest,server_config.db_path, 512); strncpy(dest, server_config.db_path, 512);
} }
void tmpdir(char* dest) void tmpdir(char *dest)
{ {
strncpy(dest, server_config.tmpdir, 512); strncpy(dest, server_config.tmpdir, 512);
} }
void plugindir(char* dest) void plugindir(char *dest)
{ {
strncpy(dest, server_config.plugins_dir, 512); strncpy(dest, server_config.plugins_dir, 512);
} }
#ifdef USE_ZLIB #ifdef USE_ZLIB
int compressable(char* ctype) int compressable(char *ctype)
{ {
if(!server_config.gzip_enable || server_config.gzip_types == NULL) if (!server_config.gzip_enable || server_config.gzip_types == NULL)
return 0; return 0;
item_t it; item_t it;
list_for_each(it, server_config.gzip_types) list_for_each(it, server_config.gzip_types)
{ {
if(it->type == LIST_TYPE_POINTER && it->value.ptr && regex_match((const char*)it->value.ptr, ctype, 0, NULL)) if (it->type == LIST_TYPE_POINTER && it->value.ptr && regex_match((const char *)it->value.ptr, ctype, 0, NULL))
{ {
return 1; return 1;
} }

View File

@ -12,29 +12,29 @@
#define CONFIG_FILE "antd-config.ini" #define CONFIG_FILE "antd-config.ini"
#endif #endif
config_t* config(); config_t *config();
void destroy_config(); void destroy_config();
void load_config(const char* file); void load_config(const char *file);
void* accept_request(void*); void *accept_request(void *);
void* finish_request(void*); void *finish_request(void *);
void cat(void*, FILE *); void cat(void *, FILE *);
void cannot_execute(void*); void cannot_execute(void *);
//int get_line(int, char *, int); //int get_line(int, char *, int);
void* serve_file(void*); void *serve_file(void *);
int startup(unsigned *); int startup(unsigned *);
int rule_check(const char*, const char*, const char* , const char* , const char* , char*); int rule_check(const char *, const char *, const char *, const char *, const char *, char *);
void ws_confirm_request(void*, const char*); void ws_confirm_request(void *, const char *);
char* post_url_decode(void* client,int len); char *post_url_decode(void *client, int len);
void decode_url_request(const char* query, dictionary_t); void decode_url_request(const char *query, dictionary_t);
void* decode_request_header(void* data); void *decode_request_header(void *data);
void* decode_request(void* data); void *decode_request(void *data);
void* decode_post_request(void* data); void *decode_post_request(void *data);
void* resolve_request(void* data); void *resolve_request(void *data);
void* decode_multi_part_request(void*,const char*); void *decode_multi_part_request(void *, const char *);
void* decode_multi_part_request_data(void* data); void *decode_multi_part_request_data(void *data);
void decode_cookie(const char*, dictionary_t d); void decode_cookie(const char *, dictionary_t d);
char* post_data_decode(void*,int); char *post_data_decode(void *, int);
void set_nonblock(int); void set_nonblock(int);
void* execute_plugin(void* data, const char *path); void *execute_plugin(void *data, const char *path);
#endif #endif