Project

General

Profile

Feature #2130 ยป diff.txt

liming, 2009-12-30 08:22

 
1
diff -u ../lighttpd-1.5/src/base.h ./src/base.h
2
--- ../lighttpd-1.5/src/base.h	2009-12-11 11:24:07.000000000 +0800
3
+++ ./src/base.h	2009-12-30 15:57:40.000000000 +0800
4
@@ -548,6 +548,7 @@
5
 	unsigned short max_fds;
6
 	unsigned short max_conns;
7
 	unsigned int max_request_size;
8
+	unsigned int max_request_header_size;
9
 
10
 	unsigned short log_request_header_on_error;
11
 	unsigned short log_state_handling;
12
diff -u ../lighttpd-1.5/src/configfile.c ./src/configfile.c
13
--- ../lighttpd-1.5/src/configfile.c	2009-12-11 11:24:07.000000000 +0800
14
+++ ./src/configfile.c	2009-12-30 16:15:43.000000000 +0800
15
@@ -110,6 +110,7 @@
16
 		{ "ssl.verifyclient.depth",      NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER },     /* 62 */
17
 		{ "ssl.verifyclient.username",   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER },     /* 63 */
18
 		{ "ssl.verifyclient.exportcert", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 64 */
19
+		{ "server.max-request-header-size", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 65 */
20
 
21
 		{ "server.host",                 "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
22
 		{ "server.docroot",              "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
23
@@ -158,6 +159,7 @@
24
 	
25
 	cv[51].destination = &(srv->srvconf.log_timing);
26
 	cv[57].destination = srv->srvconf.breakagelog_file;
27
+	cv[65].destination = &(srv->srvconf.max_request_header_size);
28
 
29
 	srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
30
 
31
diff -u ../lighttpd-1.5/src/connections.c ./src/connections.c
32
--- ../lighttpd-1.5/src/connections.c	2009-12-11 11:24:07.000000000 +0800
33
+++ ./src/connections.c	2009-12-30 15:55:56.000000000 +0800
34
@@ -637,6 +637,12 @@
35
 		return HANDLER_ERROR;
36
 	}
37
 
38
+	off_t header_len = 0;
39
+	off_t offset = 0;
40
+	if (con->recv_raw->first) {
41
+		offset = con->recv_raw->first->offset;
42
+	}
43
+	
44
 	switch (http_request_parse_cq(con->recv_raw, con->http_req)) {
45
 	case PARSE_ERROR:
46
 		con->http_status = 400; /* the header is broken */
47
@@ -646,11 +652,37 @@
48
 
49
 		return HANDLER_FINISHED;
50
 	case PARSE_NEED_MORE:
51
+		header_len = chunkqueue_written(con->recv_raw) - offset;
52
+		if (con->recv_raw && srv->srvconf.max_request_header_size != 0
53
+			&& header_len > (srv->srvconf.max_request_header_size << 10)) {
54
+			ERROR("request header length is too long, read_length=%d, client-ip: %s", 
55
+				(int)header_len, SAFE_BUF_STR(con->dst_addr_buf));
56
+				con->http_status = 400; 
57
+				con->keep_alive = 0;
58
+				con->send->is_closed = 1;
59
+				chunkqueue_remove_finished_chunks(con->recv_raw);
60
+
61
+				return HANDLER_FINISHED;
62
+		}
63
+
64
 		/* we need more */
65
 		fdevent_event_add(srv->ev, con->sock, FDEVENT_IN);
66
 
67
 		return HANDLER_WAIT_FOR_EVENT;
68
 	case PARSE_SUCCESS:
69
+		header_len = chunkqueue_written(con->recv_raw) - offset;
70
+		if (con->recv_raw && srv->srvconf.max_request_header_size != 0
71
+			&& header_len > (srv->srvconf.max_request_header_size << 10) ) {
72
+			ERROR("request header length is too long, read_length=%d, client-ip: %s", 
73
+				(int)header_len, SAFE_BUF_STR(con->dst_addr_buf));
74
+			con->http_status = 400;
75
+			con->keep_alive = 0;
76
+			con->send->is_closed = 1;
77
+			
78
+			chunkqueue_remove_finished_chunks(con->recv_raw);
79
+			
80
+			return HANDLER_FINISHED;
81
+		}
82
 		chunkqueue_remove_finished_chunks(con->recv_raw);
83
 		break;
84
 	default:
85
@@ -1016,11 +1048,15 @@
86
 
87
 			con->request_count++;             /* max-keepalive requests */
88
 			con->loops_per_request = 0;       /* infinite loops */
89
+			
90
+			off_t header_len = 0;
91
 
92
 			/* if the content was short enough, it might have a header already in the pipe */
93
 			if (con->recv_raw->first &&
94
 			    chunkqueue_length(con->recv_raw) - con->recv_raw->first->offset > 0) {
95
 				/* pipelining */
96
+				
97
+				off_t offset = con->recv_raw->first->offset;
98
 
99
 				switch (http_request_parse_cq(con->recv_raw, con->http_req)) {
100
 				case PARSE_ERROR:
101
@@ -1032,10 +1068,36 @@
102
 					connection_set_state(srv, con, CON_STATE_HANDLE_RESPONSE_HEADER);
103
 					break;
104
 				case PARSE_NEED_MORE:
105
+					header_len = chunkqueue_written(con->recv_raw) - offset;
106
+					if (con->recv_raw && srv->srvconf.max_request_header_size != 0
107
+						&& header_len > (srv->srvconf.max_request_header_size << 10)) {
108
+					
109
+						ERROR("request header length is too long, read_length=%d, client-ip[%s]", 
110
+							(int)header_len, SAFE_BUF_STR(con->dst_addr_buf));
111
+						con->http_status = 400; 
112
+						con->keep_alive = 0;
113
+						chunkqueue_remove_finished_chunks(con->recv_raw);
114
+							
115
+						connection_set_state(srv, con, CON_STATE_HANDLE_RESPONSE_HEADER);
116
+						break;
117
+					}
118
 					/* the read() call is on the way */
119
 					connection_set_state(srv, con, CON_STATE_READ_REQUEST_HEADER);
120
 					break;
121
 				case PARSE_SUCCESS:
122
+					header_len = chunkqueue_written(con->recv_raw) - offset;
123
+					if (con->recv_raw && srv->srvconf.max_request_header_size != 0
124
+						&& header_len > (srv->srvconf.max_request_header_size << 10) ) {
125
+						
126
+						ERROR("request header length is too long, read_length=%d, client-ip[%s]", 
127
+							(int)header_len, SAFE_BUF_STR(con->dst_addr_buf));
128
+						con->http_status = 400;
129
+						con->keep_alive = 0;
130
+						
131
+						chunkqueue_remove_finished_chunks(con->recv_raw);
132
+						connection_set_state(srv, con, CON_STATE_HANDLE_RESPONSE_HEADER);
133
+						break;
134
+					}
135
 					/* pipelining worked, validate the header */
136
 					chunkqueue_remove_finished_chunks(con->recv_raw);
    (1-1/1)