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