libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 67851b280ee6c5b9fcc4f82402c1dad12887e224
parent 58d06b22557a9d06dfeff5975c8241def4f88680
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 25 Jul 2010 07:17:26 +0000

GHM hacking

Diffstat:
Msrc/daemon/connection.c | 13++++++++-----
Msrc/daemon/connection_https.c | 194++++++++++++++++++-------------------------------------------------------------
Msrc/daemon/daemon.c | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/daemon/internal.c | 6------
Msrc/daemon/internal.h | 20++++++--------------
Msrc/include/microhttpd.h | 16++--------------
Msrc/testcurl/https/Makefile.am | 11+++++++++++
Msrc/testcurl/https/mhds_get_test.c | 8+++++++-
Asrc/testcurl/https/mhds_get_test_select.c | 243+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/testcurl/https/tls_daemon_options_test.c | 16++++------------
Msrc/testcurl/https/tls_thread_mode_test.c | 5++++-
11 files changed, 390 insertions(+), 220 deletions(-)

diff --git a/src/daemon/connection.c b/src/daemon/connection.c @@ -778,12 +778,17 @@ MHD_connection_get_pollfd(struct MHD_Connection *connection, struct MHD_Pollfd * #endif switch (connection->state) { +#if HTTPS_SUPPORT + case MHD_TLS_CONNECTION_INIT: + if (0 == gnutls_record_get_direction (connection->tls_session)) + p->events |= MHD_POLL_ACTION_IN; + else + p->events |= MHD_POLL_ACTION_OUT; + break; +#endif case MHD_CONNECTION_INIT: case MHD_CONNECTION_URL_RECEIVED: case MHD_CONNECTION_HEADER_PART_RECEIVED: -#if HTTPS_SUPPORT - case MHD_TLS_CONNECTION_INIT: -#endif /* while reading headers, we always grow the read buffer if needed, no size-check required */ if ((connection->read_closed) && @@ -1866,8 +1871,6 @@ MHD_connection_handle_write (struct MHD_Connection *connection) connection_close_error (connection); return MHD_NO; case MHD_TLS_CONNECTION_INIT: - case MHD_TLS_HELLO_REQUEST: - case MHD_TLS_HANDSHAKE_FAILED: EXTRA_CHECK (0); break; default: diff --git a/src/daemon/connection_https.c b/src/daemon/connection_https.c @@ -47,8 +47,7 @@ static void MHD_tls_connection_close (struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code) { - gnutls_bye (connection->tls_session, GNUTLS_SHUT_WR); - /* connection->tls_session->internals.read_eof = 1; // FIXME_GHM: needed? */ + gnutls_bye (connection->tls_session, GNUTLS_SHUT_RDWR); MHD_connection_close (connection, termination_code); } @@ -90,26 +89,12 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection) MHD_tls_connection_close (connection, MHD_REQUEST_TERMINATED_COMPLETED_OK); return MHD_NO; - case MHD_TLS_HANDSHAKE_FAILED: - MHD_tls_connection_close (connection, - MHD_REQUEST_TERMINATED_WITH_ERROR); - return MHD_NO; - /* some HTTP state */ default: return MHD_connection_handle_idle (connection); } return MHD_YES; } -/* FIXME_GHM: this is digging into gnutls/SSL internals - that is likely wrong... */ -/* Record Protocol */ -typedef enum content_type_t -{ - GNUTLS_CHANGE_CIPHER_SPEC = 20, GNUTLS_ALERT, - GNUTLS_HANDSHAKE, GNUTLS_APPLICATION_DATA, - GNUTLS_INNER_APPLICATION = 24 -} content_type_t; /** * This function handles a particular SSL/TLS connection when @@ -132,142 +117,36 @@ static int MHD_tls_connection_handle_read (struct MHD_Connection *connection) { int ret; - unsigned char msg_type; connection->last_activity = time (NULL); - if (connection->state == MHD_CONNECTION_CLOSED || - connection->state == MHD_TLS_HANDSHAKE_FAILED) - return MHD_NO; - -#if DEBUG_STATES - MHD_DLOG (connection->daemon, "%s: state: %s\n", - __FUNCTION__, MHD_state_to_string (connection->state)); -#endif - - /* discover content type */ - if (RECV (connection->socket_fd, &msg_type, 1, MSG_PEEK) == -1) + if (connection->state == MHD_TLS_CONNECTION_INIT) { -#if HAVE_MESSAGES - MHD_DLOG (connection->daemon, "Failed to peek into TLS content type\n"); -#endif - return MHD_NO; - } - - switch (msg_type) - { - /* check for handshake messages first */ - case GNUTLS_HANDSHAKE: - /* negotiate handshake only while in INIT & HELLO_REQUEST states */ - if (connection->state == MHD_TLS_CONNECTION_INIT || - connection->state == MHD_TLS_HELLO_REQUEST) - { - ret = gnutls_handshake (connection->tls_session); - if (ret == 0) - { - /* set connection state to enable HTTP processing */ - connection->state = MHD_CONNECTION_INIT; - break; - } - /* set connection as closed */ - else - { -#if HAVE_MESSAGES - MHD_DLOG (connection->daemon, - "Error: Handshake has failed (%d)\n", ret); -#endif - connection->state = MHD_TLS_HANDSHAKE_FAILED; - return MHD_NO; - } - } - /* a handshake message has been received out of bound */ - else - { -#if HAVE_MESSAGES - MHD_DLOG (connection->daemon, - "Error: received handshake message out of context\n"); -#endif - MHD_tls_connection_close (connection, - MHD_REQUEST_TERMINATED_WITH_ERROR); - return MHD_NO; - } - - /* ignore any out of bound change chiper spec messages */ - case GNUTLS_CHANGE_CIPHER_SPEC: - MHD_tls_connection_close (connection, - MHD_REQUEST_TERMINATED_WITH_ERROR); - return MHD_NO; - - case GNUTLS_ALERT: -#if FIXME_GHM - /* - * this call of MHD_gtls_recv_int expects 0 bytes read. - * done to decrypt alert message - */ - gnutls_recv_int (connection->tls_session, GNUTLS_ALERT, - GNUTLS_HANDSHAKE_FINISHED, 0, 0); - /* CLOSE_NOTIFY */ - if (connection->tls_session->internals.last_alert == - GNUTLS_A_CLOSE_NOTIFY) - { - connection->state = MHD_CONNECTION_CLOSED; - return MHD_YES; - } - /* non FATAL or WARNING */ - else - if (connection->tls_session->internals.last_alert_level != - GNUTLS_AL_FATAL) - { -#if HAVE_MESSAGES - MHD_DLOG (connection->daemon, - "Received TLS alert: %s\n", - MHD__gnutls_alert_get_name ((int) - connection->tls_session-> - internals.last_alert)); -#endif - return MHD_YES; - } - /* FATAL */ - else if (connection->tls_session->internals.last_alert_level == - GNUTLS_AL_FATAL) - { - MHD_tls_connection_close (connection, - MHD_REQUEST_TERMINATED_WITH_ERROR); - return MHD_NO; - } - /* this should never execute */ - else - { -#if HAVE_MESSAGES - MHD_DLOG (connection->daemon, - "Received unrecognized alert: %d\n", - connection->tls_session->internals.last_alert); -#endif - return MHD_NO; - } -#endif - - - /* forward application level content to MHD */ - case GNUTLS_APPLICATION_DATA: - return MHD_connection_handle_read (connection); - case GNUTLS_INNER_APPLICATION: - break; - default: + ret = gnutls_handshake (connection->tls_session); + if (ret == GNUTLS_E_SUCCESS) + { + /* set connection state to enable HTTP processing */ + connection->state = MHD_CONNECTION_INIT; + return MHD_YES; + } + if ( (ret == GNUTLS_E_AGAIN) || + (ret == GNUTLS_E_INTERRUPTED) ) + { + /* handshake not done */ + return MHD_YES; + } + /* handshake failed */ #if HAVE_MESSAGES MHD_DLOG (connection->daemon, - "Error: unrecognized TLS message type: %d, connection state: %s. l: %d, f: %s\n", - msg_type, MHD_state_to_string (connection->state), __LINE__, - __FUNCTION__); + "Error: received handshake message out of context\n"); #endif - /* close connection upon reception of unrecognized message type */ MHD_tls_connection_close (connection, - MHD_REQUEST_TERMINATED_WITH_ERROR); + MHD_REQUEST_TERMINATED_WITH_ERROR); return MHD_NO; } - - return MHD_YES; + return MHD_connection_handle_read (connection); } + /** * This function was created to handle writes to sockets when it has * been determined that the socket can be written to. This function @@ -280,23 +159,38 @@ MHD_tls_connection_handle_read (struct MHD_Connection *connection) static int MHD_tls_connection_handle_write (struct MHD_Connection *connection) { - connection->last_activity = time (NULL); + int ret; + connection->last_activity = time (NULL); #if DEBUG_STATES MHD_DLOG (connection->daemon, "%s: state: %s\n", __FUNCTION__, MHD_state_to_string (connection->state)); #endif - - switch (connection->state) + if (connection->state == MHD_TLS_CONNECTION_INIT) { - case MHD_CONNECTION_CLOSED: - case MHD_TLS_HANDSHAKE_FAILED: + ret = gnutls_handshake (connection->tls_session); + if (ret == GNUTLS_E_SUCCESS) + { + /* set connection state to enable HTTP processing */ + connection->state = MHD_CONNECTION_INIT; + return MHD_YES; + } + if ( (ret == GNUTLS_E_AGAIN) || + (ret == GNUTLS_E_INTERRUPTED) ) + { + /* handshake not done */ + return MHD_YES; + } + /* handshake failed */ +#if HAVE_MESSAGES + MHD_DLOG (connection->daemon, + "Error: received handshake message out of context\n"); +#endif + MHD_tls_connection_close (connection, + MHD_REQUEST_TERMINATED_WITH_ERROR); return MHD_NO; - /* some HTTP connection state */ - default: - return MHD_connection_handle_write (connection); } - return MHD_NO; + return MHD_connection_handle_write (connection); } /** diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c @@ -626,6 +626,43 @@ send_param_adapter (struct MHD_Connection *connection, return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT); } + +#if HTTPS_SUPPORT +/** + * Set if a socket should use non-blocking IO. + * @param fd socket + */ +static void +socket_set_nonblocking (int fd) +{ +#if MINGW + u_long mode; + mode = 1; + if (ioctlsocket (fd, FIONBIO, &mode) == SOCKET_ERROR) + { + SetErrnoFromWinsockError (WSAGetLastError ()); +#if HAVE_MESSAGES + FPRINTF(stderr, "Failed to make socket non-blocking: %s\n", + STRERROR (errno)); +#endif + } +#else + + /* not MINGW */ + int flags = fcntl (fd, F_GETFL); + if ( (flags == -1) || + (0 != fcntl (fd, F_SETFL, flags | O_NONBLOCK)) ) + { +#if HAVE_MESSAGES + FPRINTF(stderr, "Failed to make socket non-blocking: %s\n", + STRERROR (errno)); +#endif + } +#endif +} +#endif + + /** * Accept an incoming connection and create the MHD_Connection object for * it. This function also enforces policy by way of checking with the @@ -765,13 +802,20 @@ MHD_accept_connection (struct MHD_Daemon *daemon) connection->state = MHD_TLS_CONNECTION_INIT; MHD_set_https_calbacks (connection); gnutls_init (&connection->tls_session, GNUTLS_SERVER); + gnutls_priority_set (connection->tls_session, + daemon->priority_cache); + if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) + { + /* use non-blocking IO for gnutls */ + socket_set_nonblocking (connection->socket_fd); + } switch (connection->daemon->cred_type) { /* set needed credentials for certificate authentication. */ case GNUTLS_CRD_CERTIFICATE: gnutls_credentials_set (connection->tls_session, GNUTLS_CRD_CERTIFICATE, - connection->daemon->x509_cred); + connection->daemon->x509_cred); break; default: #if HAVE_MESSAGES @@ -1199,6 +1243,9 @@ parse_options_va (struct MHD_Daemon *daemon, enum MHD_OPTION opt; struct MHD_OptionItem *oa; unsigned int i; +#if HTTPS_SUPPORT + int ret; +#endif while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION))) { @@ -1241,16 +1288,6 @@ parse_options_va (struct MHD_Daemon *daemon, } break; #if HTTPS_SUPPORT - case MHD_OPTION_PROTOCOL_VERSION: - FPRINTF (stderr, - "Protocol version setting currently not supported.\n"); -#if HAVE_MESSAGES - else - FPRINTF (stderr, - "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", - opt); -#endif - break; case MHD_OPTION_HTTPS_MEM_KEY: if (daemon->options & MHD_USE_SSL) daemon->https_mem_key = va_arg (ap, const char *); @@ -1272,14 +1309,17 @@ parse_options_va (struct MHD_Daemon *daemon, #endif break; case MHD_OPTION_CIPHER_ALGORITHM: - FPRINTF (stderr, - "CIPHER setting currently not supported\n"); + ret = gnutls_priority_init (&daemon->priority_cache, + va_arg (ap, const char*), + NULL); #if HAVE_MESSAGES - else + if (ret != GNUTLS_E_SUCCESS) FPRINTF (stderr, - "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", - opt); + "gnutls unhappy: %s\n", + gnutls_strerror (ret)); #endif + if (ret != GNUTLS_E_SUCCESS) + return MHD_NO; break; #endif case MHD_OPTION_EXTERNAL_LOGGER: @@ -1333,7 +1373,6 @@ parse_options_va (struct MHD_Daemon *daemon, case MHD_OPTION_SOCK_ADDR: case MHD_OPTION_HTTPS_MEM_KEY: case MHD_OPTION_HTTPS_MEM_CERT: - case MHD_OPTION_PROTOCOL_VERSION: case MHD_OPTION_CIPHER_ALGORITHM: case MHD_OPTION_ARRAY: if (MHD_YES != parse_options (daemon, @@ -1421,6 +1460,11 @@ MHD_start_daemon_va (unsigned int options, if (retVal == NULL) return NULL; memset (retVal, 0, sizeof (struct MHD_Daemon)); +#if HTTPS_SUPPORT + gnutls_priority_init (&retVal->priority_cache, + "NORMAL", + NULL); +#endif retVal->options = (enum MHD_OPTION)options; retVal->port = port; retVal->apc = apc; diff --git a/src/daemon/internal.c b/src/daemon/internal.c @@ -77,12 +77,6 @@ MHD_state_to_string (enum MHD_CONNECTION_STATE state) return "closed"; case MHD_TLS_CONNECTION_INIT: return "secure connection init"; - case MHD_TLS_HELLO_REQUEST: - return "secure hello request"; - case MHD_TLS_HANDSHAKE_FAILED: - return "secure handshake failed"; - case MHD_TLS_HANDSHAKE_COMPLETE: - return "secure handshake _complete"; default: return "unrecognized connection state"; } diff --git a/src/daemon/internal.h b/src/daemon/internal.h @@ -345,20 +345,7 @@ enum MHD_CONNECTION_STATE * Handshake messages will be processed in this state & while * in the 'MHD_TLS_HELLO_REQUEST' state */ - MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_CLOSED + 1, - - /** - * This state indicates the server has send a 'Hello Request' to - * the client & a renegotiation of the handshake is in progress. - * - * Handshake messages will processed in this state & while - * in the 'MHD_TLS_CONNECTION_INIT' state - */ - MHD_TLS_HELLO_REQUEST, - - MHD_TLS_HANDSHAKE_FAILED, - - MHD_TLS_HANDSHAKE_COMPLETE + MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_CLOSED + 1 }; @@ -806,6 +793,11 @@ struct MHD_Daemon #if HTTPS_SUPPORT /** + * Desired cipher algorithms. + */ + gnutls_priority_t priority_cache; + + /** * What kind of credentials are we offering * for SSL/TLS? */ diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -418,20 +418,8 @@ enum MHD_OPTION MHD_OPTION_CRED_TYPE = 10, /** - * SSL/TLS protocol version. - * - * Memory pointer to a zero (MHD_GNUTLS_PROTOCOL_END) terminated - * (const) array of 'enum MHD_GNUTLS_Protocol' values representing the - * protocol versions to this server should support. Unsupported - * requests will be droped by the server. - */ - MHD_OPTION_PROTOCOL_VERSION = 11, - - /** - * Memory pointer to a zero (MHD_GNUTLS_CIPHER_UNKNOWN) - * terminated (const) array of 'enum MHD_GNUTLS_CipherAlgorithm' - * representing the cipher priority order to which the HTTPS - * daemon should adhere. + * Memory pointer to a "const char*" specifying the + * cipher algorithm (default: "NORMAL"). */ MHD_OPTION_CIPHER_ALGORITHM = 12, diff --git a/src/testcurl/https/Makefile.am b/src/testcurl/https/Makefile.am @@ -14,6 +14,7 @@ check_PROGRAMS = \ tls_authentication_test \ mhds_multi_daemon_test \ mhds_get_test \ + mhds_get_test_select \ mhds_session_info_test \ tls_thread_mode_test \ tls_multi_thread_mode_test \ @@ -28,6 +29,7 @@ TESTS = \ tls_daemon_options_test \ mhds_multi_daemon_test \ mhds_get_test \ + mhds_get_test_select \ mhds_session_info_test \ tls_thread_mode_test \ tls_multi_thread_mode_test \ @@ -116,3 +118,12 @@ mhds_get_test_LDADD = \ $(top_builddir)/src/testcurl/libcurl_version_check.a \ $(top_builddir)/src/daemon/libmicrohttpd.la \ @LIBCURL@ + + +mhds_get_test_select_SOURCES = \ + mhds_get_test_select.c \ + tls_test_common.c +mhds_get_test_select_LDADD = \ + $(top_builddir)/src/testcurl/libcurl_version_check.a \ + $(top_builddir)/src/daemon/libmicrohttpd.la \ + @LIBCURL@ diff --git a/src/testcurl/https/mhds_get_test.c b/src/testcurl/https/mhds_get_test.c @@ -29,6 +29,7 @@ #include <limits.h> #include <sys/stat.h> #include <curl/curl.h> +#include <gcrypt.h> #include "tls_test_common.h" int curl_check_version (const char *req_version, ...); @@ -89,6 +90,8 @@ test_secure_get (FILE * test_fd, char *cipher_suite, int proto_version) return ret; } +GCRY_THREAD_OPTION_PTHREAD_IMPL; + int main (int argc, char *const *argv) { @@ -96,11 +99,14 @@ main (int argc, char *const *argv) unsigned int errorCount = 0; /* gnutls_global_set_log_level(11); */ - if (curl_check_version (MHD_REQ_CURL_VERSION, MHD_REQ_CURL_OPENSSL_VERSION)) { return -1; } + gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + + if (!gcry_check_version (GCRYPT_VERSION)) + abort (); if ((test_fd = setup_test_file ()) == NULL) { diff --git a/src/testcurl/https/mhds_get_test_select.c b/src/testcurl/https/mhds_get_test_select.c @@ -0,0 +1,243 @@ +/* + This file is part of libmicrohttpd + (C) 2007 Christian Grothoff + + libmicrohttpd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + libmicrohttpd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libmicrohttpd; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ + +/** + * @file mhds_get_test.c + * @brief Testcase for libmicrohttpd HTTPS GET operations + * @author Sagie Amir + */ + +#include "platform.h" +#include "microhttpd.h" +#include <limits.h> +#include <sys/stat.h> +#include <curl/curl.h> +#include <gcrypt.h> +#include "tls_test_common.h" + +int curl_check_version (const char *req_version, ...); +extern const char srv_key_pem[]; +extern const char srv_self_signed_cert_pem[]; +extern const char srv_signed_cert_pem[]; +extern const char srv_signed_key_pem[]; + +static int oneone; + +static int +ahc_echo (void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, size_t *upload_data_size, + void **unused) +{ + static int ptr; + const char *me = cls; + struct MHD_Response *response; + int ret; + + if (0 != strcmp (me, method)) + return MHD_NO; /* unexpected method */ + if (&ptr != *unused) + { + *unused = &ptr; + fprintf (stderr, "received %s\n", method); + return MHD_YES; + } + *unused = NULL; + response = MHD_create_response_from_data (strlen (url), + (void *) url, MHD_NO, MHD_YES); + ret = MHD_queue_response (connection, MHD_HTTP_OK, response); + fprintf (stderr, "sending reply\n"); + MHD_destroy_response (response); + if (ret == MHD_NO) + abort (); + return ret; +} + +static int +testExternalGet () +{ + struct MHD_Daemon *d; + CURL *c; + char buf[2048]; + struct CBC cbc; + CURLM *multi; + CURLMcode mret; + fd_set rs; + fd_set ws; + fd_set es; + int max; + int running; + struct CURLMsg *msg; + time_t start; + struct timeval tv; + + multi = NULL; + cbc.buf = buf; + cbc.size = 2048; + cbc.pos = 0; + d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL, + 1082, NULL, NULL, &ahc_echo, "GET", + MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, + MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, + MHD_OPTION_END); + if (d == NULL) + return 256; + c = curl_easy_init (); + curl_easy_setopt (c, CURLOPT_URL, "https://localhost:1082/hello_world"); + curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer); + curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); + curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0); + curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); + if (oneone) + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + else + curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); + curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); + /* NOTE: use of CONNECTTIMEOUT without also + setting NOSIGNAL results in really weird + crashes on my system! */ + curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); + + + multi = curl_multi_init (); + if (multi == NULL) + { + curl_easy_cleanup (c); + MHD_stop_daemon (d); + return 512; + } + mret = curl_multi_add_handle (multi, c); + if (mret != CURLM_OK) + { + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + MHD_stop_daemon (d); + return 1024; + } + start = time (NULL); + while ((time (NULL) - start < 5) && (multi != NULL)) + { + max = 0; + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + curl_multi_perform (multi, &running); + mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); + if (mret != CURLM_OK) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + MHD_stop_daemon (d); + return 2048; + } + if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max)) + { + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + MHD_stop_daemon (d); + return 4096; + } + tv.tv_sec = 0; + tv.tv_usec = 1000; + select (max + 1, &rs, &ws, &es, &tv); + curl_multi_perform (multi, &running); + if (running == 0) + { + msg = curl_multi_info_read (multi, &running); + if (msg == NULL) + break; + if (msg->msg == CURLMSG_DONE) + { + if (msg->data.result != CURLE_OK) + printf ("%s failed at %s:%d: `%s'\n", + "curl_multi_perform", + __FILE__, + __LINE__, curl_easy_strerror (msg->data.result)); + curl_multi_remove_handle (multi, c); + curl_multi_cleanup (multi); + curl_easy_cleanup (c); + c = NULL; + multi = NULL; + } + } + MHD_run (d); + } + if (multi != NULL) + { + curl_multi_remove_handle (multi, c); + curl_easy_cleanup (c); + curl_multi_cleanup (multi); + } + MHD_stop_daemon (d); + if (cbc.pos != strlen ("/hello_world")) + return 8192; + if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) + return 16384; + return 0; +} + +GCRY_THREAD_OPTION_PTHREAD_IMPL; + +int +main (int argc, char *const *argv) +{ + FILE *test_fd; + unsigned int errorCount = 0; + + /* gnutls_global_set_log_level(11); */ + if (curl_check_version (MHD_REQ_CURL_VERSION, MHD_REQ_CURL_OPENSSL_VERSION)) + { + return -1; + } + gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + + if (!gcry_check_version (GCRYPT_VERSION)) + abort (); + + if ((test_fd = setup_test_file ()) == NULL) + { + fprintf (stderr, MHD_E_TEST_FILE_CREAT); + return -1; + } + + if (0 != curl_global_init (CURL_GLOBAL_ALL)) + { + fprintf (stderr, "Error: %s\n", strerror (errno)); + fclose (test_fd); + return -1; + } + + if (0 != (errorCount = testExternalGet ())) + fprintf (stderr, "Fail: %d\n", errorCount); + + + curl_global_cleanup (); + fclose (test_fd); + remove (TEST_FILE_NAME); + + return errorCount != 0; +} diff --git a/src/testcurl/https/tls_daemon_options_test.c b/src/testcurl/https/tls_daemon_options_test.c @@ -104,12 +104,6 @@ main (int argc, char *const *argv) return -1; } - int p_ssl3[] = { GNUTLS_SSL3, 0 }; - int p_tls[] = { GNUTLS_TLS1_2, - GNUTLS_TLS1_1, - GNUTLS_TLS1_0, 0 - }; - struct CipherDef ciphers[] = { {{GNUTLS_CIPHER_AES_128_CBC, 0}, "AES128-SHA"}, {{GNUTLS_CIPHER_ARCFOUR_128, 0}, "RC4-SHA"}, @@ -129,8 +123,7 @@ main (int argc, char *const *argv) CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, - MHD_OPTION_PROTOCOL_VERSION, p_tls, - MHD_OPTION_CIPHER_ALGORITHM, ciphers[cpos].options, + MHD_OPTION_CIPHER_ALGORITHM, "NORMAL", MHD_OPTION_END); cpos++; } @@ -146,8 +139,7 @@ main (int argc, char *const *argv) CURL_SSLVERSION_SSLv3, MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, - MHD_OPTION_PROTOCOL_VERSION, p_ssl3, - MHD_OPTION_CIPHER_ALGORITHM, ciphers[cpos].options, + MHD_OPTION_CIPHER_ALGORITHM, "NORMAL", MHD_OPTION_END); cpos++; } @@ -164,14 +156,14 @@ main (int argc, char *const *argv) test_fd, daemon_flags, "AES256-SHA", CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, - MHD_OPTION_PROTOCOL_VERSION, p_ssl3, MHD_OPTION_END); + MHD_OPTION_CIPHER_ALGORITHM, "SSL3", MHD_OPTION_END); #endif errorCount += test_wrap ("unmatching version: TLS vs. SSL3", &test_unmatching_ssl_version, test_fd, daemon_flags, "AES256-SHA", CURL_SSLVERSION_SSLv3, MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, - MHD_OPTION_PROTOCOL_VERSION, p_tls, MHD_OPTION_END); + MHD_OPTION_CIPHER_ALGORITHM, "SSL3", MHD_OPTION_END); curl_global_cleanup (); fclose (test_fd); remove (TEST_FILE_NAME); diff --git a/src/testcurl/https/tls_thread_mode_test.c b/src/testcurl/https/tls_thread_mode_test.c @@ -32,6 +32,7 @@ #include <sys/stat.h> #include <limits.h> #include <curl/curl.h> +#include <gcrypt.h> #include "tls_test_common.h" extern const char srv_key_pem[]; @@ -119,6 +120,8 @@ test_parallel_clients (FILE * test_fd, char *cipher_suite, return 0; } +GCRY_THREAD_OPTION_PTHREAD_IMPL; + int main (int argc, char *const *argv) { @@ -128,7 +131,7 @@ main (int argc, char *const *argv) /* initialize random seed used by curl clients */ unsigned int iseed = (unsigned int) time (NULL); srand (iseed); - + gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); if (curl_check_version (MHD_REQ_CURL_VERSION)) return -1;