From f6a4c49a7a7406f6882a264c8da3430b1e1076d4 Mon Sep 17 00:00:00 2001 From: Urban Wallasch Date: Sun, 4 Aug 2019 11:55:47 +0200 Subject: [PATCH] * Fixed a bunch of potential unterminated string and/or buffer overrun errors. * Refactored some code. --- telehttpd.c | 143 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 56 deletions(-) diff --git a/telehttpd.c b/telehttpd.c index d81d474..9d31190 100644 --- a/telehttpd.c +++ b/telehttpd.c @@ -21,8 +21,10 @@ #include "telemetry.h" #include "tele2json.h" -static struct telemetry_state_t *telemetry; -static struct telemetry_state_t telemetry0; +struct thread_data_t { + int sock; + struct telemetry_state_t tele; +}; struct { int port; @@ -40,12 +42,10 @@ struct { false, }; -struct thread_data_t { - int sock; - struct telemetry_state_t tele; -}; +static struct telemetry_state_t *telemetry; +static struct telemetry_state_t telemetry0; -static volatile int force_quit; +static volatile sig_atomic_t force_quit; static void handle_signal(int sig) { fprintf (stderr, "SIGNAL: %d\n", sig); @@ -93,12 +93,34 @@ static int check_shm( bool retry ) { return 0; } +static size_t copy_field_val( char *buf, size_t bufsz, const char *needle, const char *haystack, const char *def ) { + const char *s; + size_t l; + + if ( NULL != ( s = strstr( haystack, needle ) ) ) { + const char *e; + s += strlen( needle ); + if ( NULL != ( e = strstr( s, "\r\n" ) ) ) + l = e - s; + else + s = NULL; + } + if ( NULL == s ) { + s = def; + l = def ? strlen( def ) : 0; + } + l = l < bufsz ? l : 0; + for ( size_t i = 0; i < l; i++ ) + buf[i] = s[i]; + buf[l] = '\0'; + return l; +} + static void respond( struct thread_data_t *td, const char *req ) { - char buf[4096]; + int n; + char buf[4096]; // Must be large enough to satisfy tele2json()! char origin[256]; char host[256]; - const char *s; - int fd = td->sock; enum respond_code { r_index, r_json, @@ -112,61 +134,70 @@ static void respond( struct thread_data_t *td, const char *req ) { else code = r_none; + copy_field_val( host, sizeof host, "Host: ", req, cfg.host ); + switch (code) { case r_json: - case r_index: - if ( NULL != (s = strstr(req, "Origin: ")) ) { - s += 8; //strlen("Origin: "); - const char *e = strstr(s, "\r\n"); - strncpy(origin, s, e-s); - } - else - strcpy(origin, cfg.origin); - - if ( NULL != (s = strstr(req, "Host: ")) ) { - s += 6;//strlen("Host: "); - const char *e = strstr(s, "\r\n"); - strncpy(host, s, e-s); - } - else - strcpy(host, cfg.host); - - if (r_json == code){ - write(fd, buf, sprintf(buf, "HTTP/1.1 200 OK\r\n")); - write(fd, buf, sprintf(buf, "Host: %s\r\n", host)); - write(fd, buf, sprintf(buf, "Access-Control-Allow-Origin: %s\r\n", origin)); - write(fd, buf, sprintf(buf, "Content-type: text/json\r\n")); - write(fd, buf, sprintf(buf, "Connection: close\r\n\r\n")); - write( fd, buf, tele2json(buf, sizeof buf, &td->tele) ); - } - else { - struct file_info_t fi; - if (0 == fserv_open_server(cfg.idxfile, &fi)){ - write(fd, buf, sprintf(buf, "HTTP/1.1 200 OK\r\n")); - write(fd, buf, sprintf(buf, "Host: %s\r\n", host)); - write(fd, buf, sprintf(buf, "Content-type: text/html\r\n")); - write(fd, buf, sprintf(buf, "Connection: close\r\n\r\n")); - fserv_sendfile(fd, &fi); - fserv_close(&fi); + copy_field_val( origin, sizeof origin, "Origin: ", req, cfg.origin ); + n = snprintf( buf, sizeof buf, + "HTTP/1.1 200 OK\r\n" + "Host: %s\r\n" + "Access-Control-Allow-Origin: %s\r\n" + "Content-type: text/json\r\n" + "Connection: close\r\n" + "\r\n", + host, + origin + ); + if ( 0 < n && (size_t)n < sizeof buf && n == write( td->sock, buf, n ) ) + write( td->sock, buf, tele2json( buf, sizeof buf, &td->tele ) ); + break; + case r_index: { + struct file_info_t fi; + if ( 0 == fserv_open_server( cfg.idxfile, &fi ) ){ + n = snprintf( buf, sizeof buf, + "HTTP/1.1 200 OK\r\n" + "Host: %s\r\n" + "Content-type: text/html\r\n" + "Connection: close\r\n" + "\r\n", + host + ); + if ( 0 < n && (size_t)n < sizeof buf && n == write( td->sock, buf, n ) ) { + fserv_sendfile( td->sock, &fi ); + fserv_close( &fi ); } - else - goto SEND_404; } + else + goto SEND_404; break; + } case r_none: SEND_404: - write(fd, buf, sprintf(buf, "HTTP/1.1 404 Not Found\r\n")); - write(fd, buf, sprintf(buf, "Host: localhost\r\n")); - write(fd, buf, sprintf(buf, "Content-type: text/plain\r\n")); - write(fd, buf, sprintf(buf, "Connection: close\r\n\r\n")); - write(fd, buf, sprintf(buf, "404 Not Found")); + n = snprintf( buf, sizeof buf, + "HTTP/1.1 404 Not Found\r\n" + "Host: %s\r\n" + "Content-type: text/plain\r\n" + "Connection: close\r\n" + "\r\n" + "404 Not Found", + host + ); + if ( 0 < n && (size_t)n < sizeof buf ) + write( td->sock, buf, n ); break; default: - write(fd, buf, sprintf(buf, "HTTP/1.1 500 Internal Server Error\r\n")); - write(fd, buf, sprintf(buf, "Host: localhost\r\n")); - write(fd, buf, sprintf(buf, "Content-type: text/plain\r\n")); - write(fd, buf, sprintf(buf, "Connection: close\r\n\r\n")); - write(fd, buf, sprintf(buf, "500 Internal Server Error")); + n = snprintf( buf, sizeof buf, + "HTTP/1.1 500 Internal Server Error\r\n" + "Host: %s\r\n" + "Content-type: text/plain\r\n" + "Connection: close\r\n" + "\r\n" + "500 Internal Server Error", + host + ); + if ( 0 < n && (size_t)n < sizeof buf ) + write( td->sock, buf, n ); break; } } -- 2.30.2