diff options
Diffstat (limited to 'src/daemon/daemon.c')
-rw-r--r-- | src/daemon/daemon.c | 202 |
1 files changed, 115 insertions, 87 deletions
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 | */ | ||
68 | static 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 | */ | ||
90 | static ssize_t | ||
91 | recv_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 | */ | ||
107 | static ssize_t | ||
108 | send_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 | */ | ||
64 | static int | 122 | static int |
65 | MHD_init_daemon_certificate (struct MHD_Daemon *daemon) | 123 | MHD_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 | */ |
137 | static int | 197 | static int |
138 | MHD_TLS_init (struct MHD_Daemon *daemon) | 198 | MHD_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 | |||
168 | static 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 | */ |
304 | static ssize_t | 346 | static ssize_t |
305 | pull_param_adapter (gnutls_transport_ptr_t conn, | 347 | recv_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 | */ |
324 | static ssize_t | 364 | static ssize_t |
325 | push_param_adapter (void *conn, | 365 | send_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 | */ | ||
340 | static void * | ||
341 | MHD_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"); |