[packages/lighttpd] 1.4.51

glen glen at pld-linux.org
Fri Nov 30 14:13:56 CET 2018


commit 398f6f255b600473411b3cda136b8eafb039884b
Author: Elan Ruusamäe <glen at pld-linux.org>
Date:   Sat Oct 27 19:11:05 2018 +0300

    1.4.51

 a9e131..df8e4f.patch | 976 ---------------------------------------------------
 lighttpd.spec        |   8 +-
 2 files changed, 3 insertions(+), 981 deletions(-)
---
diff --git a/lighttpd.spec b/lighttpd.spec
index fb659bd..ed41295 100644
--- a/lighttpd.spec
+++ b/lighttpd.spec
@@ -41,12 +41,12 @@
 Summary:	Fast and light HTTP server
 Summary(pl.UTF-8):	Szybki i lekki serwer HTTP
 Name:		lighttpd
-Version:	1.4.50
-Release:	5
+Version:	1.4.51
+Release:	1
 License:	BSD
 Group:		Networking/Daemons/HTTP
 Source0:	https://download.lighttpd.net/lighttpd/releases-1.4.x/%{name}-%{version}.tar.xz
-# Source0-md5:	0547831efda8492648b7f0c652865dfd
+# Source0-md5:	6e68c19601af332fa3c5f174245f59bf
 Source1:	%{name}.init
 Source2:	%{name}.conf
 Source3:	%{name}.user
@@ -120,7 +120,6 @@ Patch2:		%{name}-mod_h264_streaming.patch
 Patch3:		%{name}-branding.patch
 Patch4:		systemd.patch
 Patch5:		test-port-setup.patch
-Patch6:		a9e131..df8e4f.patch
 URL:		https://www.lighttpd.net/
 %{?with_geoip:BuildRequires:	GeoIP-devel}
 %{?with_xattr:BuildRequires:	attr-devel}
@@ -953,7 +952,6 @@ Plik monitrc do monitorowania serwera www lighttpd.
 %patch3 -p1
 %patch4 -p1
 %patch5 -p1
-%patch6 -p1
 
 rm -f src/mod_ssi_exprparser.h # bad patching: should be removed by is emptied instead
 
