[TLS] better handling of SSL_ERROR_WANT_READ/WRITE
[lighttpd.git] / src / connections-glue.c
blob2d60ec2021482777c63b37a63058af4b33c3024d
1 #include "first.h"
3 #include "base.h"
4 #include "connections.h"
5 #include "joblist.h"
6 #include "log.h"
8 #include <errno.h>
10 #ifdef USE_OPENSSL
11 # include <openssl/ssl.h>
12 # include <openssl/err.h>
13 #endif
15 const char *connection_get_state(connection_state_t state) {
16 switch (state) {
17 case CON_STATE_CONNECT: return "connect";
18 case CON_STATE_READ: return "read";
19 case CON_STATE_READ_POST: return "readpost";
20 case CON_STATE_WRITE: return "write";
21 case CON_STATE_CLOSE: return "close";
22 case CON_STATE_ERROR: return "error";
23 case CON_STATE_HANDLE_REQUEST: return "handle-req";
24 case CON_STATE_REQUEST_START: return "req-start";
25 case CON_STATE_REQUEST_END: return "req-end";
26 case CON_STATE_RESPONSE_START: return "resp-start";
27 case CON_STATE_RESPONSE_END: return "resp-end";
28 default: return "(unknown)";
32 const char *connection_get_short_state(connection_state_t state) {
33 switch (state) {
34 case CON_STATE_CONNECT: return ".";
35 case CON_STATE_READ: return "r";
36 case CON_STATE_READ_POST: return "R";
37 case CON_STATE_WRITE: return "W";
38 case CON_STATE_CLOSE: return "C";
39 case CON_STATE_ERROR: return "E";
40 case CON_STATE_HANDLE_REQUEST: return "h";
41 case CON_STATE_REQUEST_START: return "q";
42 case CON_STATE_REQUEST_END: return "Q";
43 case CON_STATE_RESPONSE_START: return "s";
44 case CON_STATE_RESPONSE_END: return "S";
45 default: return "x";
49 int connection_set_state(server *srv, connection *con, connection_state_t state) {
50 UNUSED(srv);
52 con->state = state;
54 return 0;
57 #if 0
58 static void dump_packet(const unsigned char *data, size_t len) {
59 size_t i, j;
61 if (len == 0) return;
63 for (i = 0; i < len; i++) {
64 if (i % 16 == 0) fprintf(stderr, " ");
66 fprintf(stderr, "%02x ", data[i]);
68 if ((i + 1) % 16 == 0) {
69 fprintf(stderr, " ");
70 for (j = 0; j <= i % 16; j++) {
71 unsigned char c;
73 if (i-15+j >= len) break;
75 c = data[i-15+j];
77 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
80 fprintf(stderr, "\n");
84 if (len % 16 != 0) {
85 for (j = i % 16; j < 16; j++) {
86 fprintf(stderr, " ");
89 fprintf(stderr, " ");
90 for (j = i & ~0xf; j < len; j++) {
91 unsigned char c;
93 c = data[j];
94 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
96 fprintf(stderr, "\n");
99 #endif
101 static int connection_handle_read_ssl(server *srv, connection *con) {
102 #ifdef USE_OPENSSL
103 int r, ssl_err, len, count = 0;
104 char *mem = NULL;
105 size_t mem_len = 0;
107 if (!con->srv_socket->is_ssl) return -1;
109 ERR_clear_error();
110 do {
111 chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, SSL_pending(con->ssl));
112 #if 0
113 /* overwrite everything with 0 */
114 memset(mem, 0, mem_len);
115 #endif
117 len = SSL_read(con->ssl, mem, mem_len);
118 chunkqueue_use_memory(con->read_queue, len > 0 ? len : 0);
120 if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
121 log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
122 connection_set_state(srv, con, CON_STATE_ERROR);
123 return -1;
126 if (len > 0) {
127 con->bytes_read += len;
128 count += len;
130 } while (len == (ssize_t) mem_len && count < MAX_READ_LIMIT);
133 if (len < 0) {
134 int oerrno = errno;
135 switch ((r = SSL_get_error(con->ssl, len))) {
136 case SSL_ERROR_WANT_WRITE:
137 con->is_writable = -1;
138 case SSL_ERROR_WANT_READ:
139 con->is_readable = 0;
141 /* the manual says we have to call SSL_read with the same arguments next time.
142 * we ignore this restriction; no one has complained about it in 1.5 yet, so it probably works anyway.
145 return 0;
146 case SSL_ERROR_SYSCALL:
148 * man SSL_get_error()
150 * SSL_ERROR_SYSCALL
151 * Some I/O error occurred. The OpenSSL error queue may contain more
152 * information on the error. If the error queue is empty (i.e.
153 * ERR_get_error() returns 0), ret can be used to find out more about
154 * the error: If ret == 0, an EOF was observed that violates the
155 * protocol. If ret == -1, the underlying BIO reported an I/O error
156 * (for socket I/O on Unix systems, consult errno for details).
159 while((ssl_err = ERR_get_error())) {
160 /* get all errors from the error-queue */
161 log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
162 r, ERR_error_string(ssl_err, NULL));
165 switch(oerrno) {
166 default:
167 log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
168 len, r, oerrno,
169 strerror(oerrno));
170 break;
173 break;
174 case SSL_ERROR_ZERO_RETURN:
175 /* clean shutdown on the remote side */
177 if (r == 0) {
178 /* FIXME: later */
181 /* fall thourgh */
182 default:
183 while((ssl_err = ERR_get_error())) {
184 switch (ERR_GET_REASON(ssl_err)) {
185 case SSL_R_SSL_HANDSHAKE_FAILURE:
186 #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA
187 case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
188 #endif
189 #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
190 case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
191 #endif
192 #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE
193 case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
194 #endif
195 if (!con->conf.log_ssl_noise) continue;
196 break;
197 default:
198 break;
200 /* get all errors from the error-queue */
201 log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
202 r, ERR_error_string(ssl_err, NULL));
204 break;
207 connection_set_state(srv, con, CON_STATE_ERROR);
209 return -1;
210 } else if (len == 0) {
211 con->is_readable = 0;
212 /* the other end close the connection -> KEEP-ALIVE */
214 return -2;
215 } else {
216 return 0;
218 #else
219 UNUSED(srv);
220 UNUSED(con);
221 return -1;
222 #endif
225 /* 0: everything ok, -1: error, -2: con closed */
226 int connection_handle_read(server *srv, connection *con) {
227 int len;
228 char *mem = NULL;
229 size_t mem_len = 0;
230 int toread;
232 if (con->srv_socket->is_ssl) {
233 return connection_handle_read_ssl(srv, con);
236 /* default size for chunks is 4kb; only use bigger chunks if FIONREAD tells
237 * us more than 4kb is available
238 * if FIONREAD doesn't signal a big chunk we fill the previous buffer
239 * if it has >= 1kb free
241 #if defined(__WIN32)
242 chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, 4096);
244 len = recv(con->fd, mem, mem_len, 0);
245 #else /* __WIN32 */
246 if (ioctl(con->fd, FIONREAD, &toread) || toread <= 4*1024) {
247 toread = 4096;
249 else if (toread > MAX_READ_LIMIT) {
250 toread = MAX_READ_LIMIT;
252 chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, toread);
254 len = read(con->fd, mem, mem_len);
255 #endif /* __WIN32 */
257 chunkqueue_use_memory(con->read_queue, len > 0 ? len : 0);
259 if (len < 0) {
260 con->is_readable = 0;
262 #if defined(__WIN32)
264 int lastError = WSAGetLastError();
265 switch (lastError) {
266 case EAGAIN:
267 return 0;
268 case EINTR:
269 /* we have been interrupted before we could read */
270 con->is_readable = 1;
271 return 0;
272 case ECONNRESET:
273 /* suppress logging for this error, expected for keep-alive */
274 break;
275 default:
276 log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - recv failed: ", lastError);
277 break;
280 #else /* __WIN32 */
281 switch (errno) {
282 case EAGAIN:
283 return 0;
284 case EINTR:
285 /* we have been interrupted before we could read */
286 con->is_readable = 1;
287 return 0;
288 case ECONNRESET:
289 /* suppress logging for this error, expected for keep-alive */
290 break;
291 default:
292 log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
293 break;
295 #endif /* __WIN32 */
297 connection_set_state(srv, con, CON_STATE_ERROR);
299 return -1;
300 } else if (len == 0) {
301 con->is_readable = 0;
302 /* the other end close the connection -> KEEP-ALIVE */
304 /* pipelining */
306 return -2;
307 } else if (len != (ssize_t) mem_len) {
308 /* we got less then expected, wait for the next fd-event */
310 con->is_readable = 0;
313 con->bytes_read += len;
314 #if 0
315 dump_packet(b->ptr, len);
316 #endif
318 return 0;
321 handler_t connection_handle_read_post_state(server *srv, connection *con) {
322 chunkqueue *cq = con->read_queue;
323 chunkqueue *dst_cq = con->request_content_queue;
325 int is_closed = 0;
327 if (con->is_readable) {
328 con->read_idle_ts = srv->cur_ts;
330 switch(connection_handle_read(srv, con)) {
331 case -1:
332 return HANDLER_ERROR;
333 case -2:
334 is_closed = 1;
335 break;
336 default:
337 break;
341 chunkqueue_remove_finished_chunks(cq);
343 if (con->request.content_length <= 64*1024) {
344 /* don't buffer request bodies <= 64k on disk */
345 chunkqueue_steal(dst_cq, cq, (off_t)con->request.content_length - dst_cq->bytes_in);
347 else if (0 != chunkqueue_steal_with_tempfiles(srv, dst_cq, cq, (off_t)con->request.content_length - dst_cq->bytes_in)) {
348 /* writing to temp file failed */
349 con->http_status = 500; /* Internal Server Error */
350 con->keep_alive = 0;
351 con->mode = DIRECT;
352 chunkqueue_reset(con->write_queue);
354 return HANDLER_FINISHED;
357 chunkqueue_remove_finished_chunks(cq);
359 if (dst_cq->bytes_in == (off_t)con->request.content_length) {
360 /* Content is ready */
361 con->conf.stream_request_body &= ~FDEVENT_STREAM_REQUEST_POLLIN;
362 if (con->state == CON_STATE_READ_POST) {
363 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
365 return HANDLER_GO_ON;
366 } else if (is_closed) {
367 #if 0
368 con->http_status = 400; /* Bad Request */
369 con->keep_alive = 0;
370 con->mode = DIRECT;
371 chunkqueue_reset(con->write_queue);
373 return HANDLER_FINISHED;
374 #endif
375 return HANDLER_ERROR;
376 } else {
377 con->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLIN;
378 return (con->conf.stream_request_body & FDEVENT_STREAM_REQUEST)
379 ? HANDLER_GO_ON
380 : HANDLER_WAIT_FOR_EVENT;
384 void connection_response_reset(server *srv, connection *con) {
385 UNUSED(srv);
387 con->http_status = 0;
388 con->is_writable = 1;
389 con->file_finished = 0;
390 con->file_started = 0;
391 con->got_response = 0;
392 con->parsed_response = 0;
393 con->response.keep_alive = 0;
394 con->response.content_length = -1;
395 con->response.transfer_encoding = 0;
396 buffer_reset(con->physical.path);
397 array_reset(con->response.headers);
398 chunkqueue_reset(con->write_queue);