• 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 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
query_session_ahc(void * cls,struct MHD_Connection * connection,const char * url,const char * method,const char * upload_data,const char * version,size_t * upload_data_size,void ** ptr)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
test_query_session()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, &copyBuffer);
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
main(int argc,char * const * argv)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