1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2007 Christian Grothoff 4 5 libmicrohttpd is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 2, or (at your 8 option) any later version. 9 10 libmicrohttpd is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with libmicrohttpd; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 Boston, MA 02111-1307, USA. 19 */ 20 21 /** 22 * @file mhds_session_info_test.c 23 * @brief Testcase for libmicrohttpd HTTPS connection querying operations 24 * @author Sagie Amir 25 */ 26 27 #include "platform.h" 28 #include "microhttpd.h" 29 #include <curl/curl.h> 30 #include <gcrypt.h> 31 #include "tls_test_common.h" 32 33 extern int curl_check_version (const char *req_version, ...); 34 extern const char srv_key_pem[]; 35 extern const char srv_self_signed_cert_pem[]; 36 37 struct MHD_Daemon *d; 38 39 /* 40 * HTTP access handler call back 41 * used to query negotiated security parameters 42 */ 43 static int 44 query_session_ahc (void *cls, struct MHD_Connection *connection, 45 const char *url, const char *method, 46 const char *upload_data, const char *version, 47 size_t *upload_data_size, void **ptr) 48 { 49 struct MHD_Response *response; 50 int ret; 51 52 if (NULL == *ptr) 53 { 54 *ptr = &query_session_ahc; 55 return MHD_YES; 56 } 57 58 if (GNUTLS_TLS1_1 != 59 (ret = MHD_get_connection_info 60 (connection, 61 MHD_CONNECTION_INFO_PROTOCOL)->protocol)) 62 { 63 if (GNUTLS_TLS1_2 == ret) 64 { 65 /* as usual, TLS implementations sometimes don't 66 quite do what was asked, just mildly complain... */ 67 fprintf (stderr, 68 "Warning: requested TLS 1.1, got TLS 1.2\n"); 69 } 70 else 71 { 72 /* really different version... */ 73 fprintf (stderr, 74 "Error: requested protocol mismatch (wanted %d, got %d)\n", 75 GNUTLS_TLS1_1, 76 ret); 77 return -1; 78 } 79 } 80 81 response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE), 82 (void *) EMPTY_PAGE, 83 MHD_RESPMEM_PERSISTENT); 84 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 85 MHD_destroy_response (response); 86 return ret; 87 } 88 89 90 /** 91 * negotiate a secure connection with server & query negotiated security parameters 92 */ 93 static int 94 test_query_session () 95 { 96 CURL *c; 97 struct CBC cbc; 98 CURLcode errornum; 99 char url[256]; 100 101 if (NULL == (cbc.buf = malloc (sizeof (char) * 255))) 102 return 16; 103 cbc.size = 255; 104 cbc.pos = 0; 105 106 gen_test_file_url (url, DEAMON_TEST_PORT); 107 108 /* setup test */ 109 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL | 110 MHD_USE_DEBUG, DEAMON_TEST_PORT, 111 NULL, NULL, &query_session_ahc, NULL, 112 MHD_OPTION_HTTPS_PRIORITIES, "NORMAL:+ARCFOUR-128", 113 MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, 114 MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, 115 MHD_OPTION_END); 116 117 if (d == NULL) 118 return 2; 119 120 const char *aes256_sha = "AES256-SHA"; 121 if (curl_uses_nss_ssl() == 0) 122 { 123 aes256_sha = "rsa_aes_256_sha"; 124 } 125 126 c = curl_easy_init (); 127 #if DEBUG_HTTPS_TEST 128 curl_easy_setopt (c, CURLOPT_VERBOSE, 1); 129 #endif 130 curl_easy_setopt (c, CURLOPT_URL, url); 131 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 132 curl_easy_setopt (c, CURLOPT_TIMEOUT, 10L); 133 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 10L); 134 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 135 curl_easy_setopt (c, CURLOPT_FILE, &cbc); 136 /* TLS options */ 137 curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1); 138 curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, aes256_sha); 139 /* currently skip any peer authentication */ 140 curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0); 141 curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0); 142 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); 143 144 // NOTE: use of CONNECTTIMEOUT without also 145 // setting NOSIGNAL results in really weird 146 // crashes on my system! 147 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); 148 if (CURLE_OK != (errornum = curl_easy_perform (c))) 149 { 150 fprintf (stderr, "curl_easy_perform failed: `%s'\n", 151 curl_easy_strerror (errornum)); 152 153 MHD_stop_daemon (d); 154 curl_easy_cleanup (c); 155 free (cbc.buf); 156 return -1; 157 } 158 159 curl_easy_cleanup (c); 160 MHD_stop_daemon (d); 161 free (cbc.buf); 162 return 0; 163 } 164 165 166 int 167 main (int argc, char *const *argv) 168 { 169 unsigned int errorCount = 0; 170 171 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); 172 #ifdef GCRYCTL_INITIALIZATION_FINISHED 173 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); 174 #endif 175 if (0 != curl_global_init (CURL_GLOBAL_ALL)) 176 { 177 fprintf (stderr, "Error (code: %u)\n", errorCount); 178 return -1; 179 } 180 errorCount += test_query_session (); 181 print_test_result (errorCount, argv[0]); 182 curl_global_cleanup (); 183 if (errorCount > 0) 184 fprintf (stderr, "Error (code: %u)\n", errorCount); 185 return errorCount; 186 } 187