diff --git a/a9e131..df8e4f.patch b/a9e131..df8e4f.patch
deleted file mode 100644
index 12ea77c..0000000
--- a/a9e131..df8e4f.patch
+++ /dev/null
@@ -1,976 +0,0 @@
-From: =?UTF-8?Q?Stefan_B=c3=bchler?= <stbuehler at web.de>
-To: lighttpd-announce at lists.lighttpd.net
-Message-ID: <8cbf0c87-1037-8f70-aa24-b2f14c95170d at web.de>
-Date: Sun, 26 Aug 2018 19:06:30 +0200
-Subject: use-after-free bug in header folding
-
-Hi,
-
-Or Peles reported some use-after-free scenarios related to header 
-folding (continuing a header value on a whitespace indented line).
-
-The fix required some preparation and therefor consists of a series of 4 
-patches, see git:
-
-https://git.lighttpd.net/lighttpd/lighttpd1.4.git/log/?qt=range&q=a9e131..df8e4f&showmsg=1
-
-There are currently no plans for a new release.
-
-cheers,
-Stefan
-
-diff --git a/src/request.c b/src/request.c
-index 213a87e1..e94d8591 100644
---- a/src/request.c
-+++ b/src/request.c
-@@ -408,26 +408,179 @@ static int request_uri_is_valid_char(unsigned char c) {
- 	return 1;
- }
- 
--static int http_request_missing_CR_before_LF(server *srv, connection *con) {
-+static void http_request_missing_CR_before_LF(server *srv, connection *con) {
- 	if (srv->srvconf.log_request_header_on_error) {
- 		log_error_write(srv, __FILE__, __LINE__, "s", "missing CR before LF in header -> 400");
- 		log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request);
- 	}
-+}
- 
--	con->http_status = 400;
--	con->keep_alive = 0;
--	con->response.keep_alive = 0;
-+enum keep_alive_set {
-+	HTTP_CONNECTION_UNSET,
-+	HTTP_CONNECTION_KEEPALIVE,
-+	HTTP_CONNECTION_CLOSE,
-+};
-+
-+typedef struct {
-+	enum keep_alive_set keep_alive_set;
-+	char con_length_set;
-+	char *reqline_host;
-+	int reqline_hostlen;
-+} parse_header_state;
-+
-+static void init_parse_header_state(parse_header_state* state) {
-+	state->keep_alive_set = HTTP_CONNECTION_UNSET;
-+	state->con_length_set = 0;
-+	state->reqline_host = NULL;
-+	state->reqline_hostlen = 0;
-+}
-+
-+/* add a header to the list of headers; certain headers are also parsed in this state.
-+ *
-+ * Also might drop a header if deemed unnecessary/broken.
-+ *
-+ * returns 0 on error
-+ */
-+static int parse_single_header(server *srv, connection *con, parse_header_state *state, data_string *ds) {
-+	int cmp = 0;
-+
-+	/* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
-+	if (buffer_string_is_empty(ds->value)) {
-+		goto drop_header;
-+	}
-+
-+	/* retreive values
-+	 *
-+	 *
-+	 * the list of options is sorted to simplify the search
-+	 */
-+
-+	if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
-+		array *vals;
-+		size_t vi;
-+
-+		/* split on , */
-+
-+		vals = srv->split_vals;
-+
-+		array_reset(vals);
-+
-+		http_request_split_value(vals, ds->value);
-+
-+		for (vi = 0; vi < vals->used; vi++) {
-+			data_string *dsv = (data_string *)vals->data[vi];
-+
-+			if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
-+				state->keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
-+
-+				break;
-+			} else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
-+				state->keep_alive_set = HTTP_CONNECTION_CLOSE;
-+
-+				break;
-+			}
-+		}
-+
-+	} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
-+		char *err;
-+		off_t r;
-+
-+		if (state->con_length_set) {
-+			if (srv->srvconf.log_request_header_on_error) {
-+				log_error_write(srv, __FILE__, __LINE__, "s",
-+						"duplicate Content-Length-header -> 400");
-+				log_error_write(srv, __FILE__, __LINE__, "Sb",
-+						"request-header:\n",
-+						con->request.request);
-+			}
-+			goto invalid_header;
-+		}
-+
-+		r = strtoll(ds->value->ptr, &err, 10);
-+
-+		if (*err == '\0' && r >= 0) {
-+			state->con_length_set = 1;
-+			con->request.content_length = r;
-+		} else {
-+			log_error_write(srv, __FILE__, __LINE__, "sbs",
-+					"content-length broken:", ds->value, "-> 400");
-+			goto invalid_header;
-+		}
-+	} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Type")))) {
-+		/* if dup, only the first one will survive */
-+		if (!con->request.http_content_type) {
-+			con->request.http_content_type = ds->value->ptr;
-+		} else {
-+			if (srv->srvconf.log_request_header_on_error) {
-+				log_error_write(srv, __FILE__, __LINE__, "s",
-+						"duplicate Content-Type-header -> 400");
-+				log_error_write(srv, __FILE__, __LINE__, "Sb",
-+						"request-header:\n",
-+						con->request.request);
-+			}
-+			goto invalid_header;
-+		}
-+	} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
-+		if (state->reqline_host) {
-+			/* ignore all host: headers as we got the host in the request line */
-+			goto drop_header;
-+		} else if (!con->request.http_host) {
-+			con->request.http_host = ds->value;
-+		} else {
-+			if (srv->srvconf.log_request_header_on_error) {
-+				log_error_write(srv, __FILE__, __LINE__, "s",
-+						"duplicate Host-header -> 400");
-+				log_error_write(srv, __FILE__, __LINE__, "Sb",
-+						"request-header:\n",
-+						con->request.request);
-+			}
-+			goto invalid_header;
-+		}
-+	} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
-+		/* Proxies sometimes send dup headers
-+		 * if they are the same we ignore the second
-+		 * if not, we raise an error */
-+		if (!con->request.http_if_modified_since) {
-+			con->request.http_if_modified_since = ds->value->ptr;
-+		} else if (0 == strcasecmp(con->request.http_if_modified_since, ds->value->ptr)) {
-+			/* ignore it if they are the same */
-+			goto drop_header;
-+		} else {
-+			if (srv->srvconf.log_request_header_on_error) {
-+				log_error_write(srv, __FILE__, __LINE__, "s",
-+						"duplicate If-Modified-Since header -> 400");
-+				log_error_write(srv, __FILE__, __LINE__, "Sb",
-+						"request-header:\n",
-+						con->request.request);
-+			}
-+			goto invalid_header;
-+		}
-+	} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
-+		/* if dup, only the first one will survive */
-+		if (!con->request.http_if_none_match) {
-+			con->request.http_if_none_match = ds->value->ptr;
-+		} else {
-+			goto drop_header;
-+		}
-+	}
-+
-+	array_insert_unique(con->request.headers, (data_unset *)ds);
-+	return 1;
-+
-+drop_header:
-+	ds->free((data_unset *)ds);
-+	return 1;
-+
-+invalid_header:
-+	ds->free((data_unset *)ds);
- 	return 0;
- }
- 
- int http_request_parse(server *srv, connection *con) {
--	char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
-+	char *uri = NULL, *proto = NULL, *method = NULL;
- 	int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
- 	char *value = NULL, *key = NULL;
--	char *reqline_host = NULL;
--	int reqline_hostlen = 0;
--
--	enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
-+	data_string *current_header = NULL;
- 
- 	int line = 0;
- 
-@@ -437,6 +590,9 @@ int http_request_parse(server *srv, connection *con) {
- 	int done = 0;
- 	const unsigned int http_header_strict = (con->conf.http_parseopts & HTTP_PARSEOPT_HEADER_STRICT);
- 
-+	parse_header_state state;
-+	init_parse_header_state(&state);
-+
- 	/*
- 	 * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
- 	 * Option : "^([-a-zA-Z]+): (.+)$"
-@@ -457,9 +613,7 @@ int http_request_parse(server *srv, connection *con) {
- 
- 	      #ifdef __COVERITY__
- 		if (buffer_string_length(con->request.request) < 2) {
--			con->keep_alive = 0;
--			con->http_status = 400;
--			return 0;
-+			goto failure;
- 		}
- 	      #endif
- 		/* coverity[overflow_sink : FALSE] */
-@@ -467,12 +621,13 @@ int http_request_parse(server *srv, connection *con) {
- 	} else if (con->request_count > 0 &&
- 	    con->request.request->ptr[1] == '\n') {
- 		/* we are in keep-alive and might get \n after a previous POST request.*/
--		if (http_header_strict) return http_request_missing_CR_before_LF(srv, con);
-+		if (http_header_strict) {
-+			http_request_missing_CR_before_LF(srv, con);
-+			goto failure;
-+		}
- 	      #ifdef __COVERITY__
- 		if (buffer_string_length(con->request.request) < 1) {
--			con->keep_alive = 0;
--			con->http_status = 400;
--			return 0;
-+			goto failure;
- 		}
- 	      #endif
- 		/* coverity[overflow_sink : FALSE] */
-@@ -482,9 +637,6 @@ int http_request_parse(server *srv, connection *con) {
- 		buffer_copy_buffer(con->parse_request, con->request.request);
- 	}
- 
--	keep_alive_set = 0;
--	con_length_set = 0;
--
- 	/* parse the first line of the request
- 	 *
- 	 * should be:
-@@ -510,22 +662,19 @@ int http_request_parse(server *srv, connection *con) {
- 					con->parse_request->ptr[i] = '\0';
- 					++i;
- 				} else if (http_header_strict) { /* '\n' */
--					return http_request_missing_CR_before_LF(srv, con);
-+					http_request_missing_CR_before_LF(srv, con);
-+					goto failure;
- 				}
- 				con->parse_request->ptr[i] = '\0';
- 
- 				if (request_line_stage != 2) {
--					con->http_status = 400;
--					con->response.keep_alive = 0;
--					con->keep_alive = 0;
--
- 					if (srv->srvconf.log_request_header_on_error) {
- 						log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
- 						log_error_write(srv, __FILE__, __LINE__, "Sb",
- 								"request-header:\n",
- 								con->request.request);
- 					}
--					return 0;
-+					goto failure;
- 				}
- 
- 				proto = con->parse_request->ptr + first;
-@@ -536,8 +685,6 @@ int http_request_parse(server *srv, connection *con) {
- 				/* we got the first one :) */
- 				if (HTTP_METHOD_UNSET == (r = get_http_method_key(method))) {
- 					con->http_status = 501;
--					con->response.keep_alive = 0;
--					con->keep_alive = 0;
- 
- 					if (srv->srvconf.log_request_header_on_error) {
- 						log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
-@@ -546,7 +693,7 @@ int http_request_parse(server *srv, connection *con) {
- 								con->request.request);
- 					}
- 
--					return 0;
-+					goto failure;
- 				}
- 
- 				con->request.http_method = r;
-@@ -582,16 +729,13 @@ int http_request_parse(server *srv, connection *con) {
- 					}
- 
- 					if (invalid_version) {
--						con->http_status = 400;
--						con->keep_alive = 0;
--
- 						if (srv->srvconf.log_request_header_on_error) {
- 							log_error_write(srv, __FILE__, __LINE__, "s", "unknown protocol -> 400");
- 							log_error_write(srv, __FILE__, __LINE__, "Sb",
- 									"request-header:\n",
- 									con->request.request);
- 						}
--						return 0;
-+						goto failure;
- 					}
- 
- 					if (major_num == 1 && minor_num == 1) {
-@@ -607,19 +751,16 @@ int http_request_parse(server *srv, connection *con) {
- 									"request-header:\n",
- 									con->request.request);
- 						}
--						return 0;
-+						goto failure;
- 					}
- 				} else {
--					con->http_status = 400;
--					con->keep_alive = 0;
--
- 					if (srv->srvconf.log_request_header_on_error) {
- 						log_error_write(srv, __FILE__, __LINE__, "s", "unknown protocol -> 400");
- 						log_error_write(srv, __FILE__, __LINE__, "Sb",
- 								"request-header:\n",
- 								con->request.request);
- 					}
--					return 0;
-+					goto failure;
- 				}
- 
- 				if (*uri == '/') {
-@@ -627,14 +768,14 @@ int http_request_parse(server *srv, connection *con) {
- 					buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
- 				} else if (0 == strncasecmp(uri, "http://", 7) &&
- 				    NULL != (nuri = strchr(uri + 7, '/'))) {
--					reqline_host = uri + 7;
--					reqline_hostlen = nuri - reqline_host;
-+					state.reqline_host = uri + 7;
-+					state.reqline_hostlen = nuri - state.reqline_host;
- 
- 					buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
- 				} else if (0 == strncasecmp(uri, "https://", 8) &&
- 				    NULL != (nuri = strchr(uri + 8, '/'))) {
--					reqline_host = uri + 8;
--					reqline_hostlen = nuri - reqline_host;
-+					state.reqline_host = uri + 8;
-+					state.reqline_hostlen = nuri - state.reqline_host;
- 
- 					buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
- 				} else if (!http_header_strict
-@@ -643,10 +784,8 @@ int http_request_parse(server *srv, connection *con) {
- 					/* everything looks good so far */
- 					buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
- 				} else {
--					con->http_status = 400;
--					con->keep_alive = 0;
- 					log_error_write(srv, __FILE__, __LINE__, "ss", "request-URI parse error -> 400 for:", uri);
--					return 0;
-+					goto failure;
- 				}
- 
- 				/* check uri for invalid characters */
-@@ -660,33 +799,30 @@ int http_request_parse(server *srv, connection *con) {
- 					j = (NULL == z) ? jlen : (size_t)(z - con->request.uri->ptr);
- 				}
- 				if (j < jlen) {
--						con->http_status = 400;
--						con->keep_alive = 0;
--
--						if (srv->srvconf.log_request_header_on_error) {
--							unsigned char buf[2];
--							buf[0] = con->request.uri->ptr[j];
--							buf[1] = '\0';
--
--							if (con->request.uri->ptr[j] > 32 &&
--							    con->request.uri->ptr[j] != 127) {
--								/* the character is printable -> print it */
--								log_error_write(srv, __FILE__, __LINE__, "ss",
--										"invalid character in URI -> 400",
--										buf);
--							} else {
--								/* a control-character, print ascii-code */
--								log_error_write(srv, __FILE__, __LINE__, "sd",
--										"invalid character in URI -> 400",
--										con->request.uri->ptr[j]);
--							}
--
--							log_error_write(srv, __FILE__, __LINE__, "Sb",
--									"request-header:\n",
--									con->request.request);
-+					if (srv->srvconf.log_request_header_on_error) {
-+						unsigned char buf[2];
-+						buf[0] = con->request.uri->ptr[j];
-+						buf[1] = '\0';
-+
-+						if (con->request.uri->ptr[j] > 32 &&
-+							con->request.uri->ptr[j] != 127) {
-+							/* the character is printable -> print it */
-+							log_error_write(srv, __FILE__, __LINE__, "ss",
-+									"invalid character in URI -> 400",
-+									buf);
-+						} else {
-+							/* a control-character, print ascii-code */
-+							log_error_write(srv, __FILE__, __LINE__, "sd",
-+									"invalid character in URI -> 400",
-+									con->request.uri->ptr[j]);
- 						}
- 
--						return 0;
-+						log_error_write(srv, __FILE__, __LINE__, "Sb",
-+								"request-header:\n",
-+								con->request.request);
-+					}
-+
-+					goto failure;
- 				}
- 
- 				buffer_copy_buffer(con->request.orig_uri, con->request.uri);
-@@ -711,17 +847,13 @@ int http_request_parse(server *srv, connection *con) {
- 				break;
- 			default:
- 				/* ERROR, one space to much */
--				con->http_status = 400;
--				con->response.keep_alive = 0;
--				con->keep_alive = 0;
--
- 				if (srv->srvconf.log_request_header_on_error) {
- 					log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
- 					log_error_write(srv, __FILE__, __LINE__, "Sb",
- 							"request-header:\n",
- 							con->request.request);
- 				}
--				return 0;
-+				goto failure;
- 			}
- 
- 			request_line_stage++;
-@@ -732,20 +864,16 @@ int http_request_parse(server *srv, connection *con) {
- 	in_folding = 0;
- 
- 	if (buffer_string_is_empty(con->request.uri)) {
--		con->http_status = 400;
--		con->response.keep_alive = 0;
--		con->keep_alive = 0;
--
- 		if (srv->srvconf.log_request_header_on_error) {
- 			log_error_write(srv, __FILE__, __LINE__, "s", "no uri specified -> 400");
- 			log_error_write(srv, __FILE__, __LINE__, "Sb",
- 							"request-header:\n",
- 							con->request.request);
- 		}
--		return 0;
-+		goto failure;
- 	}
- 
--	if (reqline_host) {
-+	if (state.reqline_host) {
- 		/* Insert as host header */
- 		data_string *ds;
- 
-@@ -754,7 +882,7 @@ int http_request_parse(server *srv, connection *con) {
- 		}
- 
- 		buffer_copy_string_len(ds->key, CONST_STR_LEN("Host"));
--		buffer_copy_string_len(ds->value, reqline_host, reqline_hostlen);
-+		buffer_copy_string_len(ds->value, state.reqline_host, state.reqline_hostlen);
- 		array_insert_unique(con->request.headers, (data_unset *)ds);
- 		con->request.http_host = ds->value;
- 	}
-@@ -799,10 +927,6 @@ int http_request_parse(server *srv, connection *con) {
- 			case '=':
- 			case '{':
- 			case '}':
--				con->http_status = 400;
--				con->keep_alive = 0;
--				con->response.keep_alive = 0;
--
- 				if (srv->srvconf.log_request_header_on_error) {
- 					log_error_write(srv, __FILE__, __LINE__, "sbsds",
- 						"invalid character in key", con->request.request, cur, *cur, "-> 400");
-@@ -811,7 +935,7 @@ int http_request_parse(server *srv, connection *con) {
- 						"request-header:\n",
- 						con->request.request);
- 				}
--				return 0;
-+				goto failure;
- 			case ' ':
- 			case '\t':
- 				if (i == first) {
-@@ -850,11 +974,7 @@ int http_request_parse(server *srv, connection *con) {
- 								con->request.request);
- 						}
- 
--						con->http_status = 400;
--						con->response.keep_alive = 0;
--						con->keep_alive = 0;
--
--						return 0;
-+						goto failure;
- 					}
- 				}
- 
-@@ -876,15 +996,13 @@ int http_request_parse(server *srv, connection *con) {
- 							con->request.request);
- 					}
- 
--					con->http_status = 400;
--					con->keep_alive = 0;
--					con->response.keep_alive = 0;
--					return 0;
-+					goto failure;
- 				}
- 				break;
- 			case '\n':
- 				if (http_header_strict) {
--					return http_request_missing_CR_before_LF(srv, con);
-+					http_request_missing_CR_before_LF(srv, con);
-+					goto failure;
- 				} else if (i == first) {
- 					con->parse_request->ptr[i] = '\0';
- 					done = 1;
-@@ -893,10 +1011,6 @@ int http_request_parse(server *srv, connection *con) {
- 				/* fall through */
- 			default:
- 				if (http_header_strict ? (*cur < 32 || ((unsigned char)*cur) >= 127) : *cur == '\0') {
--					con->http_status = 400;
--					con->keep_alive = 0;
--					con->response.keep_alive = 0;
--
- 					if (srv->srvconf.log_request_header_on_error) {
- 						log_error_write(srv, __FILE__, __LINE__, "sbsds",
- 							"invalid character in key", con->request.request, cur, *cur, "-> 400");
-@@ -906,7 +1020,7 @@ int http_request_parse(server *srv, connection *con) {
- 							con->request.request);
- 					}
- 
--					return 0;
-+					goto failure;
- 				}
- 				/* ok */
- 				break;
-@@ -916,9 +1030,13 @@ int http_request_parse(server *srv, connection *con) {
- 			case '\r':
- 			case '\n':
- 				if (*cur == '\n' || con->parse_request->ptr[i+1] == '\n') {
--					data_string *ds = NULL;
-+					int value_len;
-+
- 					if (*cur == '\n') {
--						if (http_header_strict) return http_request_missing_CR_before_LF(srv, con);
-+						if (http_header_strict) {
-+							http_request_missing_CR_before_LF(srv, con);
-+							goto failure;
-+						}
- 					} else { /* (con->parse_request->ptr[i+1] == '\n') */
- 						con->parse_request->ptr[i] = '\0';
- 						++i;
-@@ -927,17 +1045,15 @@ int http_request_parse(server *srv, connection *con) {
- 					/* End of Headerline */
- 					con->parse_request->ptr[i] = '\0';
- 
-+					value_len = cur - value;
-+
-+					/* strip trailing white-spaces */
-+					while (value_len > 0 && (value[value_len - 1] == ' ' || value[value_len - 1] == '\t')) {
-+						--value_len;
-+					}
-+
- 					if (in_folding) {
--						/**
--						 * we use a evil hack to handle the line-folding
--						 * 
--						 * As array_insert_unique() deletes 'ds' in the case of a duplicate
--						 * ds points somewhere and we get a evil crash. As a solution we keep the old
--						 * "key" and get the current value from the hash and append us
--						 *
--						 * */
--
--						if (!key || !key_len) {
-+						if (!current_header) {
- 							/* 400 */
- 
- 							if (srv->srvconf.log_request_header_on_error) {
-@@ -948,193 +1064,35 @@ int http_request_parse(server *srv, connection *con) {
- 									con->request.request);
- 							}
- 
--
--							con->http_status = 400;
--							con->keep_alive = 0;
--							con->response.keep_alive = 0;
--							return 0;
-+							goto failure;
- 						}
- 
--						if (NULL != (ds = (data_string *)array_get_element_klen(con->request.headers, key, key_len))) {
--							buffer_append_string(ds->value, value);
--						}
-+						buffer_append_string_len(current_header->value, value, value_len);
- 					} else {
--						int s_len;
--						key = con->parse_request->ptr + first;
--
--						s_len = cur - value;
--
--						/* strip trailing white-spaces */
--						for (; s_len > 0 && 
--								(value[s_len - 1] == ' ' || 
--								 value[s_len - 1] == '\t'); s_len--);
--
--						value[s_len] = '\0';
--
--						if (s_len > 0) {
--							int cmp = 0;
--							if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
--								ds = data_string_init();
--							}
--							buffer_copy_string_len(ds->key, key, key_len);
--							buffer_copy_string_len(ds->value, value, s_len);
--
--							/* retreive values
--							 *
--							 *
--							 * the list of options is sorted to simplify the search
--							 */
--
--							if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
--								array *vals;
--								size_t vi;
--
--								/* split on , */
--
--								vals = srv->split_vals;
--
--								array_reset(vals);
--
--								http_request_split_value(vals, ds->value);
--
--								for (vi = 0; vi < vals->used; vi++) {
--									data_string *dsv = (data_string *)vals->data[vi];
--
--									if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
--										keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
--
--										break;
--									} else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
--										keep_alive_set = HTTP_CONNECTION_CLOSE;
--
--										break;
--									}
--								}
--
--							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
--								char *err;
--								off_t r;
--
--								if (con_length_set) {
--									con->http_status = 400;
--									con->keep_alive = 0;
--
--									if (srv->srvconf.log_request_header_on_error) {
--										log_error_write(srv, __FILE__, __LINE__, "s",
--												"duplicate Content-Length-header -> 400");
--										log_error_write(srv, __FILE__, __LINE__, "Sb",
--												"request-header:\n",
--												con->request.request);
--									}
--									array_insert_unique(con->request.headers, (data_unset *)ds);
--									return 0;
--								}
--
--								r = strtoll(ds->value->ptr, &err, 10);
--
--								if (*err == '\0' && r >= 0) {
--									con_length_set = 1;
--									con->request.content_length = r;
--								} else {
--									log_error_write(srv, __FILE__, __LINE__, "sbs",
--											"content-length broken:", ds->value, "-> 400");
--
--									con->http_status = 400;
--									con->keep_alive = 0;
--
--									array_insert_unique(con->request.headers, (data_unset *)ds);
--									return 0;
--								}
--							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Type")))) {
--								/* if dup, only the first one will survive */
--								if (!con->request.http_content_type) {
--									con->request.http_content_type = ds->value->ptr;
--								} else {
--									con->http_status = 400;
--									con->keep_alive = 0;
--
--									if (srv->srvconf.log_request_header_on_error) {
--										log_error_write(srv, __FILE__, __LINE__, "s",
--												"duplicate Content-Type-header -> 400");
--										log_error_write(srv, __FILE__, __LINE__, "Sb",
--												"request-header:\n",
--												con->request.request);
--									}
--									array_insert_unique(con->request.headers, (data_unset *)ds);
--									return 0;
--								}
--							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
--								if (reqline_host) {
--									/* ignore all host: headers as we got the host in the request line */
--									ds->free((data_unset*) ds);
--									ds = NULL;
--								} else if (!con->request.http_host) {
--									con->request.http_host = ds->value;
--								} else {
--									con->http_status = 400;
--									con->keep_alive = 0;
--
--									if (srv->srvconf.log_request_header_on_error) {
--										log_error_write(srv, __FILE__, __LINE__, "s",
--												"duplicate Host-header -> 400");
--										log_error_write(srv, __FILE__, __LINE__, "Sb",
--												"request-header:\n",
--												con->request.request);
--									}
--									array_insert_unique(con->request.headers, (data_unset *)ds);
--									return 0;
--								}
--							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
--								/* Proxies sometimes send dup headers
--								 * if they are the same we ignore the second
--								 * if not, we raise an error */
--								if (!con->request.http_if_modified_since) {
--									con->request.http_if_modified_since = ds->value->ptr;
--								} else if (0 == strcasecmp(con->request.http_if_modified_since,
--											ds->value->ptr)) {
--									/* ignore it if they are the same */
--
--									ds->free((data_unset *)ds);
--									ds = NULL;
--								} else {
--									con->http_status = 400;
--									con->keep_alive = 0;
--
--									if (srv->srvconf.log_request_header_on_error) {
--										log_error_write(srv, __FILE__, __LINE__, "s",
--												"duplicate If-Modified-Since header -> 400");
--										log_error_write(srv, __FILE__, __LINE__, "Sb",
--												"request-header:\n",
--												con->request.request);
--									}
--									array_insert_unique(con->request.headers, (data_unset *)ds);
--									return 0;
--								}
--							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
--								/* if dup, only the first one will survive */
--								if (!con->request.http_if_none_match) {
--									con->request.http_if_none_match = ds->value->ptr;
--								} else {
--									ds->free((data_unset*) ds);
--									ds = NULL;
--								}
-+						/* process previous header */
-+						if (current_header) {
-+							data_string *ds = current_header;
-+							current_header = NULL;
-+							if (!parse_single_header(srv, con, &state, ds)) {
-+								/* parse_single_header should already have logged it */
-+								goto failure;
- 							}
-+						}
- 
--							if (ds) array_insert_unique(con->request.headers, (data_unset *)ds);
--						} else {
--							/* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
-+						key = con->parse_request->ptr + first;
-+
-+						if (NULL == (current_header = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
-+							current_header = data_string_init();
- 						}
-+
-+						buffer_copy_string_len(current_header->key, key, key_len);
-+						buffer_copy_string_len(current_header->value, value, value_len);
- 					}
- 
- 					first = i+1;
- 					is_key = 1;
- 					value = NULL;
--#if 0
--					/**
--					 * for Bug 1230 keep the key_len a live
--					 */
- 					key_len = 0; 
--#endif
- 					in_folding = 0;
- 				} else {
- 					if (srv->srvconf.log_request_header_on_error) {
-@@ -1142,10 +1100,7 @@ int http_request_parse(server *srv, connection *con) {
- 								"CR without LF", con->request.request, "-> 400");
- 					}
- 
--					con->http_status = 400;
--					con->keep_alive = 0;
--					con->response.keep_alive = 0;
--					return 0;
-+					goto failure;
- 				}
- 				break;
- 			case ' ':
-@@ -1160,22 +1115,29 @@ int http_request_parse(server *srv, connection *con) {
- 								"invalid char in header", (int)*cur, "-> 400");
- 					}
- 
--					con->http_status = 400;
--					con->keep_alive = 0;
--
--					return 0;
-+					goto failure;
- 				}
- 				break;
- 			}
- 		}
- 	}
- 
-+	/* process last header */
-+	if (current_header) {
-+		data_string* ds = current_header;
-+		current_header = NULL;
-+		if (!parse_single_header(srv, con, &state, ds)) {
-+			/* parse_single_header should already have logged it */
-+			goto failure;
-+		}
-+	}
-+
- 	con->header_len = i;
- 
- 	/* do some post-processing */
- 
- 	if (con->request.http_version == HTTP_VERSION_1_1) {
--		if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
-+		if (state.keep_alive_set != HTTP_CONNECTION_CLOSE) {
- 			/* no Connection-Header sent */
- 
- 			/* HTTP/1.1 -> keep-alive default TRUE */
-@@ -1187,9 +1149,6 @@ int http_request_parse(server *srv, connection *con) {
- 		/* RFC 2616, 14.23 */
- 		if (con->request.http_host == NULL ||
- 		    buffer_string_is_empty(con->request.http_host)) {
--			con->http_status = 400;
--			con->response.keep_alive = 0;
--			con->keep_alive = 0;
- 
- 			if (srv->srvconf.log_request_header_on_error) {
- 				log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
-@@ -1197,10 +1156,10 @@ int http_request_parse(server *srv, connection *con) {
- 						"request-header:\n",
- 						con->request.request);
- 			}
--			return 0;
-+			goto failure;
- 		}
- 	} else {
--		if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
-+		if (state.keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
- 			/* no Connection-Header sent */
- 
- 			/* HTTP/1.0 -> keep-alive default FALSE  */
-@@ -1222,11 +1181,7 @@ int http_request_parse(server *srv, connection *con) {
- 					con->request.request);
- 		}
- 
--		con->http_status = 400;
--		con->response.keep_alive = 0;
--		con->keep_alive = 0;
--
--		return 0;
-+		goto failure;
- 	}
- 
- 	{
-@@ -1235,24 +1190,21 @@ int http_request_parse(server *srv, connection *con) {
- 			if (con->request.http_version == HTTP_VERSION_1_0) {
- 				log_error_write(srv, __FILE__, __LINE__, "s",
- 						"HTTP/1.0 with Transfer-Encoding (bad HTTP/1.0 proxy?) -> 400");
--				con->keep_alive = 0;
--				con->http_status = 400; /* Bad Request */
--				return 0;
-+				goto failure;
- 			}
- 
- 			if (0 != strcasecmp(ds->value->ptr, "chunked")) {
- 				/* Transfer-Encoding might contain additional encodings,
- 				 * which are not currently supported by lighttpd */
--				con->keep_alive = 0;
- 				con->http_status = 501; /* Not Implemented */
--				return 0;
-+				goto failure;
- 			}
- 
- 			/* reset value for Transfer-Encoding, a hop-by-hop header,
- 			 * which must not be blindly forwarded to backends */
- 			buffer_reset(ds->value); /* headers with empty values are ignored */
- 
--			con_length_set = 1;
-+			state.con_length_set = 1;
- 			con->request.content_length = -1;
- 
- 			/*(note: ignore whether or not Content-Length was provided)*/
-@@ -1265,27 +1217,23 @@ int http_request_parse(server *srv, connection *con) {
- 	case HTTP_METHOD_GET:
- 	case HTTP_METHOD_HEAD:
- 		/* content-length is forbidden for those */
--		if (con_length_set && con->request.content_length != 0) {
-+		if (state.con_length_set && con->request.content_length != 0) {
- 			/* content-length is missing */
- 			log_error_write(srv, __FILE__, __LINE__, "s",
- 					"GET/HEAD with content-length -> 400");
- 
--			con->keep_alive = 0;
--			con->http_status = 400;
--			return 0;
-+			goto failure;
- 		}
- 		break;
- 	case HTTP_METHOD_POST:
- 		/* content-length is required for them */
--		if (!con_length_set) {
-+		if (!state.con_length_set) {
- 			/* content-length is missing */
- 			log_error_write(srv, __FILE__, __LINE__, "s",
- 					"POST-request, but content-length missing -> 411");
- 
--			con->keep_alive = 0;
- 			con->http_status = 411;
--			return 0;
--
-+			goto failure;
- 		}
- 		break;
- 	default:
-@@ -1294,12 +1242,21 @@ int http_request_parse(server *srv, connection *con) {
- 
- 
- 	/* check if we have read post data */
--	if (con_length_set) {
-+	if (state.con_length_set) {
- 		/* we have content */
- 		if (con->request.content_length != 0) {
- 			return 1;
- 		}
- 	}
- 
-+	return 0;
-+
-+failure:
-+	if (current_header) current_header->free((data_unset *)current_header);
-+
-+	con->keep_alive = 0;
-+	con->response.keep_alive = 0;
-+	if (!con->http_status) con->http_status = 400;
-+
- 	return 0;
- }
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/lighttpd.git/commitdiff/398f6f255b600473411b3cda136b8eafb039884b



More information about the pld-cvs-commit mailing list