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, &copyBuffer);
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