1/* 2 This file is part of libmicrohttpd 3 Copyright (C) 2013 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 3, 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 test_empty_response.c 23 * @brief Testcase for libmicrohttpd HTTPS GET operations with emtpy reply 24 * @author Christian Grothoff 25 */ 26#include "platform.h" 27#include "microhttpd.h" 28#include <limits.h> 29#include <sys/stat.h> 30#include <curl/curl.h> 31#include <gcrypt.h> 32#include "tls_test_common.h" 33 34extern const char srv_key_pem[]; 35extern const char srv_self_signed_cert_pem[]; 36extern const char srv_signed_cert_pem[]; 37extern const char srv_signed_key_pem[]; 38 39static int oneone; 40 41static int 42ahc_echo (void *cls, 43 struct MHD_Connection *connection, 44 const char *url, 45 const char *method, 46 const char *version, 47 const char *upload_data, size_t *upload_data_size, 48 void **unused) 49{ 50 struct MHD_Response *response; 51 int ret; 52 53 response = MHD_create_response_from_buffer (0, NULL, 54 MHD_RESPMEM_PERSISTENT); 55 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 56 MHD_destroy_response (response); 57 return ret; 58} 59 60 61static int 62testInternalSelectGet () 63{ 64 struct MHD_Daemon *d; 65 CURL *c; 66 char buf[2048]; 67 struct CBC cbc; 68 CURLM *multi; 69 CURLMcode mret; 70 fd_set rs; 71 fd_set ws; 72 fd_set es; 73 MHD_socket max; 74 int running; 75 struct CURLMsg *msg; 76 time_t start; 77 struct timeval tv; 78 79 multi = NULL; 80 cbc.buf = buf; 81 cbc.size = 2048; 82 cbc.pos = 0; 83 d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | MHD_USE_SELECT_INTERNALLY, 84 1082, NULL, NULL, &ahc_echo, "GET", 85 MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, 86 MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, 87 MHD_OPTION_END); 88 if (d == NULL) 89 return 256; 90 91 char *aes256_sha = "AES256-SHA"; 92 if (curl_uses_nss_ssl() == 0) 93 { 94 aes256_sha = "rsa_aes_256_sha"; 95 } 96 97 c = curl_easy_init (); 98 curl_easy_setopt (c, CURLOPT_URL, "https://127.0.0.1:1082/hello_world"); 99 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 100 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 101 /* TLS options */ 102 curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); 103 curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, aes256_sha); 104 curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0); 105 curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0); 106 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); 107 if (oneone) 108 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 109 else 110 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 111 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 112 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); 113 /* NOTE: use of CONNECTTIMEOUT without also 114 setting NOSIGNAL results in really weird 115 crashes on my system! */ 116 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); 117 118 119 multi = curl_multi_init (); 120 if (multi == NULL) 121 { 122 curl_easy_cleanup (c); 123 MHD_stop_daemon (d); 124 return 512; 125 } 126 mret = curl_multi_add_handle (multi, c); 127 if (mret != CURLM_OK) 128 { 129 curl_multi_cleanup (multi); 130 curl_easy_cleanup (c); 131 MHD_stop_daemon (d); 132 return 1024; 133 } 134 start = time (NULL); 135 while ((time (NULL) - start < 5) && (multi != NULL)) 136 { 137 max = 0; 138 FD_ZERO (&rs); 139 FD_ZERO (&ws); 140 FD_ZERO (&es); 141 mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); 142 if (mret != CURLM_OK) 143 { 144 curl_multi_remove_handle (multi, c); 145 curl_multi_cleanup (multi); 146 curl_easy_cleanup (c); 147 MHD_stop_daemon (d); 148 return 2048; 149 } 150 tv.tv_sec = 0; 151 tv.tv_usec = 1000; 152 select (max + 1, &rs, &ws, &es, &tv); 153 curl_multi_perform (multi, &running); 154 if (running == 0) 155 { 156 msg = curl_multi_info_read (multi, &running); 157 if (msg == NULL) 158 break; 159 if (msg->msg == CURLMSG_DONE) 160 { 161 if (msg->data.result != CURLE_OK) 162 printf ("%s failed at %s:%d: `%s'\n", 163 "curl_multi_perform", 164 __FILE__, 165 __LINE__, curl_easy_strerror (msg->data.result)); 166 curl_multi_remove_handle (multi, c); 167 curl_multi_cleanup (multi); 168 curl_easy_cleanup (c); 169 c = NULL; 170 multi = NULL; 171 } 172 } 173 } 174 if (multi != NULL) 175 { 176 curl_multi_remove_handle (multi, c); 177 curl_easy_cleanup (c); 178 curl_multi_cleanup (multi); 179 } 180 MHD_stop_daemon (d); 181 if (cbc.pos != 0) 182 return 8192; 183 return 0; 184} 185 186 187int 188main (int argc, char *const *argv) 189{ 190 unsigned int errorCount = 0; 191 192 if (0 != curl_global_init (CURL_GLOBAL_ALL)) 193 { 194 fprintf (stderr, "Error: %s\n", strerror (errno)); 195 return -1; 196 } 197 if (0 != (errorCount = testInternalSelectGet ())) 198 fprintf (stderr, "Fail: %d\n", errorCount); 199 curl_global_cleanup (); 200 return errorCount != 0; 201} 202