aboutsummaryrefslogtreecommitdiff
path: root/src/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon')
-rw-r--r--src/daemon/connection.c114
-rw-r--r--src/daemon/connection_https.c92
-rw-r--r--src/daemon/daemon.c202
-rw-r--r--src/daemon/https/tls/gnutls_buffers.c11
-rw-r--r--src/daemon/internal.h37
5 files changed, 223 insertions, 233 deletions
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index dd75771d..8477a9d0 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -410,7 +410,8 @@ try_ready_chunked_body (struct MHD_Connection *connection)
410 } 410 }
411 if (ret > 0xFFFFFF) 411 if (ret > 0xFFFFFF)
412 ret = 0xFFFFFF; 412 ret = 0xFFFFFF;
413 cblen = snprintf (cbuf, sizeof (cbuf), "%X\r\n", ret); 413 SPRINTF (cbuf, "%X\r\n", ret);
414 cblen = strlen(cbuf);
414 EXTRA_CHECK (cblen <= sizeof (cbuf)); 415 EXTRA_CHECK (cblen <= sizeof (cbuf));
415 memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen); 416 memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen);
416 memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2); 417 memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2);
@@ -458,10 +459,9 @@ add_extra_headers (struct MHD_Connection *connection)
458 else if (NULL == MHD_get_response_header (connection->response, 459 else if (NULL == MHD_get_response_header (connection->response,
459 MHD_HTTP_HEADER_CONTENT_LENGTH)) 460 MHD_HTTP_HEADER_CONTENT_LENGTH))
460 { 461 {
461 _REAL_SNPRINTF (buf, 462 SPRINTF (buf,
462 128, 463 "%llu",
463 "%llu", 464 (unsigned long long) connection->response->total_size);
464 (unsigned long long) connection->response->total_size);
465 MHD_add_response_header (connection->response, 465 MHD_add_response_header (connection->response,
466 MHD_HTTP_HEADER_CONTENT_LENGTH, buf); 466 MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
467 } 467 }
@@ -469,11 +469,12 @@ add_extra_headers (struct MHD_Connection *connection)
469 469
470/** 470/**
471 * Produce HTTP "Date:" header. 471 * Produce HTTP "Date:" header.
472 * @param date where to write the header 472 *
473 * @param max maximum number of characters to write 473 * @param date where to write the header, with
474 * at least 128 bytes available space.
474 */ 475 */
475static void 476static void
476get_date_string (char *date, unsigned int max) 477get_date_string (char *date)
477{ 478{
478 static const char *days[] = 479 static const char *days[] =
479 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 480 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
@@ -486,17 +487,17 @@ get_date_string (char *date, unsigned int max)
486 487
487 time (&t); 488 time (&t);
488 gmtime_r (&t, &now); 489 gmtime_r (&t, &now);
489 snprintf (date, 490 SPRINTF (date,
490 max - 1, 491 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
491 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n", 492 days[now.tm_wday % 7],
492 days[now.tm_wday % 7], 493 now.tm_mday,
493 now.tm_mday, 494 mons[now.tm_mon % 12],
494 mons[now.tm_mon % 12], 495 1900 + now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
495 1900 + now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
496} 496}
497 497
498/** 498/**
499 * try growing the read buffer 499 * Try growing the read buffer
500 *
500 * @return MHD_YES on success, MHD_NO on failure 501 * @return MHD_YES on success, MHD_NO on failure
501 */ 502 */
502static int 503static int
@@ -530,7 +531,7 @@ build_header_response (struct MHD_Connection *connection)
530 size_t size; 531 size_t size;
531 size_t off; 532 size_t off;
532 struct MHD_HTTP_Header *pos; 533 struct MHD_HTTP_Header *pos;
533 char code[128]; 534 char code[256];
534 char date[128]; 535 char date[128];
535 char *data; 536 char *data;
536 enum MHD_ValueKind kind; 537 enum MHD_ValueKind kind;
@@ -540,15 +541,18 @@ build_header_response (struct MHD_Connection *connection)
540 { 541 {
541 add_extra_headers (connection); 542 add_extra_headers (connection);
542 reason_phrase = MHD_get_reason_phrase_for (connection->responseCode); 543 reason_phrase = MHD_get_reason_phrase_for (connection->responseCode);
543 _REAL_SNPRINTF (code, 128, "%s %u %s\r\n", MHD_HTTP_VERSION_1_1, 544 SPRINTF (code,
544 connection->responseCode, reason_phrase); 545 "%s %u %s\r\n",
546 MHD_HTTP_VERSION_1_1,
547 connection->responseCode,
548 reason_phrase);
545 off = strlen (code); 549 off = strlen (code);
546 /* estimate size */ 550 /* estimate size */
547 size = off + 2; /* extra \r\n at the end */ 551 size = off + 2; /* extra \r\n at the end */
548 kind = MHD_HEADER_KIND; 552 kind = MHD_HEADER_KIND;
549 if (NULL == MHD_get_response_header (connection->response, 553 if (NULL == MHD_get_response_header (connection->response,
550 MHD_HTTP_HEADER_DATE)) 554 MHD_HTTP_HEADER_DATE))
551 get_date_string (date, sizeof (date)); 555 get_date_string (date);
552 else 556 else
553 date[0] = '\0'; 557 date[0] = '\0';
554 size += strlen (date); 558 size += strlen (date);
@@ -1138,9 +1142,9 @@ call_connection_handler (struct MHD_Connection *connection)
1138 { 1142 {
1139 buffer_head[i] = '\0'; 1143 buffer_head[i] = '\0';
1140 malformed = 1144 malformed =
1141 (1 != sscanf (buffer_head, "%X", 1145 (1 != SSCANF (buffer_head, "%X",
1142 &connection->current_chunk_size)) && 1146 &connection->current_chunk_size)) &&
1143 (1 != sscanf (buffer_head, "%x", 1147 (1 != SSCANF (buffer_head, "%x",
1144 &connection->current_chunk_size)); 1148 &connection->current_chunk_size));
1145 } 1149 }
1146 if (malformed) 1150 if (malformed)
@@ -1234,8 +1238,9 @@ do_read (struct MHD_Connection *connection)
1234 if (connection->read_buffer_size == connection->read_buffer_offset) 1238 if (connection->read_buffer_size == connection->read_buffer_offset)
1235 return MHD_NO; 1239 return MHD_NO;
1236 1240
1237 bytes_read = connection->recv_cls (connection); 1241 bytes_read = connection->recv_cls (connection,
1238 1242 &connection->read_buffer[connection->read_buffer_offset],
1243 connection->read_buffer_size - connection->read_buffer_offset);
1239 if (bytes_read < 0) 1244 if (bytes_read < 0)
1240 { 1245 {
1241 if (errno == EINTR) 1246 if (errno == EINTR)
@@ -1270,7 +1275,11 @@ do_write (struct MHD_Connection *connection)
1270{ 1275{
1271 int ret; 1276 int ret;
1272 1277
1273 ret = connection->send_cls (connection); 1278 ret = connection->send_cls (connection,
1279 &connection->write_buffer
1280 [connection->write_buffer_send_offset],
1281 connection->write_buffer_append_offset
1282 - connection->write_buffer_send_offset);
1274 1283
1275 if (ret < 0) 1284 if (ret < 0)
1276 { 1285 {
@@ -1284,7 +1293,7 @@ do_write (struct MHD_Connection *connection)
1284 return MHD_YES; 1293 return MHD_YES;
1285 } 1294 }
1286#if DEBUG_SEND_DATA 1295#if DEBUG_SEND_DATA
1287 fprintf (stderr, 1296 FPRINTF (stderr,
1288 "Sent response: `%.*s'\n", 1297 "Sent response: `%.*s'\n",
1289 ret, 1298 ret,
1290 &connection->write_buffer[connection->write_buffer_send_offset]); 1299 &connection->write_buffer[connection->write_buffer_send_offset]);
@@ -1293,15 +1302,6 @@ do_write (struct MHD_Connection *connection)
1293 return MHD_YES; 1302 return MHD_YES;
1294} 1303}
1295 1304
1296static ssize_t
1297MHD_con_read (struct MHD_Connection *connection)
1298{
1299 return RECV (connection->socket_fd,
1300 &connection->read_buffer[connection->read_buffer_offset],
1301 connection->read_buffer_size -
1302 connection->read_buffer_offset, MSG_NOSIGNAL);
1303}
1304
1305/** 1305/**
1306 * Check if we are done sending the write-buffer. 1306 * Check if we are done sending the write-buffer.
1307 * If so, transition into "next_state". 1307 * If so, transition into "next_state".
@@ -1462,7 +1462,7 @@ parse_connection_headers (struct MHD_Connection *connection)
1462 MHD_HTTP_HEADER_CONTENT_LENGTH); 1462 MHD_HTTP_HEADER_CONTENT_LENGTH);
1463 if (clen != NULL) 1463 if (clen != NULL)
1464 { 1464 {
1465 if (1 != sscanf (clen, "%llu", &cval)) 1465 if (1 != SSCANF (clen, "%llu", &cval))
1466 { 1466 {
1467#if HAVE_MESSAGES 1467#if HAVE_MESSAGES
1468 MHD_DLOG (connection->daemon, 1468 MHD_DLOG (connection->daemon,
@@ -1553,16 +1553,6 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
1553 return MHD_YES; 1553 return MHD_YES;
1554} 1554}
1555 1555
1556static ssize_t
1557MHD_con_write (struct MHD_Connection *connection)
1558{
1559 return SEND (connection->socket_fd,
1560 &connection->write_buffer[connection->
1561 write_buffer_send_offset],
1562 connection->write_buffer_append_offset -
1563 connection->write_buffer_send_offset, MSG_NOSIGNAL);
1564}
1565
1566/** 1556/**
1567 * This function was created to handle writes to sockets when it has 1557 * This function was created to handle writes to sockets when it has
1568 * been determined that the socket can be written to. All 1558 * been determined that the socket can be written to. All
@@ -1595,12 +1585,11 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1595 case MHD_CONNECTION_HEADERS_PROCESSED: 1585 case MHD_CONNECTION_HEADERS_PROCESSED:
1596 break; 1586 break;
1597 case MHD_CONNECTION_CONTINUE_SENDING: 1587 case MHD_CONNECTION_CONTINUE_SENDING:
1598 ret = SEND (connection->socket_fd, 1588 ret = connection->send_cls (connection,
1599 &HTTP_100_CONTINUE 1589 &HTTP_100_CONTINUE
1600 [connection->continue_message_write_offset], 1590 [connection->continue_message_write_offset],
1601 strlen (HTTP_100_CONTINUE) - 1591 strlen (HTTP_100_CONTINUE) -
1602 connection->continue_message_write_offset, 1592 connection->continue_message_write_offset);
1603 MSG_NOSIGNAL);
1604 if (ret < 0) 1593 if (ret < 0)
1605 { 1594 {
1606 if (errno == EINTR) 1595 if (errno == EINTR)
@@ -1613,7 +1602,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1613 return MHD_NO; 1602 return MHD_NO;
1614 } 1603 }
1615#if DEBUG_SEND_DATA 1604#if DEBUG_SEND_DATA
1616 fprintf (stderr, 1605 FPRINTF (stderr,
1617 "Sent 100 continue response: `%.*s'\n", 1606 "Sent 100 continue response: `%.*s'\n",
1618 ret, 1607 ret,
1619 &HTTP_100_CONTINUE 1608 &HTTP_100_CONTINUE
@@ -1661,17 +1650,17 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1661 else 1650 else
1662#endif 1651#endif
1663 { 1652 {
1664 ret = SEND (connection->socket_fd, 1653 ret = connection->send_cls (connection,
1665 &response->data[connection-> 1654 &response->data[connection->
1666 response_write_position - 1655 response_write_position -
1667 response->data_start], 1656 response->data_start],
1668 response->data_size - 1657 response->data_size -
1669 (connection->response_write_position - 1658 (connection->response_write_position -
1670 response->data_start), MSG_NOSIGNAL); 1659 response->data_start));
1671 } 1660 }
1672#if DEBUG_SEND_DATA 1661#if DEBUG_SEND_DATA
1673 if (ret > 0) 1662 if (ret > 0)
1674 fprintf (stderr, 1663 FPRINTF (stderr,
1675 "Sent DATA response: `%.*s'\n", 1664 "Sent DATA response: `%.*s'\n",
1676 ret, 1665 ret,
1677 &response->data[connection->response_write_position - 1666 &response->data[connection->response_write_position -
@@ -1748,6 +1737,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
1748 unsigned int timeout; 1737 unsigned int timeout;
1749 const char *end; 1738 const char *end;
1750 char *line; 1739 char *line;
1740
1751 while (1) 1741 while (1)
1752 { 1742 {
1753#if DEBUG_STATES 1743#if DEBUG_STATES
@@ -2072,8 +2062,6 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2072void 2062void
2073MHD_set_http_calbacks (struct MHD_Connection *connection) 2063MHD_set_http_calbacks (struct MHD_Connection *connection)
2074{ 2064{
2075 connection->recv_cls = &MHD_con_read;
2076 connection->send_cls = &MHD_con_write;
2077 connection->read_handler = &MHD_connection_handle_read; 2065 connection->read_handler = &MHD_connection_handle_read;
2078 connection->write_handler = &MHD_connection_handle_write; 2066 connection->write_handler = &MHD_connection_handle_write;
2079 connection->idle_handler = &MHD_connection_handle_idle; 2067 connection->idle_handler = &MHD_connection_handle_idle;
diff --git a/src/daemon/connection_https.c b/src/daemon/connection_https.c
index 7504031b..df91af10 100644
--- a/src/daemon/connection_https.c
+++ b/src/daemon/connection_https.c
@@ -87,46 +87,23 @@ MHD_get_connection_info (struct MHD_Connection *connection,
87/** 87/**
88 * This function is called once a secure connection has been marked 88 * This function is called once a secure connection has been marked
89 * for closure. 89 * for closure.
90 * 90 *
91 * @param connection: the connection to close 91 * NOTE: Some code duplication with connection_close_error
92 */ 92 * in connection.c
93static void
94MHD_tls_connection_close (struct MHD_Connection *connection)
95{
96 MHD_gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR);
97 connection->tls_session->internals.read_eof = 1;
98
99 SHUTDOWN (connection->socket_fd, SHUT_RDWR);
100 CLOSE (connection->socket_fd);
101 connection->socket_fd = -1;
102
103 connection->state = MHD_CONNECTION_CLOSED;
104
105 /* call notify_completed callback if one was registered */
106 if (connection->daemon->notify_completed != NULL)
107 connection->daemon->notify_completed (connection->daemon->
108 notify_completed_cls, connection,
109 &connection->client_context,
110 MHD_REQUEST_TERMINATED_COMPLETED_OK);
111}
112
113/**
114 * This function is called once a secure connection has been marked
115 * for closure.
116 * 93 *
117 * @param connection: the connection to close 94 * @param connection: the connection to close
118 * @param termination_code: the termination code with which the notify completed callback function is called. 95 * @param termination_code: the termination code with which the notify completed callback function is called.
119 */ 96 */
120static void 97static void
121MHD_tls_connection_close_err (struct MHD_Connection *connection, 98MHD_tls_connection_close (struct MHD_Connection *connection,
122 enum MHD_RequestTerminationCode 99 enum MHD_RequestTerminationCode
123 termination_code) 100 termination_code)
124{ 101{
102 MHD_gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR);
125 connection->tls_session->internals.read_eof = 1; 103 connection->tls_session->internals.read_eof = 1;
126 SHUTDOWN (connection->socket_fd, SHUT_RDWR); 104 SHUTDOWN (connection->socket_fd, SHUT_RDWR);
127 CLOSE (connection->socket_fd); 105 CLOSE (connection->socket_fd);
128 connection->socket_fd = -1; 106 connection->socket_fd = -1;
129
130 connection->state = MHD_CONNECTION_CLOSED; 107 connection->state = MHD_CONNECTION_CLOSED;
131 if (connection->daemon->notify_completed != NULL) 108 if (connection->daemon->notify_completed != NULL)
132 connection->daemon->notify_completed (connection->daemon-> 109 connection->daemon->notify_completed (connection->daemon->
@@ -135,39 +112,6 @@ MHD_tls_connection_close_err (struct MHD_Connection *connection,
135 termination_code); 112 termination_code);
136} 113}
137 114
138
139/**
140 * @name : MHDS_con_read
141 *
142 * reads data from the TLS record protocol
143 * @param connection: is a %MHD_Connection structure.
144 * @return: number of bytes received and zero on EOF. A negative
145 * error code is returned in case of an error.
146 **/
147static ssize_t
148MHDS_con_read (struct MHD_Connection *connection)
149{
150 /* no special handling when GNUTLS_E_AGAIN is returned since this function is called from within a select loop */
151 ssize_t size = MHD_gnutls_record_recv (connection->tls_session,
152 &connection->read_buffer
153 [connection->read_buffer_offset],
154 connection->read_buffer_size);
155 return size;
156}
157
158static ssize_t
159MHDS_con_write (struct MHD_Connection *connection)
160{
161 ssize_t sent = MHD_gnutls_record_send (connection->tls_session,
162 &connection->write_buffer
163 [connection->
164 write_buffer_send_offset],
165 connection->write_buffer_append_offset
166 -
167 connection->write_buffer_send_offset);
168 return sent;
169}
170
171/** 115/**
172 * This function was created to handle per-connection processing that 116 * This function was created to handle per-connection processing that
173 * has to happen even if the socket cannot be read or written to. All 117 * has to happen even if the socket cannot be read or written to. All
@@ -187,16 +131,14 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
187 MHD_DLOG (connection->daemon, "%s: state: %s\n", 131 MHD_DLOG (connection->daemon, "%s: state: %s\n",
188 __FUNCTION__, MHD_state_to_string (connection->state)); 132 __FUNCTION__, MHD_state_to_string (connection->state));
189#endif 133#endif
190
191 timeout = connection->daemon->connection_timeout; 134 timeout = connection->daemon->connection_timeout;
192 if ((connection->socket_fd != -1) && (timeout != 0) 135 if ((connection->socket_fd != -1) && (timeout != 0)
193 && (time (NULL) - timeout > connection->last_activity)) 136 && (time (NULL) - timeout > connection->last_activity))
194 { 137 {
195 MHD_tls_connection_close_err (connection, 138 MHD_tls_connection_close (connection,
196 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); 139 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
197 return MHD_NO; 140 return MHD_NO;
198 } 141 }
199
200 switch (connection->state) 142 switch (connection->state)
201 { 143 {
202 /* on newly created connections we might reach here before any reply has been received */ 144 /* on newly created connections we might reach here before any reply has been received */
@@ -205,10 +147,11 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
205 /* close connection if necessary */ 147 /* close connection if necessary */
206 case MHD_CONNECTION_CLOSED: 148 case MHD_CONNECTION_CLOSED:
207 if (connection->socket_fd != -1) 149 if (connection->socket_fd != -1)
208 MHD_tls_connection_close (connection); 150 MHD_tls_connection_close (connection,
151 MHD_REQUEST_TERMINATED_COMPLETED_OK);
209 return MHD_NO; 152 return MHD_NO;
210 case MHD_TLS_HANDSHAKE_FAILED: 153 case MHD_TLS_HANDSHAKE_FAILED:
211 MHD_tls_connection_close_err (connection, 154 MHD_tls_connection_close (connection,
212 MHD_TLS_REQUEST_TERMINATED_WITH_ERROR); 155 MHD_TLS_REQUEST_TERMINATED_WITH_ERROR);
213 return MHD_NO; 156 return MHD_NO;
214 /* some HTTP state */ 157 /* some HTTP state */
@@ -293,14 +236,14 @@ MHD_tls_connection_handle_read (struct MHD_Connection *connection)
293 MHD_DLOG (connection->daemon, 236 MHD_DLOG (connection->daemon,
294 "Error: received handshake message out of context\n"); 237 "Error: received handshake message out of context\n");
295#endif 238#endif
296 MHD_tls_connection_close_err (connection, 239 MHD_tls_connection_close (connection,
297 MHD_TLS_REQUEST_TERMINATED_WITH_ERROR); 240 MHD_TLS_REQUEST_TERMINATED_WITH_ERROR);
298 return MHD_NO; 241 return MHD_NO;
299 } 242 }
300 243
301 /* ignore any out of bound change chiper spec messages */ 244 /* ignore any out of bound change chiper spec messages */
302 case GNUTLS_CHANGE_CIPHER_SPEC: 245 case GNUTLS_CHANGE_CIPHER_SPEC:
303 MHD_tls_connection_close_err (connection, 246 MHD_tls_connection_close (connection,
304 MHD_TLS_REQUEST_TERMINATED_WITH_ERROR); 247 MHD_TLS_REQUEST_TERMINATED_WITH_ERROR);
305 return MHD_NO; 248 return MHD_NO;
306 249
@@ -335,8 +278,8 @@ MHD_tls_connection_handle_read (struct MHD_Connection *connection)
335 else if (connection->tls_session->internals.last_alert_level == 278 else if (connection->tls_session->internals.last_alert_level ==
336 GNUTLS_AL_FATAL) 279 GNUTLS_AL_FATAL)
337 { 280 {
338 MHD_tls_connection_close_err (connection, 281 MHD_tls_connection_close (connection,
339 MHD_TLS_REQUEST_TERMINATED_WITH_FATAL_ALERT); 282 MHD_TLS_REQUEST_TERMINATED_WITH_FATAL_ALERT);
340 return MHD_NO; 283 return MHD_NO;
341 } 284 }
342 /* this should never execute */ 285 /* this should never execute */
@@ -400,16 +343,13 @@ MHD_tls_connection_handle_write (struct MHD_Connection *connection)
400 return MHD_NO; 343 return MHD_NO;
401} 344}
402 345
403/* 346/**
404 * set connection callback function to be used through out 347 * Set connection callback function to be used through out
405 * the processing of this secure connection. 348 * the processing of this secure connection.
406 *
407 */ 349 */
408void 350void
409MHD_set_https_calbacks (struct MHD_Connection *connection) 351MHD_set_https_calbacks (struct MHD_Connection *connection)
410{ 352{
411 connection->recv_cls = &MHDS_con_read;
412 connection->send_cls = &MHDS_con_write;
413 connection->read_handler = &MHD_tls_connection_handle_read; 353 connection->read_handler = &MHD_tls_connection_handle_read;
414 connection->write_handler = &MHD_tls_connection_handle_write; 354 connection->write_handler = &MHD_tls_connection_handle_write;
415 connection->idle_handler = &MHD_tls_connection_handle_idle; 355 connection->idle_handler = &MHD_tls_connection_handle_idle;
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index 7911be33..34a94922 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -60,7 +60,65 @@
60#define DEBUG_CONNECT MHD_NO 60#define DEBUG_CONNECT MHD_NO
61 61
62#if HTTPS_SUPPORT 62#if HTTPS_SUPPORT
63/* TODO unite with code in gnutls_priority.c */ 63/**
64 * Note: code duplication with code in gnutls_priority.c
65 *
66 * @return 0
67 */
68static int
69_set_priority (mhd_gtls_priority_st * st, const int *list)
70{
71 int num = 0;
72
73 while ( (list[num] != 0) &&
74 (num < MAX_ALGOS) )
75 num++;
76 st->num_algorithms = num;
77 memcpy(st->priority, list, num * sizeof(int));
78 return 0;
79}
80
81
82/**
83 * Callback for receiving data from the socket.
84 *
85 * @param conn the MHD connection structure
86 * @param other where to write received data to
87 * @param i maximum size of other (in bytes)
88 * @return number of bytes actually received
89 */
90static ssize_t
91recv_tls_adapter (struct MHD_Connection* connection,
92 void *other,
93 size_t i)
94{
95 return MHD_gnutls_record_recv(connection->tls_session,
96 other, i);
97}
98
99/**
100 * Callback for writing data to the socket.
101 *
102 * @param conn the MHD connection structure
103 * @param other data to write
104 * @param i number of bytes to write
105 * @return actual number of bytes written
106 */
107static ssize_t
108send_tls_adapter (struct MHD_Connection* connection,
109 const void *other,
110 size_t i)
111{
112 return MHD_gnutls_record_send(connection->tls_session,
113 other, i);
114}
115
116
117/**
118 * Read and setup our certificate and key.
119 *
120 * @return 0 on success
121 */
64static int 122static int
65MHD_init_daemon_certificate (struct MHD_Daemon *daemon) 123MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
66{ 124{
@@ -132,27 +190,25 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
132} 190}
133 191
134/** 192/**
135 * initialize security aspects of the HTTPS daemon 193 * Initialize security aspects of the HTTPS daemon
194 *
195 * @return 0 on success
136 */ 196 */
137static int 197static int
138MHD_TLS_init (struct MHD_Daemon *daemon) 198MHD_TLS_init (struct MHD_Daemon *daemon)
139{ 199{
140 int ret;
141
142 switch (daemon->cred_type) 200 switch (daemon->cred_type)
143 { 201 {
144 case MHD_GNUTLS_CRD_ANON: 202 case MHD_GNUTLS_CRD_ANON:
145 ret = MHD_gnutls_anon_allocate_server_credentials (&daemon->anon_cred); 203 if ( (0 != MHD_gnutls_anon_allocate_server_credentials (&daemon->anon_cred)) ||
146 ret |= MHD_gnutls_dh_params_init (&daemon->dh_params); 204 (0 != MHD_gnutls_dh_params_init (&daemon->dh_params)) )
147 if (ret != 0)
148 return GNUTLS_E_MEMORY_ERROR; 205 return GNUTLS_E_MEMORY_ERROR;
149 MHD_gnutls_dh_params_generate2 (daemon->dh_params, 1024); 206 MHD_gnutls_dh_params_generate2 (daemon->dh_params, 1024);
150 MHD_gnutls_anon_set_server_dh_params (daemon->anon_cred, 207 MHD_gnutls_anon_set_server_dh_params (daemon->anon_cred,
151 daemon->dh_params); 208 daemon->dh_params);
152 return 0; 209 return 0;
153 case MHD_GNUTLS_CRD_CERTIFICATE: 210 case MHD_GNUTLS_CRD_CERTIFICATE:
154 ret = MHD_gnutls_certificate_allocate_credentials (&daemon->x509_cred); 211 if (0 != MHD_gnutls_certificate_allocate_credentials (&daemon->x509_cred))
155 if (ret != 0)
156 return GNUTLS_E_MEMORY_ERROR; 212 return GNUTLS_E_MEMORY_ERROR;
157 return MHD_init_daemon_certificate (daemon); 213 return MHD_init_daemon_certificate (daemon);
158 default: 214 default:
@@ -164,19 +220,6 @@ MHD_TLS_init (struct MHD_Daemon *daemon)
164 return -1; 220 return -1;
165 } 221 }
166} 222}
167
168static int
169_set_priority (mhd_gtls_priority_st * st, const int *list)
170{
171 int num = 0;
172
173 while ( (list[num] != 0) &&
174 (num < MAX_ALGOS) )
175 num++;
176 st->num_algorithms = num;
177 memcpy(st->priority, list, num * sizeof(int));
178 return 0;
179}
180#endif 223#endif
181 224
182/** 225/**
@@ -292,9 +335,8 @@ MHD_handle_connection (void *data)
292 return NULL; 335 return NULL;
293} 336}
294 337
295#if HTTPS_SUPPORT
296/** 338/**
297 * Callback for receiving data from the socket (for gnutls). 339 * Callback for receiving data from the socket.
298 * 340 *
299 * @param conn the MHD connection structure 341 * @param conn the MHD connection structure
300 * @param other where to write received data to 342 * @param other where to write received data to
@@ -302,19 +344,17 @@ MHD_handle_connection (void *data)
302 * @return number of bytes actually received 344 * @return number of bytes actually received
303 */ 345 */
304static ssize_t 346static ssize_t
305pull_param_adapter (gnutls_transport_ptr_t conn, 347recv_param_adapter (struct MHD_Connection * connection,
306 void *other, 348 void *other,
307 size_t i) 349 size_t i)
308{ 350{
309 struct MHD_Connection * connection = (struct MHD_Connection*) conn;
310
311 if (connection->socket_fd == -1) 351 if (connection->socket_fd == -1)
312 return -1; 352 return -1;
313 return RECV(connection->socket_fd, other, i, MSG_NOSIGNAL); 353 return RECV(connection->socket_fd, other, i, MSG_NOSIGNAL);
314} 354}
315 355
316/** 356/**
317 * Callback for writing data to the socket (for gnutls). 357 * Callback for writing data to the socket.
318 * 358 *
319 * @param conn the MHD connection structure 359 * @param conn the MHD connection structure
320 * @param other data to write 360 * @param other data to write
@@ -322,61 +362,16 @@ pull_param_adapter (gnutls_transport_ptr_t conn,
322 * @return actual number of bytes written 362 * @return actual number of bytes written
323 */ 363 */
324static ssize_t 364static ssize_t
325push_param_adapter (void *conn, 365send_param_adapter (struct MHD_Connection *connection,
326 const void *other, 366 const void *other,
327 size_t i) 367 size_t i)
328{ 368{
329 struct MHD_Connection * connection = (struct MHD_Connection*) conn;
330
331 if (connection->socket_fd == -1) 369 if (connection->socket_fd == -1)
332 return -1; 370 return -1;
333 return SEND(connection->socket_fd, other, i, MSG_NOSIGNAL); 371 return SEND(connection->socket_fd, other, i, MSG_NOSIGNAL);
334} 372}
335 373
336/** 374/**
337 * Handle an individual TLS connection (main function
338 * of the thread handling a TLS connection).
339 */
340static void *
341MHD_TLS_init_connection (void *data)
342{
343 struct MHD_Connection *con = data;
344
345 EXTRA_CHECK (con->state == MHD_CONNECTION_INIT);
346 con->state = MHD_TLS_CONNECTION_INIT;
347 MHD_gnutls_init (&con->tls_session, GNUTLS_SERVER);
348 MHD_gnutls_priority_set (con->tls_session, con->daemon->priority_cache);
349 switch (con->daemon->cred_type)
350 {
351 /* set needed credentials for certificate authentication. */
352 case MHD_GNUTLS_CRD_CERTIFICATE:
353 MHD_gnutls_credentials_set (con->tls_session,
354 MHD_GNUTLS_CRD_CERTIFICATE,
355 con->daemon->x509_cred);
356 break;
357 case MHD_GNUTLS_CRD_ANON:
358 /* set needed credentials for anonymous authentication. */
359 MHD_gnutls_credentials_set (con->tls_session, MHD_GNUTLS_CRD_ANON,
360 con->daemon->anon_cred);
361 MHD_gnutls_dh_set_prime_bits (con->tls_session, 1024);
362 break;
363 default:
364#if HAVE_MESSAGES
365 MHD_DLOG (con->daemon,
366 "Failed to setup TLS credentials: unknown credential type %d\n",
367 con->daemon->cred_type);
368#endif
369 abort();
370 }
371 MHD_gnutls_transport_set_ptr (con->tls_session,
372 (gnutls_transport_ptr_t) con);
373 MHD_gnutls_transport_set_pull_function(con->tls_session, &pull_param_adapter);
374 MHD_gnutls_transport_set_push_function(con->tls_session, &push_param_adapter);
375 return MHD_handle_connection (data);
376}
377#endif
378
379/**
380 * Accept an incoming connection and create the MHD_Connection object for 375 * Accept an incoming connection and create the MHD_Connection object for
381 * it. This function also enforces policy by way of checking with the 376 * it. This function also enforces policy by way of checking with the
382 * accept policy callback. 377 * accept policy callback.
@@ -519,19 +514,52 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
519 514
520 /* set default connection handlers */ 515 /* set default connection handlers */
521 MHD_set_http_calbacks (connection); 516 MHD_set_http_calbacks (connection);
517 connection->recv_cls = &recv_param_adapter;
518 connection->send_cls = &send_param_adapter;
522#if HTTPS_SUPPORT 519#if HTTPS_SUPPORT
523 if (0 != (daemon->options & MHD_USE_SSL)) 520 if (0 != (daemon->options & MHD_USE_SSL))
524 MHD_set_https_calbacks (connection); 521 {
522 connection->recv_cls = &recv_tls_adapter;
523 connection->send_cls = &send_tls_adapter;
524 connection->state = MHD_TLS_CONNECTION_INIT;
525 MHD_set_https_calbacks (connection);
526 MHD_gnutls_init (&connection->tls_session, GNUTLS_SERVER);
527 MHD_gnutls_priority_set (connection->tls_session, connection->daemon->priority_cache);
528 switch (connection->daemon->cred_type)
529 {
530 /* set needed credentials for certificate authentication. */
531 case MHD_GNUTLS_CRD_CERTIFICATE:
532 MHD_gnutls_credentials_set (connection->tls_session,
533 MHD_GNUTLS_CRD_CERTIFICATE,
534 connection->daemon->x509_cred);
535 break;
536 case MHD_GNUTLS_CRD_ANON:
537 /* set needed credentials for anonymous authentication. */
538 MHD_gnutls_credentials_set (connection->tls_session, MHD_GNUTLS_CRD_ANON,
539 connection->daemon->anon_cred);
540 MHD_gnutls_dh_set_prime_bits (connection->tls_session, 1024);
541 break;
542 default:
543#if HAVE_MESSAGES
544 MHD_DLOG (connection->daemon,
545 "Failed to setup TLS credentials: unknown credential type %d\n",
546 connection->daemon->cred_type);
547#endif
548 abort();
549 }
550 MHD_gnutls_transport_set_ptr (connection->tls_session,
551 (gnutls_transport_ptr_t) connection);
552 MHD_gnutls_transport_set_pull_function(connection->tls_session,
553 (mhd_gtls_pull_func) &recv_param_adapter);
554 MHD_gnutls_transport_set_push_function(connection->tls_session,
555 (mhd_gtls_push_func) &send_param_adapter);
556 }
525#endif 557#endif
526 558
527 /* attempt to create handler thread */ 559 /* attempt to create handler thread */
528 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 560 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
529 { 561 {
530 res_thread_create = pthread_create (&connection->pid, NULL, 562 res_thread_create = pthread_create (&connection->pid, NULL,
531#if HTTPS_SUPPORT
532 (0 != (daemon->options & MHD_USE_SSL)) ?
533 &MHD_TLS_init_connection :
534#endif
535 &MHD_handle_connection, 563 &MHD_handle_connection,
536 connection); 564 connection);
537 if (res_thread_create != 0) 565 if (res_thread_create != 0)
@@ -855,7 +883,6 @@ MHD_start_daemon_va (unsigned int options,
855 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT; 883 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
856 retVal->pool_size = MHD_POOL_SIZE_DEFAULT; 884 retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
857 retVal->connection_timeout = 0; /* no timeout */ 885 retVal->connection_timeout = 0; /* no timeout */
858
859#if HTTPS_SUPPORT 886#if HTTPS_SUPPORT
860 if (options & MHD_USE_SSL) 887 if (options & MHD_USE_SSL)
861 { 888 {
@@ -931,13 +958,13 @@ MHD_start_daemon_va (unsigned int options,
931 if ((opt >= MHD_OPTION_HTTPS_KEY_PATH) && 958 if ((opt >= MHD_OPTION_HTTPS_KEY_PATH) &&
932 (opt <= MHD_OPTION_TLS_COMP_ALGO)) 959 (opt <= MHD_OPTION_TLS_COMP_ALGO))
933 { 960 {
934 fprintf (stderr, 961 FPRINTF (stderr,
935 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n", 962 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
936 opt); 963 opt);
937 } 964 }
938 else 965 else
939 { 966 {
940 fprintf (stderr, 967 FPRINTF (stderr,
941 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n", 968 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
942 opt); 969 opt);
943 } 970 }
@@ -954,7 +981,7 @@ MHD_start_daemon_va (unsigned int options,
954 { 981 {
955#if HAVE_MESSAGES 982#if HAVE_MESSAGES
956 if ((options & MHD_USE_DEBUG) != 0) 983 if ((options & MHD_USE_DEBUG) != 0)
957 fprintf (stderr, "Call to socket failed: %s\n", STRERROR (errno)); 984 FPRINTF (stderr, "Call to socket failed: %s\n", STRERROR (errno));
958#endif 985#endif
959 free (retVal); 986 free (retVal);
960 return NULL; 987 return NULL;
@@ -965,7 +992,7 @@ MHD_start_daemon_va (unsigned int options,
965 &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0) 992 &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
966 { 993 {
967#if HAVE_MESSAGES 994#if HAVE_MESSAGES
968 fprintf (stderr, "setsockopt failed: %s\n", STRERROR (errno)); 995 FPRINTF (stderr, "setsockopt failed: %s\n", STRERROR (errno));
969#endif 996#endif
970 } 997 }
971 998
@@ -996,7 +1023,7 @@ MHD_start_daemon_va (unsigned int options,
996 { 1023 {
997#if HAVE_MESSAGES 1024#if HAVE_MESSAGES
998 if ((options & MHD_USE_DEBUG) != 0) 1025 if ((options & MHD_USE_DEBUG) != 0)
999 fprintf (stderr, 1026 FPRINTF (stderr,
1000 "Failed to bind to port %u: %s\n", port, STRERROR (errno)); 1027 "Failed to bind to port %u: %s\n", port, STRERROR (errno));
1001#endif 1028#endif
1002 CLOSE (socket_fd); 1029 CLOSE (socket_fd);
@@ -1009,7 +1036,7 @@ MHD_start_daemon_va (unsigned int options,
1009 { 1036 {
1010#if HAVE_MESSAGES 1037#if HAVE_MESSAGES
1011 if ((options & MHD_USE_DEBUG) != 0) 1038 if ((options & MHD_USE_DEBUG) != 0)
1012 fprintf (stderr, 1039 FPRINTF (stderr,
1013 "Failed to listen for connections: %s\n", STRERROR (errno)); 1040 "Failed to listen for connections: %s\n", STRERROR (errno));
1014#endif 1041#endif
1015 CLOSE (socket_fd); 1042 CLOSE (socket_fd);
@@ -1019,7 +1046,8 @@ MHD_start_daemon_va (unsigned int options,
1019 1046
1020#if HTTPS_SUPPORT 1047#if HTTPS_SUPPORT
1021 /* initialize HTTPS daemon certificate aspects & send / recv functions */ 1048 /* initialize HTTPS daemon certificate aspects & send / recv functions */
1022 if ((options & MHD_USE_SSL) && MHD_TLS_init (retVal)) 1049 if ( (0 != (options & MHD_USE_SSL)) &&
1050 (0 != MHD_TLS_init (retVal)) )
1023 { 1051 {
1024#if HAVE_MESSAGES 1052#if HAVE_MESSAGES
1025 MHD_DLOG (retVal, "Failed to initialize TLS support\n"); 1053 MHD_DLOG (retVal, "Failed to initialize TLS support\n");
diff --git a/src/daemon/https/tls/gnutls_buffers.c b/src/daemon/https/tls/gnutls_buffers.c
index da44e87c..16be8011 100644
--- a/src/daemon/https/tls/gnutls_buffers.c
+++ b/src/daemon/https/tls/gnutls_buffers.c
@@ -487,6 +487,7 @@ mhd_gtls_io_read_buffered (mhd_gtls_session_t session, opaque ** iptr,
487 if (sizeOfPtr > MAX_RECV_SIZE || sizeOfPtr == 0) 487 if (sizeOfPtr > MAX_RECV_SIZE || sizeOfPtr == 0)
488 { 488 {
489 gnutls_assert (); /* internal error */ 489 gnutls_assert (); /* internal error */
490 printf("AT %u\n", __LINE__);
490 return GNUTLS_E_INVALID_REQUEST; 491 return GNUTLS_E_INVALID_REQUEST;
491 } 492 }
492 493
@@ -537,6 +538,7 @@ mhd_gtls_io_read_buffered (mhd_gtls_session_t session, opaque ** iptr,
537 > MAX_RECV_SIZE) 538 > MAX_RECV_SIZE)
538 { 539 {
539 gnutls_assert (); /* internal error */ 540 gnutls_assert (); /* internal error */
541 printf("AT %u\n", __LINE__);
540 return GNUTLS_E_INVALID_REQUEST; 542 return GNUTLS_E_INVALID_REQUEST;
541 } 543 }
542 544
@@ -549,12 +551,14 @@ mhd_gtls_io_read_buffered (mhd_gtls_session_t session, opaque ** iptr,
549 if (session->internals.record_recv_buffer.data == NULL) 551 if (session->internals.record_recv_buffer.data == NULL)
550 { 552 {
551 gnutls_assert (); 553 gnutls_assert ();
554 printf("AT %u\n", __LINE__);
552 return GNUTLS_E_MEMORY_ERROR; 555 return GNUTLS_E_MEMORY_ERROR;
553 } 556 }
554 557
555 buf_pos = session->internals.record_recv_buffer.length; 558 buf_pos = session->internals.record_recv_buffer.length;
556 buf = session->internals.record_recv_buffer.data; 559 buf = session->internals.record_recv_buffer.data;
557 *iptr = buf; 560 *iptr = buf;
561 printf("AT %u\n", __LINE__);
558 562
559 /* READ DATA - but leave RCVLOWAT bytes in the kernel buffer. */ 563 /* READ DATA - but leave RCVLOWAT bytes in the kernel buffer. */
560 if (recvdata - recvlowat > 0) 564 if (recvdata - recvlowat > 0)
@@ -566,6 +570,7 @@ mhd_gtls_io_read_buffered (mhd_gtls_session_t session, opaque ** iptr,
566 */ 570 */
567 if (ret < 0 && MHD_gtls_error_is_fatal (ret) == 0) 571 if (ret < 0 && MHD_gtls_error_is_fatal (ret) == 0)
568 { 572 {
573 printf("AT %u\n", __LINE__);
569 return ret; 574 return ret;
570 } 575 }
571 } 576 }
@@ -593,6 +598,7 @@ mhd_gtls_io_read_buffered (mhd_gtls_session_t session, opaque ** iptr,
593 598
594 if (ret2 < 0 && MHD_gtls_error_is_fatal (ret2) == 0) 599 if (ret2 < 0 && MHD_gtls_error_is_fatal (ret2) == 0)
595 { 600 {
601 printf("AT %u\n", __LINE__);
596 return ret2; 602 return ret2;
597 } 603 }
598 604
@@ -612,6 +618,7 @@ mhd_gtls_io_read_buffered (mhd_gtls_session_t session, opaque ** iptr,
612 { 618 {
613 gnutls_assert (); 619 gnutls_assert ();
614 /* that's because they are initialized to 0 */ 620 /* that's because they are initialized to 0 */
621 printf("AT %u\n", __LINE__);
615 return MIN (ret, ret2); 622 return MIN (ret, ret2);
616 } 623 }
617 624
@@ -620,12 +627,14 @@ mhd_gtls_io_read_buffered (mhd_gtls_session_t session, opaque ** iptr,
620 if (ret > 0 && ret < recvlowat) 627 if (ret > 0 && ret < recvlowat)
621 { 628 {
622 gnutls_assert (); 629 gnutls_assert ();
630 printf("AT %u\n", __LINE__);
623 return GNUTLS_E_AGAIN; 631 return GNUTLS_E_AGAIN;
624 } 632 }
625 633
626 if (ret == 0) 634 if (ret == 0)
627 { /* EOF */ 635 { /* EOF */
628 gnutls_assert (); 636 gnutls_assert ();
637 printf("AT %u\n", __LINE__);
629 return 0; 638 return 0;
630 } 639 }
631 640
@@ -635,10 +644,12 @@ mhd_gtls_io_read_buffered (mhd_gtls_session_t session, opaque ** iptr,
635 { 644 {
636 /* Short Read */ 645 /* Short Read */
637 gnutls_assert (); 646 gnutls_assert ();
647 printf("AT %u\n", __LINE__);
638 return GNUTLS_E_AGAIN; 648 return GNUTLS_E_AGAIN;
639 } 649 }
640 else 650 else
641 { 651 {
652 printf("AT %u\n", __LINE__);
642 return ret; 653 return ret;
643 } 654 }
644} 655}
diff --git a/src/daemon/internal.h b/src/daemon/internal.h
index c2d6ab0b..76c17dbc 100644
--- a/src/daemon/internal.h
+++ b/src/daemon/internal.h
@@ -305,6 +305,33 @@ enum MHD_CONNECTION_STATE
305char *MHD_state_to_string (enum MHD_CONNECTION_STATE state); 305char *MHD_state_to_string (enum MHD_CONNECTION_STATE state);
306#endif 306#endif
307 307
308/**
309 * Function to receive plaintext data.
310 *
311 * @param conn the connection struct
312 * @param write_to where to write received data
313 * @param max_bytes maximum number of bytes to receive
314 * @return number of bytes written to write_to
315 */
316typedef ssize_t (*ReceiveCallback)(struct MHD_Connection * conn,
317 void * write_to,
318 size_t max_bytes);
319
320
321/**
322 * Function to transmit plaintext data.
323 *
324 * @param conn the connection struct
325 * @param read_from where to read data to transmit
326 * @param max_bytes maximum number of bytes to transmit
327 * @return number of bytes transmitted
328 */
329typedef ssize_t (*TransmitCallback)(struct MHD_Connection * conn,
330 const void * write_to,
331 size_t max_bytes);
332
333
334
308struct MHD_Connection 335struct MHD_Connection
309{ 336{
310 337
@@ -538,13 +565,9 @@ struct MHD_Connection
538 565
539 int (*idle_handler) (struct MHD_Connection * connection); 566 int (*idle_handler) (struct MHD_Connection * connection);
540 567
541 /** 568 ReceiveCallback recv_cls;
542 * function pointers to the appropriate send & receive funtions 569
543 * according to whether this is a HTTPS / HTTP daemon 570 TransmitCallback send_cls;
544 */
545 ssize_t (*recv_cls) (struct MHD_Connection * connection);
546
547 ssize_t (*send_cls) (struct MHD_Connection * connection);
548 571
549#if HTTPS_SUPPORT 572#if HTTPS_SUPPORT
550 /* TODO rename as this might be an SSL connection */ 573 /* TODO rename as this might be an SSL connection */