aboutsummaryrefslogtreecommitdiff
path: root/src/gns/test_gns_proxy.c
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2019-01-25 20:52:55 +0100
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2019-01-25 20:52:55 +0100
commit7f666b4467ae5f530e904675df3f28886f4202fa (patch)
tree7bceb77a3b5de5fc8ec48bf8211d8bcd239f08fb /src/gns/test_gns_proxy.c
parent92d1fd704da83c27e9aac3d385b8dd6cf0c18a8a (diff)
downloadgnunet-7f666b4467ae5f530e904675df3f28886f4202fa.tar.gz
gnunet-7f666b4467ae5f530e904675df3f28886f4202fa.zip
Fix #5514; Add test for GNS Proxy and DANE; Fix TLS connections on ports != 443 through proxy
Diffstat (limited to 'src/gns/test_gns_proxy.c')
-rw-r--r--src/gns/test_gns_proxy.c402
1 files changed, 241 insertions, 161 deletions
diff --git a/src/gns/test_gns_proxy.c b/src/gns/test_gns_proxy.c
index ea61a89d5..75fe95617 100644
--- a/src/gns/test_gns_proxy.c
+++ b/src/gns/test_gns_proxy.c
@@ -30,13 +30,15 @@
30#include <gnurl/curl.h> 30#include <gnurl/curl.h>
31#endif 31#endif
32#include <microhttpd.h> 32#include <microhttpd.h>
33#include "gnunet_namestore_service.h" 33#include "gnunet_util_lib.h"
34#include "gnunet_gns_service.h" 34#include "gnutls/x509.h"
35#include "gnunet_testing_lib.h"
36#include "gnunet_os_lib.h"
37 35
38#define PORT 8080 36/**
39#define TEST_DOMAIN "www.gnu" 37 * Largest allowed size for a PEM certificate.
38 */
39#define MAX_PEM_SIZE (10 * 1024)
40
41#define TEST_DOMAIN "www.test"
40 42
41#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) 43#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
42 44
@@ -45,7 +47,6 @@
45 */ 47 */
46static int global_ret; 48static int global_ret;
47 49
48static struct GNUNET_NAMESTORE_Handle *namestore;
49 50
50static struct MHD_Daemon *mhd; 51static struct MHD_Daemon *mhd;
51 52
@@ -61,7 +62,15 @@ static char *url;
61 62
62static struct GNUNET_OS_Process *proxy_proc; 63static struct GNUNET_OS_Process *proxy_proc;
63 64
64static char* tmp_cfgfile; 65static char* cafile_opt;
66
67static char* cafile_srv;
68
69static uint16_t port;
70
71static gnutls_x509_crt_t proxy_cert;
72
73static gnutls_x509_privkey_t proxy_key;
65 74
66struct CBC 75struct CBC
67{ 76{
@@ -71,6 +80,101 @@ struct CBC
71 80
72static struct CBC cbc; 81static struct CBC cbc;
73 82
83/**
84 * Read file in filename
85 *
86 * @param filename file to read
87 * @param size pointer where filesize is stored
88 * @return NULL on error
89 */
90static void*
91load_file (const char* filename,
92 unsigned int* size)
93{
94 void *buffer;
95 uint64_t fsize;
96
97 if (GNUNET_OK !=
98 GNUNET_DISK_file_size (filename,
99 &fsize,
100 GNUNET_YES,
101 GNUNET_YES))
102 return NULL;
103 if (fsize > MAX_PEM_SIZE)
104 return NULL;
105 *size = (unsigned int) fsize;
106 buffer = GNUNET_malloc (*size);
107 if (fsize !=
108 GNUNET_DISK_fn_read (filename,
109 buffer,
110 (size_t) fsize))
111 {
112 GNUNET_free (buffer);
113 return NULL;
114 }
115 return buffer;
116}
117
118/**
119 * Load PEM key from file
120 *
121 * @param key where to store the data
122 * @param keyfile path to the PEM file
123 * @return #GNUNET_OK on success
124 */
125static int
126load_key_from_file (gnutls_x509_privkey_t key,
127 const char* keyfile)
128{
129 gnutls_datum_t key_data;
130 int ret;
131
132 key_data.data = load_file (keyfile,
133 &key_data.size);
134 if (NULL == key_data.data)
135 return GNUNET_SYSERR;
136 ret = gnutls_x509_privkey_import (key, &key_data,
137 GNUTLS_X509_FMT_PEM);
138 if (GNUTLS_E_SUCCESS != ret)
139 {
140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
141 _("Unable to import private key from file `%s'\n"),
142 keyfile);
143 }
144 GNUNET_free_non_null (key_data.data);
145 return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
146}
147
148/**
149 * Load cert from file
150 *
151 * @param crt struct to store data in
152 * @param certfile path to pem file
153 * @return #GNUNET_OK on success
154 */
155static int
156load_cert_from_file (gnutls_x509_crt_t crt,
157 const char* certfile)
158{
159 gnutls_datum_t cert_data;
160 int ret;
161
162 cert_data.data = load_file (certfile,
163 &cert_data.size);
164 if (NULL == cert_data.data)
165 return GNUNET_SYSERR;
166 ret = gnutls_x509_crt_import (crt,
167 &cert_data,
168 GNUTLS_X509_FMT_PEM);
169 if (GNUTLS_E_SUCCESS != ret)
170 {
171 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
172 _("Unable to import certificate from `%s'\n"),
173 certfile);
174 }
175 GNUNET_free_non_null (cert_data.data);
176 return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
177}
74 178
75static size_t 179static size_t
76copy_buffer (void *ptr, size_t size, size_t nmemb, void *ctx) 180copy_buffer (void *ptr, size_t size, size_t nmemb, void *ctx)
@@ -112,8 +216,11 @@ mhd_ahc (void *cls,
112 MHD_RESPMEM_MUST_COPY); 216 MHD_RESPMEM_MUST_COPY);
113 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 217 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
114 MHD_destroy_response (response); 218 MHD_destroy_response (response);
115 if (ret == MHD_NO) 219 if (ret == MHD_NO) {
220 global_ret = 1;
116 abort (); 221 abort ();
222 }
223 global_ret = 0;
117 return ret; 224 return ret;
118} 225}
119 226
@@ -138,13 +245,6 @@ do_shutdown ()
138 } 245 }
139 GNUNET_free_non_null (url); 246 GNUNET_free_non_null (url);
140 247
141 if (NULL != tmp_cfgfile)
142 {
143 if (0 != remove (tmp_cfgfile))
144 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "remove", tmp_cfgfile);
145 GNUNET_free (tmp_cfgfile);
146 tmp_cfgfile = NULL;
147 }
148 if (NULL != proxy_proc) 248 if (NULL != proxy_proc)
149 { 249 {
150 (void) GNUNET_OS_process_kill (proxy_proc, SIGKILL); 250 (void) GNUNET_OS_process_kill (proxy_proc, SIGKILL);
@@ -198,12 +298,12 @@ curl_main ()
198 { 298 {
199 if (msg->data.result != CURLE_OK) 299 if (msg->data.result != CURLE_OK)
200 { 300 {
201 fprintf (stderr, 301 fprintf (stderr,
202 "%s failed at %s:%d: `%s'\n", 302 "%s failed at %s:%d: `%s'\n",
203 "curl_multi_perform", 303 "curl_multi_perform",
204 __FILE__, 304 __FILE__,
205 __LINE__, curl_easy_strerror (msg->data.result)); 305 __LINE__, curl_easy_strerror (msg->data.result));
206 global_ret = 1; 306 global_ret = 1;
207 } 307 }
208 } 308 }
209 curl_multi_remove_handle (multi, curl); 309 curl_multi_remove_handle (multi, curl);
@@ -232,17 +332,17 @@ curl_main ()
232 else 332 else
233 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout); 333 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout);
234 GNUNET_NETWORK_fdset_copy_native (&nrs, 334 GNUNET_NETWORK_fdset_copy_native (&nrs,
235 &rs, 335 &rs,
236 max + 1); 336 max + 1);
237 GNUNET_NETWORK_fdset_copy_native (&nws, 337 GNUNET_NETWORK_fdset_copy_native (&nws,
238 &ws, 338 &ws,
239 max + 1); 339 max + 1);
240 curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 340 curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
241 delay, 341 delay,
242 &nrs, 342 &nrs,
243 &nws, 343 &nws,
244 &curl_task, 344 &curl_task,
245 NULL); 345 NULL);
246} 346}
247 347
248 348
@@ -250,33 +350,30 @@ static void
250start_curl (void *cls) 350start_curl (void *cls)
251{ 351{
252 GNUNET_asprintf (&url, 352 GNUNET_asprintf (&url,
253 "http://%s:%d/hello_world", 353 "https://%s:%d/hello_world",
254 TEST_DOMAIN, PORT); 354 TEST_DOMAIN, port);
255 curl = curl_easy_init (); 355 curl = curl_easy_init ();
256 curl_easy_setopt (curl, CURLOPT_URL, url); 356 curl_easy_setopt (curl, CURLOPT_URL, url);
357 //curl_easy_setopt (curl, CURLOPT_URL, "https://127.0.0.1:8443/hello_world");
257 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, &copy_buffer); 358 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, &copy_buffer);
258 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbc); 359 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbc);
259 curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1); 360 curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1);
260 curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L); 361 curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L);
261 curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 15L); 362 curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 15L);
262 curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1); 363 curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
364 curl_easy_setopt (curl, CURLOPT_CAINFO, cafile_opt);
365 //curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0L);
366 //curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0L);
263 curl_easy_setopt (curl, CURLOPT_PROXY, "socks5h://127.0.0.1:7777"); 367 curl_easy_setopt (curl, CURLOPT_PROXY, "socks5h://127.0.0.1:7777");
264 368
265 multi = curl_multi_init (); 369 multi = curl_multi_init ();
266 GNUNET_assert (multi != NULL); 370 GNUNET_assert (multi != NULL);
267 GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl)); 371 GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl));
268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Beginning HTTP download from `%s'\n", url); 372 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Beginning HTTP download from `%s'\n", url);
269 curl_main (); 373 curl_main ();
270} 374}
271 375
272 376
273static void
274disco_ns (void* cls)
275{
276 GNUNET_NAMESTORE_disconnect (namestore);
277}
278
279
280/** 377/**
281 * Callback invoked from the namestore service once record is 378 * Callback invoked from the namestore service once record is
282 * created. 379 * created.
@@ -290,24 +387,11 @@ disco_ns (void* cls)
290 * specified target peer; NULL on error 387 * specified target peer; NULL on error
291 */ 388 */
292static void 389static void
293commence_testing (void *cls, 390commence_testing (void *cls)
294 int32_t success,
295 const char *emsg)
296{ 391{
297 GNUNET_SCHEDULER_add_now (&disco_ns, NULL);
298
299 if ( (emsg != NULL) && (GNUNET_YES != success) )
300 {
301 fprintf (stderr,
302 "NS failed to create record %s\n",
303 emsg);
304 GNUNET_SCHEDULER_shutdown ();
305 return;
306 }
307
308 curl_task_id = 392 curl_task_id =
309 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, 393 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
310 &start_curl, NULL); 394 &start_curl, NULL);
311} 395}
312 396
313 397
@@ -345,139 +429,135 @@ mhd_main ()
345 FD_ZERO (&es); 429 FD_ZERO (&es);
346 max_fd = -1; 430 max_fd = -1;
347 GNUNET_assert (MHD_YES == 431 GNUNET_assert (MHD_YES ==
348 MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd)); 432 MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd));
349 if (MHD_YES == MHD_get_timeout (mhd, &timeout)) 433 if (MHD_YES == MHD_get_timeout (mhd, &timeout))
350 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 434 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
351 (unsigned int) timeout); 435 (unsigned int) timeout);
352 else 436 else
353 delay = GNUNET_TIME_UNIT_FOREVER_REL; 437 delay = GNUNET_TIME_UNIT_FOREVER_REL;
354 GNUNET_NETWORK_fdset_copy_native (&nrs, 438 GNUNET_NETWORK_fdset_copy_native (&nrs,
355 &rs, 439 &rs,
356 max_fd + 1); 440 max_fd + 1);
357 GNUNET_NETWORK_fdset_copy_native (&nws, 441 GNUNET_NETWORK_fdset_copy_native (&nws,
358 &ws, 442 &ws,
359 max_fd + 1); 443 max_fd + 1);
360 mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 444 mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
361 delay, 445 delay,
362 &nrs, 446 &nrs,
363 &nws, 447 &nws,
364 &mhd_task, 448 &mhd_task,
365 NULL); 449 NULL);
366} 450}
367 451
452
453/**
454 * Main function that will be run
455 *
456 * @param cls closure
457 * @param args remaining command-line arguments
458 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
459 * @param c configuration
460 */
368static void 461static void
369run (void *cls, 462run (void *cls,
370 const struct GNUNET_CONFIGURATION_Handle *cfg, 463 char *const *args,
371 struct GNUNET_TESTING_Peer *peer) 464 const char *cfgfile,
465 const struct GNUNET_CONFIGURATION_Handle *c)
372{ 466{
373 enum MHD_FLAG flags; 467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
374 struct GNUNET_CRYPTO_EcdsaPrivateKey *host_key; 468 "Using `%s' as CA\n",
375 struct GNUNET_GNSRECORD_Data rd; 469 cafile_srv);
376 char *zone_keyfile; 470 char cert[MAX_PEM_SIZE];
377 471 char key[MAX_PEM_SIZE];
378 namestore = GNUNET_NAMESTORE_connect (cfg); 472 size_t key_buf_size;
379 GNUNET_assert (NULL != namestore); 473 size_t cert_buf_size;
380 flags = MHD_USE_DEBUG; 474
381 mhd = MHD_start_daemon (flags, 475 gnutls_global_init ();
382 PORT, 476 gnutls_x509_crt_init (&proxy_cert);
383 NULL, NULL, 477 gnutls_x509_privkey_init (&proxy_key);
384 &mhd_ahc, NULL, 478
385 MHD_OPTION_END); 479 if ( (GNUNET_OK !=
386 GNUNET_assert (NULL != mhd); 480 load_cert_from_file (proxy_cert,
387 mhd_main (); 481 cafile_srv)) ||
388 482 (GNUNET_OK !=
389 tmp_cfgfile = GNUNET_DISK_mktemp ("test_gns_proxy_tmp.conf"); 483 load_key_from_file (proxy_key,
390 if (NULL == tmp_cfgfile) 484 cafile_srv)) )
391 {
392 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
393 "Failed to create tmp cfg!\n");
394 do_shutdown ();
395 return;
396 }
397
398 if (GNUNET_OK != GNUNET_CONFIGURATION_write ((struct GNUNET_CONFIGURATION_Handle *)cfg,
399 tmp_cfgfile))
400 { 485 {
401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
402 "Failed to write tmp cfg\n"); 487 _("Failed to load X.509 key and certificate from `%s'\n"),
403 do_shutdown (); 488 cafile_srv);
404 return; 489 gnutls_x509_crt_deinit (proxy_cert);
405 } 490 gnutls_x509_privkey_deinit (proxy_key);
406 491 gnutls_global_deinit ();
407 proxy_proc = GNUNET_OS_start_process (GNUNET_NO,
408 GNUNET_OS_INHERIT_STD_ALL,
409 NULL,
410 NULL,
411 NULL,
412 "gnunet-gns-proxy",
413 "gnunet-gns-proxy",
414 "-c", tmp_cfgfile, NULL);
415
416 if (NULL == proxy_proc)
417 {
418 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
419 "Unable to start proxy\n");
420 do_shutdown ();
421 return;
422 }
423
424 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
425 "ZONEKEY",
426 &zone_keyfile))
427 {
428 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
429 return; 492 return;
430 } 493 }
494 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
495 NULL);
496 key_buf_size = sizeof (key);
497 cert_buf_size = sizeof (cert);
498 gnutls_x509_crt_export (proxy_cert,
499 GNUTLS_X509_FMT_PEM,
500 cert,
501 &cert_buf_size);
502 gnutls_x509_privkey_export (proxy_key,
503 GNUTLS_X509_FMT_PEM,
504 key,
505 &key_buf_size);
506 mhd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | MHD_ALLOW_SUSPEND_RESUME, port,
507 NULL, NULL,
508 &mhd_ahc, NULL,
509 MHD_OPTION_HTTPS_MEM_KEY, key,
510 MHD_OPTION_HTTPS_MEM_CERT, cert,
511 MHD_OPTION_END);
512 GNUNET_assert (NULL != mhd);
513 mhd_main ();
431 514
432 host_key = GNUNET_CRYPTO_ecdsa_key_create_from_file (zone_keyfile); 515 GNUNET_SCHEDULER_add_now (&commence_testing,
433 rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; 516 NULL);
434 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_string_to_value (GNUNET_DNSPARSER_TYPE_A,
435 "127.0.0.1",
436 (void**)&rd.data,
437 &rd.data_size));
438 rd.record_type = GNUNET_DNSPARSER_TYPE_A;
439
440 GNUNET_NAMESTORE_record_create (namestore,
441 host_key,
442 "www",
443 &rd,
444 &commence_testing,
445 NULL);
446
447 GNUNET_free ((void**)rd.data);
448 GNUNET_free (zone_keyfile);
449 GNUNET_free (host_key);
450} 517}
451 518
452int 519int
453main (int argc, char *const *argv) 520main (int argc, char *const *argv)
454{ 521{
455 char *binary; 522 struct GNUNET_GETOPT_CommandLineOption options[] = {
456 523 GNUNET_GETOPT_option_uint16 ('p',
457 if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary ("gnunet-gns-proxy", GNUNET_NO, NULL)) 524 "port",
458 { 525 NULL,
459 fprintf (stderr, "Proxy binary not in PATH... skipping!\n"); 526 gettext_noop ("listen on specified port (default: 7777)"),
460 return 0; 527 &port),
461 } 528 GNUNET_GETOPT_option_string ('A',
462 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns"); 529 "curlcert",
463 if (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, NULL)) // TODO: once we have a windows-testcase, add test parameters here 530 NULL,
464 { 531 gettext_noop ("pem file to use as CA"),
465 fprintf (stderr, "DNS helper binary has wrong permissions... skipping!\n"); 532 &cafile_opt),
466 GNUNET_free (binary); 533 GNUNET_GETOPT_option_string ('S',
467 return 0; 534 "servercert",
468 } 535 NULL,
469 GNUNET_free (binary); 536 gettext_noop ("pem file to use for the server"),
537 &cafile_srv),
538
539 GNUNET_GETOPT_OPTION_END
540 };
470 541
471 if (0 != curl_global_init (CURL_GLOBAL_WIN32)) 542 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
472 { 543 {
473 fprintf (stderr, "failed to initialize curl\n"); 544 fprintf (stderr, "failed to initialize curl\n");
474 return 2; 545 return 2;
475 } 546 }
476 if (0 != GNUNET_TESTING_peer_run ("test-gnunet-gns-proxy", 547 if (GNUNET_OK !=
477 "test_gns_proxy.conf", 548 GNUNET_STRINGS_get_utf8_args (argc, argv,
478 &run, NULL)) 549 &argc, &argv))
550 return 2;
551 GNUNET_log_setup ("gnunet-gns-proxy-test",
552 "WARNING",
553 NULL);
554 if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv,
555 "gnunet-gns-proxy-test",
556 _("GNUnet GNS proxy test"),
557 options,
558 &run, NULL))
479 return 1; 559 return 1;
480 GNUNET_DISK_directory_remove ("/tmp/gnunet-test-gns-proxy"); 560 GNUNET_free_non_null ((char *) argv);
481 return global_ret; 561 return global_ret;
482} 562}
483 563