aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl/https/tls_test_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testcurl/https/tls_test_common.c')
-rw-r--r--src/testcurl/https/tls_test_common.c414
1 files changed, 414 insertions, 0 deletions
diff --git a/src/testcurl/https/tls_test_common.c b/src/testcurl/https/tls_test_common.c
new file mode 100644
index 00000000..e9367462
--- /dev/null
+++ b/src/testcurl/https/tls_test_common.c
@@ -0,0 +1,414 @@
1/*
2 This file is part of libmicrohttpd
3 (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 tls_daemon_options_test.c
23 * @brief Common tls test functions
24 * @author Sagie Amir
25 */
26
27#include "tls_test_common.h"
28#include "tls_test_keys.h"
29
30const char test_file_data[] = "Hello World\n";
31
32int curl_check_version (const char *req_version, ...);
33
34void
35print_test_result (int test_outcome, char *test_name)
36{
37 if (test_outcome != 0)
38 fprintf (stderr, "running test: %s [fail]\n", test_name);
39 else
40 fprintf (stdout, "running test: %s [pass]\n", test_name);
41}
42
43size_t
44copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
45{
46 struct CBC *cbc = ctx;
47
48 if (cbc->pos + size * nmemb > cbc->size)
49 return 0; /* overflow */
50 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
51 cbc->pos += size * nmemb;
52 return size * nmemb;
53}
54
55static int
56file_reader (void *cls, size_t pos, char *buf, int max)
57{
58 FILE *file = cls;
59 fseek (file, pos, SEEK_SET);
60 return fread (buf, 1, max, file);
61}
62
63/**
64 * HTTP access handler call back
65 */
66int
67http_ahc (void *cls, struct MHD_Connection *connection,
68 const char *url, const char *method, const char *upload_data,
69 const char *version, unsigned int *upload_data_size, void **ptr)
70{
71 static int aptr;
72 struct MHD_Response *response;
73 int ret;
74 FILE *file;
75 struct stat buf;
76
77 if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
78 return MHD_NO; /* unexpected method */
79 if (&aptr != *ptr)
80 {
81 /* do never respond on first call */
82 *ptr = &aptr;
83 return MHD_YES;
84 }
85 *ptr = NULL; /* reset when done */
86
87 file = fopen (url, "r");
88 if (file == NULL)
89 {
90 response = MHD_create_response_from_data (strlen (PAGE_NOT_FOUND),
91 (void *) PAGE_NOT_FOUND,
92 MHD_NO, MHD_NO);
93 ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
94 MHD_destroy_response (response);
95 }
96 else
97 {
98 stat (url, &buf);
99 response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
100 &file_reader, file,
101 (MHD_ContentReaderFreeCallback)
102 & fclose);
103 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
104 MHD_destroy_response (response);
105 }
106 return ret;
107}
108
109/* HTTP access handler call back */
110int
111http_dummy_ahc (void *cls, struct MHD_Connection *connection,
112 const char *url, const char *method, const char *upload_data,
113 const char *version, unsigned int *upload_data_size,
114 void **ptr)
115{
116 return 0;
117}
118
119/**
120 * send a test http request to the daemon
121 * @param url
122 * @param cbc - may be null
123 * @param cipher_suite
124 * @param proto_version
125 * @return
126 */
127/* TODO have test wrap consider a NULL cbc */
128send_curl_req (char *url, struct CBC * cbc, char *cipher_suite,
129 int proto_version)
130{
131 CURL *c;
132 CURLcode errornum;
133 c = curl_easy_init ();
134#if DEBUG_HTTPS_TEST
135 curl_easy_setopt (c, CURLOPT_VERBOSE, CURL_VERBOS_LEVEL);
136#endif
137 curl_easy_setopt (c, CURLOPT_URL, url);
138 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
139 curl_easy_setopt (c, CURLOPT_TIMEOUT, 60L);
140 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 60L);
141
142 if (cbc != NULL)
143 {
144 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
145 curl_easy_setopt (c, CURLOPT_FILE, cbc);
146 }
147
148 /* TLS options */
149 curl_easy_setopt (c, CURLOPT_SSLVERSION, proto_version);
150 curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, cipher_suite);
151
152 /* currently skip any peer authentication */
153 curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
154 curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
155
156 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
157
158 /* NOTE: use of CONNECTTIMEOUT without also
159 setting NOSIGNAL results in really weird
160 crashes on my system! */
161 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
162 if (CURLE_OK != (errornum = curl_easy_perform (c)))
163 {
164 fprintf (stderr, "curl_easy_perform failed: `%s'\n",
165 curl_easy_strerror (errornum));
166 curl_easy_cleanup (c);
167 return errornum;
168 }
169
170 curl_easy_cleanup (c);
171
172 return CURLE_OK;
173}
174
175/**
176 * compile test file url pointing to the current running directory path
177 * @param url - char buffer into which the url is compiled
178 * @return
179 */
180int
181gen_test_file_url (char *url, int port)
182{
183 int ret = 0;
184 char *doc_path;
185 size_t doc_path_len;
186 /* setup test file path, url */
187 doc_path_len = PATH_MAX > 4096 ? 4096 : PATH_MAX;
188 if (NULL == (doc_path = malloc (doc_path_len)))
189 {
190 fprintf (stderr, MHD_E_MEM);
191 ret = -1;
192 }
193 if (getcwd (doc_path, doc_path_len) == NULL)
194 {
195 fprintf (stderr, "Error: failed to get working directory. %s\n",
196 strerror (errno));
197 ret = -1;
198 }
199 /* construct url - this might use doc_path */
200 if (sprintf (url, "%s:%d%s/%s", "https://localhost", port,
201 doc_path, TEST_FILE_NAME) < 0)
202 ret = -1;
203
204 free (doc_path);
205 return ret;
206}
207
208/**
209 * test HTTPS file transfer
210 * @param test_fd: file to attempt transferring
211 */
212int
213test_https_transfer (FILE * test_fd, char *cipher_suite, int proto_version)
214{
215 int len, ret = 0;
216 struct CBC cbc;
217 char url[255];
218 struct stat statb;
219 /* used to memcmp local copy & deamon supplied copy */
220 unsigned char *mem_test_file_local;
221
222 stat (TEST_FILE_NAME, &statb);
223 len = statb.st_size;
224
225 if (NULL == (mem_test_file_local = malloc (len)))
226 {
227 fprintf (stderr, MHD_E_MEM);
228 ret = -1;
229 goto cleanup;
230 }
231
232 fseek (test_fd, 0, SEEK_SET);
233 if (fread (mem_test_file_local, sizeof (char), len, test_fd) != len)
234 {
235 fprintf (stderr, "Error: failed to read test file. %s\n",
236 strerror (errno));
237 ret = -1;
238 goto cleanup;
239 }
240
241 if (NULL == (cbc.buf = malloc (sizeof (char) * len)))
242 {
243 fprintf (stderr, MHD_E_MEM);
244 ret = -1;
245 goto cleanup;
246 }
247 cbc.size = len;
248 cbc.pos = 0;
249
250 if (gen_test_file_url (url, DEAMON_TEST_PORT))
251 {
252 ret = -1;
253 goto cleanup;
254 }
255
256 if (CURLE_OK != send_curl_req (url, &cbc, cipher_suite, proto_version))
257 {
258 ret = -1;
259 goto cleanup;
260 }
261
262 /* compare test file & daemon responce */
263 if (memcmp (cbc.buf, mem_test_file_local, len) != 0)
264 {
265 fprintf (stderr, "Error: local file & received file differ.\n");
266 ret = -1;
267 }
268
269cleanup:
270 free (mem_test_file_local);
271 free (cbc.buf);
272 return ret;
273}
274
275/**
276 * setup a mock test file which is requested from the running daemon
277 * @return open file descriptor to the test file
278 */
279FILE *
280setup_test_file ()
281{
282 FILE *test_fd;
283
284 if (NULL == (test_fd = fopen (TEST_FILE_NAME, "w+")))
285 {
286 fprintf (stderr, "Error: failed to open `%s': %s\n",
287 TEST_FILE_NAME, strerror (errno));
288 return NULL;
289 }
290 if (fwrite (test_file_data, sizeof (char), strlen (test_file_data), test_fd)
291 != strlen (test_file_data))
292 {
293 fprintf (stderr, "Error: failed to write `%s. %s'\n",
294 TEST_FILE_NAME, strerror (errno));
295 fclose (test_fd);
296 return NULL;
297 }
298 if (fflush (test_fd))
299 {
300 fprintf (stderr, "Error: failed to flush test file stream. %s\n",
301 strerror (errno));
302 fclose (test_fd);
303 return NULL;
304 }
305 return test_fd;
306}
307
308/**
309 * setup test case
310 *
311 * @param d
312 * @param daemon_flags
313 * @param arg_list
314 * @return
315 */
316int
317setup_testcase (struct MHD_Daemon **d, int daemon_flags, va_list arg_list)
318{
319 *d = MHD_start_daemon_va (daemon_flags, DEAMON_TEST_PORT,
320 NULL, NULL, &http_ahc, NULL, arg_list);
321
322 if (*d == NULL)
323 {
324 fprintf (stderr, MHD_E_SERVER_INIT);
325 return -1;
326 }
327
328 return 0;
329}
330
331void
332teardown_testcase (struct MHD_Daemon *d)
333{
334 MHD_stop_daemon (d);
335}
336
337int
338setup_session (MHD_gtls_session_t * session,
339 MHD_gnutls_datum_t * key,
340 MHD_gnutls_datum_t * cert, MHD_gtls_cert_credentials_t * xcred)
341{
342 int ret;
343 const char **err_pos;
344
345 MHD__gnutls_certificate_allocate_credentials (xcred);
346
347 MHD_gtls_set_datum_m (key, srv_key_pem, strlen (srv_key_pem), &malloc);
348 MHD_gtls_set_datum_m (cert, srv_self_signed_cert_pem,
349 strlen (srv_self_signed_cert_pem), &malloc);
350
351 MHD__gnutls_certificate_set_x509_key_mem (*xcred, cert, key,
352 GNUTLS_X509_FMT_PEM);
353
354 MHD__gnutls_init (session, GNUTLS_CLIENT);
355 ret = MHD__gnutls_priority_set_direct (*session, "NORMAL", err_pos);
356 if (ret < 0)
357 {
358 return -1;
359 }
360
361 MHD__gnutls_credentials_set (*session, MHD_GNUTLS_CRD_CERTIFICATE, xcred);
362 return 0;
363}
364
365int
366teardown_session (MHD_gtls_session_t session,
367 MHD_gnutls_datum_t * key,
368 MHD_gnutls_datum_t * cert,
369 MHD_gtls_cert_credentials_t xcred)
370{
371
372 MHD_gtls_free_datum_m (key, free);
373 MHD_gtls_free_datum_m (cert, free);
374
375 MHD__gnutls_deinit (session);
376
377 MHD__gnutls_certificate_free_credentials (xcred);
378 return 0;
379}
380
381/* TODO test_wrap: change sig to (setup_func, test, va_list test_arg) */
382int
383test_wrap (char *test_name, int
384 (*test_function) (FILE * test_fd, char *cipher_suite,
385 int proto_version), FILE * test_fd,
386 int daemon_flags, char *cipher_suite, int proto_version, ...)
387{
388 int ret;
389 va_list arg_list;
390 struct MHD_Daemon *d;
391
392 va_start (arg_list, proto_version);
393 if (setup_testcase (&d, daemon_flags, arg_list) != 0)
394 {
395 va_end (arg_list);
396 return -1;
397 }
398
399 fprintf (stdout, "running test: %s ", test_name);
400 ret = test_function (test_fd, cipher_suite, proto_version);
401
402 if (ret == 0)
403 {
404 fprintf (stdout, "[pass]\n");
405 }
406 else
407 {
408 fprintf (stdout, "[fail]\n");
409 }
410
411 teardown_testcase (d);
412 va_end (arg_list);
413 return ret;
414}