Hello community, here is the log from the commit of package hiawatha for openSUSE:Factory checked in at 2014-01-29 22:15:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hiawatha (Old) and /work/SRC/openSUSE:Factory/.hiawatha.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hiawatha" Changes: -------- --- /work/SRC/openSUSE:Factory/hiawatha/hiawatha.changes 2013-11-22 07:11:16.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.hiawatha.new/hiawatha.changes 2014-01-29 22:15:44.000000000 +0100 @@ -1,0 +2,6 @@ +Thu Dec 12 22:04:38 UTC 2013 - [email protected] + +- Update to 9.3.1: + * Several bugfixes in reverse proxy. + +------------------------------------------------------------------- Old: ---- hiawatha-9.3.tar.gz New: ---- hiawatha-9.3.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hiawatha.spec ++++++ --- /var/tmp/diff_new_pack.qIwnys/_old 2014-01-29 22:15:44.000000000 +0100 +++ /var/tmp/diff_new_pack.qIwnys/_new 2014-01-29 22:15:44.000000000 +0100 @@ -1,8 +1,8 @@ # # spec file for package hiawatha # -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. -# Copyright (c) 2013 Mariusz Fik <[email protected]>. +# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2013-2014 Mariusz Fik <[email protected]>. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -20,7 +20,7 @@ %define webroot /srv/www Name: hiawatha -Version: 9.3 +Version: 9.3.1 Release: 0 Summary: A secure and advanced webserver License: GPL-2.0 ++++++ hiawatha-9.3.tar.gz -> hiawatha-9.3.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiawatha-9.3/CMakeLists.txt new/hiawatha-9.3.1/CMakeLists.txt --- old/hiawatha-9.3/CMakeLists.txt 2013-11-05 22:39:25.000000000 +0100 +++ new/hiawatha-9.3.1/CMakeLists.txt 2013-12-07 19:54:45.000000000 +0100 @@ -35,7 +35,7 @@ # Settings set(HIAWATHA_VERSION_MAJOR 9) set(HIAWATHA_VERSION_MINOR 3) -set(HIAWATHA_VERSION_PATCH 0) +set(HIAWATHA_VERSION_PATCH 1) string(TOLOWER ${CMAKE_PROJECT_NAME} PROJECT_NAME) if(${HIAWATHA_VERSION_PATCH} EQUAL 0) set(HIAWATHA_VERSION "${HIAWATHA_VERSION_MAJOR}.${HIAWATHA_VERSION_MINOR}") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiawatha-9.3/ChangeLog new/hiawatha-9.3.1/ChangeLog --- old/hiawatha-9.3/ChangeLog 2013-11-05 22:39:26.000000000 +0100 +++ new/hiawatha-9.3.1/ChangeLog 2013-12-07 19:54:46.000000000 +0100 @@ -1,3 +1,9 @@ +hiawatha (9.3.1) stable; urgency=low + + * Several bugfixes in reverse proxy. + + -- Hugo Leisink <[email protected]> Sat, 7 Dec 2013 19:54:49 +0100 + hiawatha (9.3) stable; urgency=low * PolarSSL updated to version 1.3.2. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiawatha-9.3/src/cache.c new/hiawatha-9.3.1/src/cache.c --- old/hiawatha-9.3/src/cache.c 2013-11-05 22:39:25.000000000 +0100 +++ new/hiawatha-9.3.1/src/cache.c 2013-12-24 20:11:00.000000000 +0100 @@ -30,6 +30,7 @@ #define MAX_CACHE_INDEX 250 #define EXTENSION_SIZE 10 +extern char *hs_conn; extern char *hs_conlen; static t_cached_object *cache[MAX_CACHE_INDEX]; @@ -165,36 +166,13 @@ static t_cached_object *add_output_to_cache(t_session *session, char *output, int size, int time, t_cot_type cot_type) { t_cached_object *object; - size_t len; - char *pos, *loc, *data, str[50]; + char *data; - if ((pos = strstr(output, "\r\n\r\n")) == NULL) { + if ((data = (char*)malloc(size + 1)) == NULL) { return NULL; } - *pos = '\0'; - loc = strcasestr(output, hs_conlen); - *pos = '\r'; - - if (loc == NULL) { - /* Output has no Content-Length - */ - len = size - (pos + 4 - output); - sprintf(str, "%s%ld\r\n", hs_conlen, (long)len); - len = strlen(str); - if ((data = (char*)malloc(len + size)) == NULL) { - return NULL; - } - memcpy(data, str, len); - memcpy(data + len, output, size); - size += len; - } else { - /* Output has Content-Length - */ - if ((data = (char*)malloc(size)) == NULL) { - return NULL; - } - memcpy(data, output, size); - } + memcpy(data, output, size); + *(data + size) = '\0'; secure_header(output); @@ -542,6 +520,7 @@ object->in_use = 1; object->type = cot_file; copy_ip(&(object->last_ip), &(session->ip_address)); + object->close_connection = false; if (add_object_to_cache(object) == false) { clear_free(object->data, size); @@ -646,6 +625,38 @@ } t_cached_object *add_cgi_output_to_cache(t_session *session, char *output, int size, int time) { + char *eoh, cl[32], *new_output; + size_t content_length, cl_len; + t_cached_object *object; + + if ((eoh = strstr(output, "\r\n\r\n")) != NULL) { + *eoh = '\0'; + + if (strstr(output, hs_conlen) == NULL) { + content_length = size - strlen(output) - 4; + *eoh = '\r'; + + if ((cl_len = snprintf(cl, 31, "%s%ld\r\n", hs_conlen, content_length)) > 30) { + return NULL; + } + + if ((new_output = malloc(cl_len + size)) == NULL) { + return NULL; + } + + memcpy(new_output, cl, cl_len); + memcpy(new_output + cl_len, output, size); + + object = add_output_to_cache(session, new_output, cl_len + size, time, cot_cgi); + + free(new_output); + + return object; + } + + *eoh = '\r'; + } + return add_output_to_cache(session, output, size, time, cot_cgi); } @@ -693,8 +704,14 @@ return search_cache_for_output(session, cot_rproxy); } -t_cached_object *add_rproxy_output_to_cache(t_session *session, char *output, int size, int time) { - return add_output_to_cache(session, output, size, time, cot_rproxy); +t_cached_object *add_rproxy_output_to_cache(t_session *session, char *output, int size, int time, bool keep_alive) { + t_cached_object *object; + + if ((object = add_output_to_cache(session, output, size, time, cot_rproxy)) != NULL) { + object->close_connection = (keep_alive == false); + } + + return object; } void handle_remove_header_for_rproxy_cache(t_session *session, char *buffer) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiawatha-9.3/src/cache.h new/hiawatha-9.3.1/src/cache.h --- old/hiawatha-9.3/src/cache.h 2013-11-05 22:39:26.000000000 +0100 +++ new/hiawatha-9.3.1/src/cache.h 2013-12-07 19:54:46.000000000 +0100 @@ -37,6 +37,7 @@ volatile int in_use; t_ip_addr last_ip; t_cot_type type; + bool close_connection; struct type_cached_object *prev; struct type_cached_object *next; @@ -69,7 +70,7 @@ */ #ifdef ENABLE_RPROXY int rproxy_cache_time(t_session *session, char *buffer); -t_cached_object *add_rproxy_output_to_cache(t_session *session, char *output, int size, int time); +t_cached_object *add_rproxy_output_to_cache(t_session *session, char *output, int size, int time, bool keep_alive); t_cached_object *search_cache_for_rproxy_output(t_session *session); void handle_remove_header_for_rproxy_cache(t_session *session, char *buffer); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiawatha-9.3/src/liblist.c new/hiawatha-9.3.1/src/liblist.c --- old/hiawatha-9.3/src/liblist.c 2013-11-05 22:39:25.000000000 +0100 +++ new/hiawatha-9.3.1/src/liblist.c 2013-12-07 19:54:45.000000000 +0100 @@ -106,6 +106,28 @@ return NULL; } +/* Reset the strlen of the HTTP header + */ +void reset_http_header_strlen(char *key, t_http_header *http_headers) { + int len; + + if ((key == NULL) || (http_headers == NULL)) { + return; + } + + len = strlen(key); + while (http_headers != NULL) { + if (strncasecmp(http_headers->data, key, len) == 0) { + http_headers->length = strlen(http_headers->data); + if (http_headers->value_offset > http_headers->length) { + http_headers->value_offset = 0; + } + break; + } + http_headers = http_headers->next; + } +} + /* free() a list of http_headers. */ t_http_header *remove_http_headers(t_http_header *http_headers) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiawatha-9.3/src/liblist.h new/hiawatha-9.3.1/src/liblist.h --- old/hiawatha-9.3/src/liblist.h 2013-11-05 22:39:26.000000000 +0100 +++ new/hiawatha-9.3.1/src/liblist.h 2013-12-07 19:54:46.000000000 +0100 @@ -72,6 +72,7 @@ t_http_header *parse_http_headers(char *line); char *get_http_header(char *key, t_http_header *http_headers); +void reset_http_header_strlen(char *key, t_http_header *http_headers); t_http_header *remove_http_headers(t_http_header *http_headers); void init_charlist(t_charlist *list); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiawatha-9.3/src/target.c new/hiawatha-9.3.1/src/target.c --- old/hiawatha-9.3/src/target.c 2013-11-05 22:39:25.000000000 +0100 +++ new/hiawatha-9.3.1/src/target.c 2013-12-07 19:54:45.000000000 +0100 @@ -726,7 +726,7 @@ free(cache_buffer); cache_buffer = NULL; } else { - memcpy(cache_buffer + cache_size, cgi_info.input_buffer, cgi_info.input_len); + memcpy(cache_buffer + cache_size, cgi_info.input_buffer, cgi_info.input_len); cache_size += cgi_info.input_len; *(cache_buffer + cache_size) = '\0'; } @@ -883,7 +883,7 @@ case cgi_END_OF_DATA: if (in_body) { retval = rs_QUIT; - if (send_in_chunks) { + if (send_in_chunks && (session->request_method != HEAD)) { if (send_chunk(session, NULL, 0) == -1) { retval = rs_DISCONNECT; } @@ -1329,14 +1329,32 @@ #endif #ifdef ENABLE_RPROXY +static int find_chunk_size(char *buffer) { + int chunk_extra_size, chunk_size; + + if (strstr(buffer, "\r\n") == NULL) { + return -1; + } + + chunk_extra_size = 4; + chunk_size = 0; + while (*buffer != '\r') { + chunk_size = (16 * chunk_size) + (int)hex_to_int(*buffer); + chunk_extra_size++; + buffer++; + } + + return chunk_extra_size + chunk_size; +} + int proxy_request(t_session *session, t_rproxy *rproxy) { t_rproxy_options options; t_rproxy_webserver webserver; t_rproxy_result rproxy_result; char buffer[RPROXY_BUFFER_SIZE + 1], *end_of_header, *str, *eol; - int bytes_read, bytes_in_buffer = 0, result = 200, code, poll_result; - int can_read, content_length = -1, content_read = 0; - bool header_read = false, keep_reading = true, keep_alive, chunked = false; + int bytes_read, bytes_in_buffer = 0, result = 200, code, poll_result, send_size; + int can_read, content_length = -1, content_read = 0, chunk_size, chunk_total, header_size; + bool header_read = false, keep_reading = true, keep_alive, chunked_transfer = false; struct pollfd poll_data; time_t deadline; #ifdef ENABLE_CACHE @@ -1356,12 +1374,14 @@ */ if (session->request_method == GET) { if ((cached_object = search_cache_for_rproxy_output(session)) != NULL) { - if (send_header(session) == -1) { - result = rs_DISCONNECT; - } else if (send_buffer(session, cached_object->data, cached_object->size) == -1) { + if (send_buffer(session, cached_object->data, cached_object->size) == -1) { result = rs_DISCONNECT; } + if (cached_object->close_connection) { + session->keep_alive = false; + } + done_with_cached_object(cached_object, false); return result; @@ -1393,14 +1413,16 @@ */ if (session->rproxy_kept_alive) { if (recv(session->rproxy_socket, buffer, 1, MSG_DONTWAIT | MSG_PEEK) == -1) { + if (errno != EAGAIN) { #ifdef ENABLE_SSL - if (session->rproxy_use_ssl) { - ssl_close(&(session->rproxy_ssl)); - } + if (session->rproxy_use_ssl) { + ssl_close(&(session->rproxy_ssl)); + } #endif - close(session->rproxy_socket); + close(session->rproxy_socket); - session->rproxy_kept_alive = false; + session->rproxy_kept_alive = false; + } } } @@ -1480,12 +1502,16 @@ } } + if (RPROXY_BUFFER_SIZE - bytes_in_buffer > 0) { #ifdef ENABLE_SSL - if (webserver.use_ssl) { - bytes_read = ssl_receive(&(webserver.ssl), buffer + bytes_in_buffer, RPROXY_BUFFER_SIZE - bytes_in_buffer); - } else + if (webserver.use_ssl) { + bytes_read = ssl_receive(&(webserver.ssl), buffer + bytes_in_buffer, RPROXY_BUFFER_SIZE - bytes_in_buffer); + } else #endif - bytes_read = read(webserver.socket, buffer + bytes_in_buffer, RPROXY_BUFFER_SIZE - bytes_in_buffer); + bytes_read = read(webserver.socket, buffer + bytes_in_buffer, RPROXY_BUFFER_SIZE - bytes_in_buffer); + } else { + bytes_read = -1; + } switch (bytes_read) { case -1: @@ -1501,10 +1527,12 @@ default: /* Read first line and extract return code */ - if (header_read == false) { - bytes_in_buffer += bytes_read; + bytes_in_buffer += bytes_read; + *(buffer + bytes_in_buffer) = '\0'; - *(buffer + bytes_in_buffer) = '\0'; + if (header_read == false) { + /* Look for header + */ if ((end_of_header = strstr(buffer, "\r\n\r\n")) != NULL) { *(end_of_header + 2) = '\0'; if ((code = extract_http_code(buffer)) != -1) { @@ -1520,7 +1548,7 @@ } #ifdef ENABLE_CACHE - if (code == 200) { + if ((code == 200) && (session->request_method == GET)) { if ((cache_time = rproxy_cache_time(session, buffer)) > 0) { if ((cache_buffer = (char*)malloc(session->config->cache_max_filesize + 1)) != NULL) { *(cache_buffer + session->config->cache_max_filesize) = '\0'; @@ -1533,46 +1561,47 @@ /* Parse content length */ - if ((str = strstr(buffer, hs_conlen)) != NULL) { + if (session->request_method == HEAD) { + content_length = 0; + } else if (((code >= 100) && (code < 200)) || (code == 204) || + (code == 302) || (code == 303) || (code == 304)) { + content_length = 0; + } else if ((str = strcasestr(buffer, hs_conlen)) != NULL) { str += strlen(hs_conlen); if ((eol = strchr(str, '\r')) != NULL) { *eol = '\0'; content_length = str2int(str); *eol = '\r'; } + } else { + content_length = 0; } - /* Determine if is chunked encoding + /* Determine if is chunked transfer encoding */ - if (strstr(buffer, hs_chunked) != NULL) { - chunked = true; + if (strcasestr(buffer, hs_chunked) != NULL) { + chunked_transfer = true; + content_length = -1; + header_size = end_of_header + 4 - buffer; } /* Determine connection type */ - if (strstr(buffer, " HTTP/1.0\r\n") != NULL) { + if (strncmp(buffer, "HTTP/1.0 ", 9) == 0) { keep_alive = false; - } else if (strstr(buffer, " HTTP/1.1\r\n") != NULL) { - keep_alive = true; - if ((str = strstr(buffer, hs_conn)) != NULL) { + } else if (strncmp(buffer, "HTTP/1.1 ", 9) == 0) { + if ((str = strcasestr(buffer, hs_conn)) != NULL) { str += strlen(hs_conn); - if ((eol = strchr(str, '\r')) != NULL) { - *eol = '\0'; - if (strcmp(str, "close") == 0) { - keep_alive = false; - } - *eol = '\r'; + if (strncmp(str, "close\r\n", 7) == 0) { + keep_alive = false; } } } content_read = bytes_in_buffer - (end_of_header + 4 - buffer); + header_read = true; *(end_of_header + 2)= '\r'; - - bytes_read = bytes_in_buffer; - bytes_in_buffer = 0; - header_read = true; } else if (bytes_in_buffer == RPROXY_BUFFER_SIZE) { result = -1; keep_reading = false; @@ -1582,41 +1611,79 @@ continue; } } else { + /* Dealing with body + */ content_read += bytes_read; - *(buffer + bytes_read) = '\0'; } if (content_read == content_length) { keep_reading = false; } - if (chunked && (bytes_read >= 7)) { - if (memcmp(buffer + bytes_read - 7, "\r\n0\r\n\r\n", 7) == 0) { - keep_reading = false; + /* Determine what to send + */ + if (chunked_transfer) { + /* Send chunk + */ + chunk_total = header_size; + while ((chunk_size = find_chunk_size(buffer + chunk_total)) != -1) { + if (chunk_total + chunk_size <= bytes_in_buffer) { + chunk_total += chunk_size; + + if (chunk_size == 5) { + keep_reading = false; + } + } else { + break; + } + } + + if (bytes_in_buffer >= chunk_total) { + send_size = chunk_total; + } else { + send_size = 0; } + } else { + /* Send complete buffer + */ + send_size = bytes_in_buffer; } - /* Send data to client + /* Send buffer content */ - if (send_buffer(session, buffer, bytes_read) == -1) { - result = -1; - keep_reading = false; - keep_alive = false; - break; - } + if (send_size > 0) { + if (send_buffer(session, buffer, send_size) == -1) { + result = -1; + keep_reading = false; + keep_alive = false; + break; + } #ifdef ENABLE_CACHE - if (cache_buffer != NULL) { - if ((off_t)(cache_size + bytes_read) > session->config->cache_max_filesize) { - clear_free(cache_buffer, cache_size); - cache_buffer = NULL; + /* Add output to cache buffer + */ + if (cache_buffer != NULL) { + if ((off_t)(cache_size + send_size) > session->config->cache_max_filesize) { + clear_free(cache_buffer, cache_size); + cache_buffer = NULL; + } else { + memcpy(cache_buffer + cache_size, buffer, send_size); + cache_size += send_size; + *(cache_buffer + cache_size) = '\0'; + } + } +#endif + + if (chunked_transfer) { + bytes_in_buffer -= chunk_total; + memmove(buffer, buffer + chunk_total, bytes_in_buffer); + *(buffer + bytes_in_buffer) = '\0'; + + header_size = 0; } else { - memcpy(cache_buffer + cache_size, buffer, bytes_read); - cache_size += bytes_read; - *(cache_buffer + cache_size) = '\0'; + bytes_in_buffer = 0; } } -#endif session->data_sent = true; } @@ -1625,7 +1692,7 @@ #ifdef ENABLE_CACHE if (cache_buffer != NULL) { - add_rproxy_output_to_cache(session, cache_buffer, cache_size, cache_time); + add_rproxy_output_to_cache(session, cache_buffer, cache_size, cache_time, keep_alive); clear_free(cache_buffer, cache_size); } #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiawatha-9.3/src/workers.c new/hiawatha-9.3.1/src/workers.c --- old/hiawatha-9.3/src/workers.c 2013-11-05 22:39:26.000000000 +0100 +++ new/hiawatha-9.3.1/src/workers.c 2013-12-07 19:54:46.000000000 +0100 @@ -382,6 +382,7 @@ #else remove_port_from_hostname(session->hostname); #endif + reset_http_header_strlen("Host:", session->http_headers); if ((host_record = get_hostrecord(session->config->first_host, session->hostname, session->binding)) != NULL) { session->host = host_record; @@ -1181,7 +1182,7 @@ free(new_thread); return -1; } else if (pthread_create(&(new_thread->worker), &child_attr, (void*)thread_wait_loop, (void*)new_thread) != 0) { - fprintf(stderr, "pthread create error.\n"); + perror("pthread create error"); pthread_attr_destroy(&child_attr); free(new_thread); return -1; -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
