diff --git a/Makefile b/Makefile index 00d4005..7659390 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,11 @@ packages: compile: @mkdir -p bin - gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb + gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb -Wall compile-debian: @mkdir -p bin - gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb \ + gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb -Wall \ -D MAGIC_FILE="\"/usr/share/file/magic.mgc\"" \ -D PHP_FPM_SOCKET="\"/var/run/php/php7.3-fpm.sock\"" diff --git a/src/cache.c b/src/cache.c index c5dfce6..350757e 100644 --- a/src/cache.c +++ b/src/cache.c @@ -69,6 +69,7 @@ int cache_process() { SHA_CTX ctx; unsigned char hash[SHA_DIGEST_LENGTH]; int cache_changed = 0; + int p_len; while (cache_continue) { for (int i = 0; i < FILE_CACHE_SIZE; i++) { if (cache[i].filename[0] != 0 && cache[i].meta.etag[0] == 0 && !cache[i].is_updating) { @@ -97,12 +98,19 @@ int cache_process() { buf[j] = ch; } buf[strlen(rel_path)] = 0; - sprintf(filename_comp, "%.*s/.necronda-server/cache/%s.z", cache[i].webroot_len, cache[i].filename, buf); + p_len = snprintf(filename_comp, sizeof(filename_comp), "%.*s/.necronda-server/cache/%s.z", + cache[i].webroot_len, cache[i].filename, buf); + if (p_len < 0 || p_len >= sizeof(filename_comp)) { + fprintf(stderr, ERR_STR "Unable to open cached file: " + "File name for compressed file too long" CLR_STR "\n"); + goto comp_err; + } fprintf(stdout, "[cache] Compressing file %s\n", cache[i].filename); comp_file = fopen(filename_comp, "wb"); if (comp_file == NULL) { - compress = 0; fprintf(stderr, ERR_STR "Unable to open cached file: %s" CLR_STR "\n", strerror(errno)); + comp_err: + compress = 0; } else { strm.zalloc = Z_NULL; strm.zfree = Z_NULL; diff --git a/src/client.c b/src/client.c index 6f65861..6288d2e 100644 --- a/src/client.c +++ b/src/client.c @@ -42,6 +42,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int int accept_if_modified_since = 0; int use_fastcgi = 0; int use_rev_proxy = 0; + int p_len; fastcgi_conn php_fpm = {.socket = 0, .req_id = 0}; http_status custom_status; @@ -139,6 +140,8 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int } else if (ret == 3) { sprintf(err_msg, "The specified webroot directory does not exist."); res.status = http_get_status(404); + } else { + res.status = http_get_status(500); } goto respond; } @@ -152,7 +155,12 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int size = sizeof(buf0); url_encode(uri.uri, buf0, &size); if (change_proto) { - sprintf(buf1, "https://%s%s", host, buf0); + p_len = snprintf(buf1, sizeof(buf1), "https://%s%s", host, buf0); + if (p_len < 0 || p_len >= sizeof(buf1)) { + res.status = http_get_status(500); + print(ERR_STR "Header field 'Location' too long" CLR_STR); + goto respond; + } http_add_header_field(&res.hdr, "Location", buf1); } else { http_add_header_field(&res.hdr, "Location", buf0); diff --git a/src/config.c b/src/config.c index 5b52e94..e21106f 100644 --- a/src/config.c +++ b/src/config.c @@ -69,8 +69,7 @@ int config_load(const char *filename) { int i = 0; int mode = 0; char *ptr = NULL; - char host[256], *source, *target; - host[0] = 0; + char *source, *target; while ((ptr = strtok(ptr == NULL ? conf : NULL, "\n")) != NULL) { char *comment = strchr(ptr, '#'); if (comment != NULL) comment[0] = 0; diff --git a/src/debug.c b/src/debug.c deleted file mode 100644 index 75621d0..0000000 --- a/src/debug.c +++ /dev/null @@ -1,17 +0,0 @@ -// -// Created by lorenz on 17.01.21. -// - -#include "fastcgi.c" -#include "http.c" -#include "sock.c" - -const char *msg = "PHP message: PHP Notice: Undefined index: Verifiedd in /srv/necronda/www.necronda.net/admin/users.php on line 58PHP message: PHP Notice: Undefined index: Verifiedd in /srv/necronda/www.necronda.net/admin/users.php on line 58PHP message: PHP Notice: Undefined index: Verifiedd in /srv/necronda/www.necronda.net/admin/users.php on line 58PHP message: PHP Notice: Undefined index: Verifiedd in /srv/necronda/www.necronda.net/admin/users.php on line 58PHP message: PHP Notice: Undefined index: Verifiedd in /srv/necronda/www.necronda.net/admin/users.php on line 58PHP message: PHP Notice: Undefined index: Verifiedd in /srv/necronda/www.necronda.net/admin/users.php on line 58PHP message: PHP Notice: Undefined index: Verifiedd in /srv/necronda/www.necronda.net/admin/users.php on line 58PHP message: PHP Notice: Undefined index: Verifiedd in /srv/necronda/www.necronda.net/admin/users.php on line 58"; - -int main() { - char err[256]; - int ret = fastcgi_php_error(msg, strlen(msg), err); - printf("%i\n", ret); - return 0; -} - diff --git a/src/fastcgi.c b/src/fastcgi.c index 40b54fa..67d10d4 100644 --- a/src/fastcgi.c +++ b/src/fastcgi.c @@ -130,7 +130,7 @@ int fastcgi_init(fastcgi_conn *conn, unsigned int client_num, unsigned int req_n if (uri->pathinfo != NULL && strlen(uri->pathinfo) > 0) { sprintf(buf0, "/%s", uri->pathinfo); } else { - sprintf(buf0, ""); + buf0[0] = 0; } param_ptr = fastcgi_add_param(param_ptr, "PATH_INFO", buf0); diff --git a/src/http.c b/src/http.c index df6b4fa..e4cb742 100644 --- a/src/http.c +++ b/src/http.c @@ -49,9 +49,9 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) } long len = pos1 - buf; - hdr->fields[hdr->field_num][0] = malloc(len + 1); - sprintf(hdr->fields[hdr->field_num][0], "%.*s", (int) len, buf); - http_to_camel_case(hdr->fields[hdr->field_num][0], HTTP_CAMEL); + hdr->fields[(int) hdr->field_num][0] = malloc(len + 1); + sprintf(hdr->fields[(int) hdr->field_num][0], "%.*s", (int) len, buf); + http_to_camel_case(hdr->fields[(int) hdr->field_num][0], HTTP_CAMEL); pos1++; pos2 = (char *) end_ptr - 1; @@ -60,11 +60,11 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) len = pos2 - pos1 + 1; if (len <= 0) { - hdr->fields[hdr->field_num][1] = malloc(1); - hdr->fields[hdr->field_num][1][0] = 0; + hdr->fields[(int) hdr->field_num][1] = malloc(1); + hdr->fields[(int) hdr->field_num][1][0] = 0; } else { - hdr->fields[hdr->field_num][1] = malloc(len + 1); - sprintf(hdr->fields[hdr->field_num][1], "%.*s", (int) len, pos1); + hdr->fields[(int) hdr->field_num][1] = malloc(len + 1); + sprintf(hdr->fields[(int) hdr->field_num][1], "%.*s", (int) len, pos1); } hdr->field_num++; return 0; @@ -184,8 +184,8 @@ void http_add_header_field(http_hdr *hdr, const char *field_name, const char *fi strcpy(_field_name, field_name); strcpy(_field_value, field_value); http_to_camel_case(_field_name, HTTP_PRESERVE); - hdr->fields[hdr->field_num][0] = _field_name; - hdr->fields[hdr->field_num][1] = _field_value; + hdr->fields[(int) hdr->field_num][0] = _field_name; + hdr->fields[(int) hdr->field_num][1] = _field_value; hdr->field_num++; } @@ -266,7 +266,7 @@ const char *http_get_status_color(http_status *status) { unsigned short code = status->code; if (code >= 100 && code < 200) { return HTTP_1XX_STR; - } else if (code >= 200 && code < 300 || code == 304) { + } else if ((code >= 200 && code < 300) || code == 304) { return HTTP_2XX_STR; } else if (code >= 300 && code < 400) { return HTTP_3XX_STR; diff --git a/src/rev_proxy.c b/src/rev_proxy.c index 976a674..8443cfd 100644 --- a/src/rev_proxy.c +++ b/src/rev_proxy.c @@ -14,6 +14,7 @@ struct timeval server_timeout = {.tv_sec = SERVER_TIMEOUT, .tv_usec = 0}; int rev_proxy_request_header(http_req *req, int enc) { char buf1[256]; char buf2[256]; + int p_len; http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL); http_add_header_field(&req->hdr, "Connection", "keep-alive"); @@ -22,7 +23,11 @@ int rev_proxy_request_header(http_req *req, int enc) { if (via == NULL) { http_add_header_field(&req->hdr, "Via", buf1); } else { - sprintf(buf2, "%s, %s", via, buf1); + p_len = snprintf(buf2, sizeof(buf2), "%s, %s", via, buf1); + if (p_len < 0 || p_len >= sizeof(buf2)) { + print(ERR_STR "Header field 'Via' too long" CLR_STR); + return -1; + } http_remove_header_field(&req->hdr, "Via", HTTP_REMOVE_ALL); http_add_header_field(&req->hdr, "Via", buf2); } @@ -32,15 +37,23 @@ int rev_proxy_request_header(http_req *req, int enc) { int client_ipv6 = strchr(client_addr_str, ':') != NULL; int server_ipv6 = strchr(server_addr_str, ':') != NULL; - sprintf(buf1, "by=%s%s%s;for=%s%s%s;host=%s;proto=%s", - server_ipv6 ? "\"[" : "", server_addr_str, server_ipv6 ? "]\"" : "", - client_ipv6 ? "\"[" : "", client_addr_str, client_ipv6 ? "]\"" : "", - host, enc ? "https" : "http"); + p_len = snprintf(buf1, sizeof(buf1), "by=%s%s%s;for=%s%s%s;host=%s;proto=%s", + server_ipv6 ? "\"[" : "", server_addr_str, server_ipv6 ? "]\"" : "", + client_ipv6 ? "\"[" : "", client_addr_str, client_ipv6 ? "]\"" : "", + host, enc ? "https" : "http"); + if (p_len < 0 || p_len >= sizeof(buf1)) { + print(ERR_STR "Appended part of header field 'Forwarded' too long" CLR_STR); + return -1; + } if (forwarded == NULL) { // TODO escape IPv6 addresses http_add_header_field(&req->hdr, "Forwarded", buf1); } else { - sprintf(buf2, "%s, %s", forwarded, buf1); + p_len = snprintf(buf2, sizeof(buf2), "%s, %s", forwarded, buf1); + if (p_len < 0 || p_len >= sizeof(buf2)) { + print(ERR_STR "Header field 'Forwarded' too long" CLR_STR); + return -1; + } http_remove_header_field(&req->hdr, "Forwarded", HTTP_REMOVE_ALL); http_add_header_field(&req->hdr, "Forwarded", buf2); } @@ -102,13 +115,22 @@ int rev_proxy_request_header(http_req *req, int enc) { int rev_proxy_response_header(http_req *req, http_res *res) { char buf1[256]; char buf2[256]; + int p_len; char *via = http_get_header_field(&res->hdr, "Via"); - sprintf(buf1, "HTTP/%s %s", req->version, DEFAULT_HOST); + p_len = snprintf(buf1, sizeof(buf1), "HTTP/%s %s", req->version, DEFAULT_HOST); + if (p_len < 0 || p_len >= sizeof(buf1)) { + print(ERR_STR "Appended part of header field 'Via' too long" CLR_STR); + return -1; + } if (via == NULL) { http_add_header_field(&res->hdr, "Via", buf1); } else { - sprintf(buf2, "%s, %s", via, buf1); + p_len = snprintf(buf2, sizeof(buf2), "%s, %s", via, buf1); + if (p_len < 0 || p_len >= sizeof(buf2)) { + print(ERR_STR "Header field 'Via' too long" CLR_STR); + return -1; + } http_remove_header_field(&res->hdr, "Via", HTTP_REMOVE_ALL); http_add_header_field(&res->hdr, "Via", buf2); } @@ -201,7 +223,11 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client print(BLUE_STR "Established new connection with " BLD_STR "[%s]:%i" CLR_STR, buffer, conf->rev_proxy.port); rev_proxy: - rev_proxy_request_header(req, (int) client->enc); + ret = rev_proxy_request_header(req, (int) client->enc); + if (ret != 0) { + res->status = http_get_status(500); + return -1; + } ret = http_send_request(&rev_proxy, req); if (ret < 0) { @@ -323,7 +349,11 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client } sock_recv(&rev_proxy, buffer, header_len, 0); - rev_proxy_response_header(req, res); + ret = rev_proxy_response_header(req, res); + if (ret != 0) { + res->status = http_get_status(500); + return -1; + } return 0; diff --git a/src/uri.c b/src/uri.c index 8f89b4c..3d7bfad 100644 --- a/src/uri.c +++ b/src/uri.c @@ -28,6 +28,7 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo char buf1[1024]; char buf2[1024]; char buf3[1024]; + int p_len; uri->webroot = NULL; uri->req_path = NULL; uri->path = NULL; @@ -96,8 +97,10 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo while (1) { sprintf(buf0, "%s%s", uri->webroot, uri->path); - sprintf(buf1, "%s.php", buf0); - sprintf(buf2, "%s.html", buf0); + p_len = snprintf(buf1, sizeof(buf1), "%s.php", buf0); + if (p_len < 0 || p_len >= sizeof(buf1)) return -1; + p_len = snprintf(buf2, sizeof(buf2), "%s.html", buf0); + if (p_len < 0 || p_len >= sizeof(buf2)) return -1; if (strlen(uri->path) <= 1 || path_exists(buf0) || path_is_file(buf1) || path_is_file(buf2)) { break; diff --git a/src/utils.c b/src/utils.c index feb2d66..51f66b5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -120,7 +120,7 @@ MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off += sprintf(str + *str_off, "%lu", list->entry_data.uint64); break; case MMDB_DATA_TYPE_UINT128: - *str_off += sprintf(str + *str_off, "%llu", list->entry_data.uint128); + *str_off += sprintf(str + *str_off, "%llu", (unsigned long long) list->entry_data.uint128); break; case MMDB_DATA_TYPE_INT32: *str_off += sprintf(str + *str_off, "%i", list->entry_data.uint32);