tls_test_common.c (20398B)
1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2007 Christian Grothoff 4 Copyright (C) 2017-2022 Evgeny Grin (Karlson2k) 5 6 libmicrohttpd is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published 8 by the Free Software Foundation; either version 2, or (at your 9 option) any later version. 10 11 libmicrohttpd is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with libmicrohttpd; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 Boston, MA 02110-1301, USA. 20 */ 21 22 /** 23 * @file tls_test_common.c 24 * @brief Common tls test functions 25 * @author Sagie Amir 26 * @author Karlson2k (Evgeny Grin) 27 */ 28 #include <string.h> 29 #include "tls_test_common.h" 30 #include "tls_test_keys.h" 31 32 /** 33 * Map @a know_gnutls_tls_ids values to printable names. 34 */ 35 const char *tls_names[KNOW_TLS_IDS_COUNT] = { 36 "Bad value", 37 "SSL version 3", 38 "TLS version 1.0", 39 "TLS version 1.1", 40 "TLS version 1.2", 41 "TLS version 1.3" 42 }; 43 44 /** 45 * Map @a know_gnutls_tls_ids values to GnuTLS priorities strings. 46 */ 47 const char *priorities_map[KNOW_TLS_IDS_COUNT] = { 48 "NONE", 49 "NORMAL:!VERS-ALL:+VERS-SSL3.0", 50 "NORMAL:!VERS-ALL:+VERS-TLS1.0", 51 "NORMAL:!VERS-ALL:+VERS-TLS1.1", 52 "NORMAL:!VERS-ALL:+VERS-TLS1.2", 53 "NORMAL:!VERS-ALL:+VERS-TLS1.3" 54 }; 55 56 /** 57 * Map @a know_gnutls_tls_ids values to GnuTLS priorities append strings. 58 */ 59 const char *priorities_append_map[KNOW_TLS_IDS_COUNT] = { 60 "NONE", 61 "!VERS-ALL:+VERS-SSL3.0", 62 "!VERS-ALL:+VERS-TLS1.0", 63 "!VERS-ALL:+VERS-TLS1.1", 64 "!VERS-ALL:+VERS-TLS1.2", 65 "!VERS-ALL:+VERS-TLS1.3" 66 }; 67 68 69 /** 70 * Map @a know_gnutls_tls_ids values to libcurl @a CURLOPT_SSLVERSION value. 71 */ 72 const long libcurl_tls_vers_map[KNOW_TLS_IDS_COUNT] = { 73 CURL_SSLVERSION_LAST, /* bad value */ 74 CURL_SSLVERSION_SSLv3, 75 #if CURL_AT_LEAST_VERSION (7,34,0) 76 CURL_SSLVERSION_TLSv1_0, 77 #else /* CURL VER < 7.34.0 */ 78 CURL_SSLVERSION_TLSv1, /* TLS 1.0 or later */ 79 #endif /* CURL VER < 7.34.0 */ 80 #if CURL_AT_LEAST_VERSION (7,34,0) 81 CURL_SSLVERSION_TLSv1_1, 82 #else /* CURL VER < 7.34.0 */ 83 CURL_SSLVERSION_LAST, /* bad value, not supported by this libcurl version */ 84 #endif /* CURL VER < 7.34.0 */ 85 #if CURL_AT_LEAST_VERSION (7,34,0) 86 CURL_SSLVERSION_TLSv1_2, 87 #else /* CURL VER < 7.34.0 */ 88 CURL_SSLVERSION_LAST, /* bad value, not supported by this libcurl version */ 89 #endif /* CURL VER < 7.34.0 */ 90 #if CURL_AT_LEAST_VERSION (7,52,0) 91 CURL_SSLVERSION_TLSv1_3 92 #else /* CURL VER < 7.34.0 */ 93 CURL_SSLVERSION_LAST /* bad value, not supported by this libcurl version */ 94 #endif /* CURL VER < 7.34.0 */ 95 }; 96 97 #if CURL_AT_LEAST_VERSION (7,54,0) 98 /** 99 * Map @a know_gnutls_tls_ids values to libcurl @a CURLOPT_SSLVERSION value 100 * for maximum supported TLS version. 101 */ 102 const long libcurl_tls_max_vers_map[KNOW_TLS_IDS_COUNT] = { 103 CURL_SSLVERSION_MAX_DEFAULT, /* bad value */ 104 CURL_SSLVERSION_MAX_DEFAULT, /* SSLv3 */ 105 CURL_SSLVERSION_MAX_TLSv1_0, 106 CURL_SSLVERSION_MAX_TLSv1_1, 107 CURL_SSLVERSION_MAX_TLSv1_2, 108 CURL_SSLVERSION_MAX_TLSv1_3 109 }; 110 #endif /* CURL_AT_LEAST_VERSION(7,54,0) */ 111 112 /* 113 * test HTTPS transfer 114 */ 115 enum test_get_result 116 test_daemon_get (void *cls, 117 const char *cipher_suite, 118 int proto_version, 119 uint16_t port, 120 int ver_peer) 121 { 122 CURL *c; 123 struct CBC cbc; 124 CURLcode errornum; 125 CURLcode e; 126 char url[255]; 127 size_t len; 128 (void) cls; /* Unused. Silence compiler warning. */ 129 130 len = strlen (test_data); 131 if (NULL == (cbc.buf = malloc (sizeof (char) * len))) 132 { 133 fprintf (stderr, MHD_E_MEM); 134 return TEST_GET_HARD_ERROR; 135 } 136 cbc.size = len; 137 cbc.pos = 0; 138 139 /* construct url - this might use doc_path */ 140 gen_test_uri (url, 141 sizeof (url), 142 port); 143 144 c = curl_easy_init (); 145 #ifdef _DEBUG 146 curl_easy_setopt (c, CURLOPT_VERBOSE, 1L); 147 #endif 148 if ((CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_URL, url))) || 149 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_HTTP_VERSION, 150 CURL_HTTP_VERSION_1_1))) || 151 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_TIMEOUT, 10L))) || 152 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 10L))) || 153 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, 154 ©Buffer))) || 155 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc))) || 156 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L))) || 157 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L)))) 158 { 159 fprintf (stderr, "curl_easy_setopt failed: `%s'\n", 160 curl_easy_strerror (e)); 161 curl_easy_cleanup (c); 162 free (cbc.buf); 163 return TEST_GET_CURL_GEN_ERROR; 164 } 165 166 /* TLS options */ 167 if ((CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_SSLVERSION, 168 proto_version))) || 169 ((NULL != cipher_suite) && 170 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, 171 cipher_suite)))) || 172 173 /* perform peer authentication */ 174 /* TODO merge into send_curl_req */ 175 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 176 ver_peer))) || 177 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0L)))) 178 { 179 fprintf (stderr, "HTTPS curl_easy_setopt failed: `%s'\n", 180 curl_easy_strerror (e)); 181 curl_easy_cleanup (c); 182 free (cbc.buf); 183 return TEST_GET_CURL_GEN_ERROR; 184 } 185 if (ver_peer && 186 (CURLE_OK != 187 (e = curl_easy_setopt (c, CURLOPT_CAINFO, ca_cert_file_name)))) 188 { 189 fprintf (stderr, "HTTPS curl_easy_setopt failed: `%s'\n", 190 curl_easy_strerror (e)); 191 curl_easy_cleanup (c); 192 free (cbc.buf); 193 return TEST_GET_CURL_CA_ERROR; 194 } 195 if (CURLE_OK != (errornum = curl_easy_perform (c))) 196 { 197 fprintf (stderr, "curl_easy_perform failed: `%s'\n", 198 curl_easy_strerror (errornum)); 199 curl_easy_cleanup (c); 200 free (cbc.buf); 201 if ((CURLE_SSL_CACERT_BADFILE == errornum) 202 #if CURL_AT_LEAST_VERSION (7,21,5) 203 || (CURLE_NOT_BUILT_IN == errornum) 204 #endif /* CURL_AT_LEAST_VERSION (7,21,5) */ 205 ) 206 return TEST_GET_CURL_CA_ERROR; 207 if (CURLE_OUT_OF_MEMORY == errornum) 208 return TEST_GET_HARD_ERROR; 209 return TEST_GET_ERROR; 210 } 211 212 curl_easy_cleanup (c); 213 214 if (memcmp (cbc.buf, test_data, len) != 0) 215 { 216 fprintf (stderr, "Error: local data & received data differ.\n"); 217 free (cbc.buf); 218 return TEST_GET_TRANSFER_ERROR; 219 } 220 221 free (cbc.buf); 222 return TEST_GET_OK; 223 } 224 225 226 void 227 print_test_result (unsigned int test_outcome, 228 const char *test_name) 229 { 230 if (test_outcome != 0) 231 fprintf (stderr, 232 "running test: %s [fail: %u]\n", 233 test_name, test_outcome); 234 #if 0 235 else 236 fprintf (stdout, 237 "running test: %s [pass]\n", 238 test_name); 239 #endif 240 } 241 242 243 size_t 244 copyBuffer (void *ptr, 245 size_t size, 246 size_t nmemb, 247 void *ctx) 248 { 249 struct CBC *cbc = ctx; 250 251 if (cbc->pos + size * nmemb > cbc->size) 252 { 253 fprintf (stderr, "Server data does not fit buffer.\n"); 254 return 0; /* overflow */ 255 } 256 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); 257 cbc->pos += size * nmemb; 258 return size * nmemb; 259 } 260 261 262 /** 263 * HTTP access handler call back 264 */ 265 enum MHD_Result 266 http_ahc (void *cls, 267 struct MHD_Connection *connection, 268 const char *url, 269 const char *method, 270 const char *version, 271 const char *upload_data, 272 size_t *upload_data_size, 273 void **req_cls) 274 { 275 static int aptr; 276 struct MHD_Response *response; 277 enum MHD_Result ret; 278 (void) cls; (void) url; (void) version; /* Unused. Silent compiler warning. */ 279 (void) upload_data; (void) upload_data_size; /* Unused. Silent compiler warning. */ 280 281 if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) 282 return MHD_NO; /* unexpected method */ 283 if (&aptr != *req_cls) 284 { 285 /* do never respond on first call */ 286 *req_cls = &aptr; 287 return MHD_YES; 288 } 289 *req_cls = NULL; /* reset when done */ 290 response = MHD_create_response_from_buffer_static (strlen (test_data), 291 test_data); 292 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 293 MHD_destroy_response (response); 294 return ret; 295 } 296 297 298 /* HTTP access handler call back */ 299 enum MHD_Result 300 http_dummy_ahc (void *cls, 301 struct MHD_Connection *connection, 302 const char *url, 303 const char *method, 304 const char *version, 305 const char *upload_data, 306 size_t *upload_data_size, 307 void **req_cls) 308 { 309 (void) cls; 310 (void) connection; 311 (void) url; 312 (void) method; 313 (void) version; /* Unused. Silent compiler warning. */ 314 (void) upload_data; 315 (void) upload_data_size; 316 (void) req_cls; /* Unused. Silent compiler warning. */ 317 return 0; 318 } 319 320 321 /** 322 * send a test http request to the daemon 323 * @param url 324 * @param cbc - may be null 325 * @param cipher_suite 326 * @param proto_version 327 * @return 328 */ 329 /* TODO have test wrap consider a NULL cbc */ 330 CURLcode 331 send_curl_req (char *url, 332 struct CBC *cbc, 333 const char *cipher_suite, 334 int proto_version) 335 { 336 CURL *c; 337 CURLcode errornum; 338 CURLcode e; 339 c = curl_easy_init (); 340 #ifdef _DEBUG 341 curl_easy_setopt (c, CURLOPT_VERBOSE, 1L); 342 #endif 343 if ((CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_URL, url))) || 344 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_HTTP_VERSION, 345 CURL_HTTP_VERSION_1_1))) || 346 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_TIMEOUT, 60L))) || 347 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 60L))) || 348 349 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L))) || 350 351 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L)))) 352 { 353 fprintf (stderr, "curl_easy_setopt failed: `%s'\n", 354 curl_easy_strerror (e)); 355 curl_easy_cleanup (c); 356 return e; 357 } 358 if (cbc != NULL) 359 { 360 if ((CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, 361 ©Buffer))) || 362 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_WRITEDATA, cbc)))) 363 { 364 fprintf (stderr, "curl_easy_setopt failed: `%s'\n", 365 curl_easy_strerror (e)); 366 curl_easy_cleanup (c); 367 return e; 368 } 369 } 370 371 /* TLS options */ 372 if ((CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_SSLVERSION, 373 proto_version))) || 374 ((NULL != cipher_suite) && 375 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, 376 cipher_suite)))) || 377 /* currently skip any peer authentication */ 378 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0L))) || 379 (CURLE_OK != (e = curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0L)))) 380 { 381 fprintf (stderr, "HTTPS curl_easy_setopt failed: `%s'\n", 382 curl_easy_strerror (e)); 383 curl_easy_cleanup (c); 384 return e; 385 } 386 387 if (CURLE_OK != (errornum = curl_easy_perform (c))) 388 { 389 fprintf (stderr, "curl_easy_perform failed: `%s'\n", 390 curl_easy_strerror (errornum)); 391 curl_easy_cleanup (c); 392 return errornum; 393 } 394 curl_easy_cleanup (c); 395 396 return CURLE_OK; 397 } 398 399 400 /** 401 * compile test URI 402 * 403 * @param[out] uri - char buffer into which the url is compiled 404 * @param uri_len number of bytes available in @a url 405 * @param port port to use for the test 406 * @return 1 on error 407 */ 408 unsigned int 409 gen_test_uri (char *uri, 410 size_t uri_len, 411 uint16_t port) 412 { 413 int res; 414 415 res = snprintf (uri, 416 uri_len, 417 "https://127.0.0.1:%u/urlpath", 418 (unsigned int) port); 419 if (res <= 0) 420 return 1; 421 if ((size_t) res >= uri_len) 422 return 1; 423 424 return 0; 425 } 426 427 428 /** 429 * test HTTPS data transfer 430 */ 431 unsigned int 432 test_https_transfer (void *cls, 433 uint16_t port, 434 const char *cipher_suite, 435 int proto_version) 436 { 437 size_t len; 438 unsigned int ret = 0; 439 struct CBC cbc; 440 char url[255]; 441 (void) cls; /* Unused. Silent compiler warning. */ 442 443 len = strlen (test_data); 444 if (NULL == (cbc.buf = malloc (sizeof (char) * len))) 445 { 446 fprintf (stderr, MHD_E_MEM); 447 return 1; 448 } 449 cbc.size = len; 450 cbc.pos = 0; 451 452 if (gen_test_uri (url, 453 sizeof (url), 454 port)) 455 { 456 ret = 1; 457 goto cleanup; 458 } 459 460 if (CURLE_OK != 461 send_curl_req (url, &cbc, cipher_suite, proto_version)) 462 { 463 ret = 1; 464 goto cleanup; 465 } 466 467 /* compare test data & daemon response */ 468 if ( (len != strlen (test_data)) || 469 (memcmp (cbc.buf, 470 test_data, 471 len) != 0) ) 472 { 473 fprintf (stderr, "Error: original data & received data differ.\n"); 474 ret = 1; 475 } 476 cleanup: 477 free (cbc.buf); 478 return ret; 479 } 480 481 482 /** 483 * setup test case 484 * 485 * @param d 486 * @param daemon_flags 487 * @param arg_list 488 * @return port number on success or zero on failure 489 */ 490 static uint16_t 491 setup_testcase (struct MHD_Daemon **d, uint16_t port, unsigned int daemon_flags, 492 va_list arg_list) 493 { 494 *d = MHD_start_daemon_va (daemon_flags, port, 495 NULL, NULL, &http_ahc, NULL, arg_list); 496 497 if (*d == NULL) 498 { 499 fprintf (stderr, MHD_E_SERVER_INIT); 500 return 0; 501 } 502 503 if (0 == port) 504 { 505 const union MHD_DaemonInfo *dinfo; 506 dinfo = MHD_get_daemon_info (*d, MHD_DAEMON_INFO_BIND_PORT); 507 if ((NULL == dinfo) || (0 == dinfo->port) ) 508 { 509 MHD_stop_daemon (*d); 510 return 0; 511 } 512 port = dinfo->port; 513 } 514 515 return port; 516 } 517 518 519 static void 520 teardown_testcase (struct MHD_Daemon *d) 521 { 522 MHD_stop_daemon (d); 523 } 524 525 526 unsigned int 527 setup_session (gnutls_session_t *session, 528 gnutls_certificate_credentials_t *xcred) 529 { 530 if (GNUTLS_E_SUCCESS == gnutls_init (session, GNUTLS_CLIENT)) 531 { 532 if (GNUTLS_E_SUCCESS == gnutls_set_default_priority (*session)) 533 { 534 if (GNUTLS_E_SUCCESS == gnutls_certificate_allocate_credentials (xcred)) 535 { 536 if (GNUTLS_E_SUCCESS == gnutls_credentials_set (*session, 537 GNUTLS_CRD_CERTIFICATE, 538 *xcred)) 539 { 540 return 0; 541 } 542 gnutls_certificate_free_credentials (*xcred); 543 } 544 } 545 gnutls_deinit (*session); 546 } 547 return 1; 548 } 549 550 551 unsigned int 552 teardown_session (gnutls_session_t session, 553 gnutls_certificate_credentials_t xcred) 554 { 555 gnutls_deinit (session); 556 gnutls_certificate_free_credentials (xcred); 557 return 0; 558 } 559 560 561 /* TODO test_wrap: change sig to (setup_func, test, va_list test_arg) */ 562 unsigned int 563 test_wrap (const char *test_name, unsigned int 564 (*test_function)(void *cls, uint16_t port, const char *cipher_suite, 565 int proto_version), void *cls, 566 uint16_t port, 567 unsigned int daemon_flags, const char *cipher_suite, 568 int proto_version, ...) 569 { 570 unsigned int ret; 571 va_list arg_list; 572 struct MHD_Daemon *d; 573 (void) cls; /* Unused. Silent compiler warning. */ 574 575 va_start (arg_list, proto_version); 576 port = setup_testcase (&d, port, daemon_flags, arg_list); 577 if (0 == port) 578 { 579 va_end (arg_list); 580 fprintf (stderr, "Failed to setup testcase %s\n", test_name); 581 return 1; 582 } 583 #if 0 584 fprintf (stdout, "running test: %s ", test_name); 585 #endif 586 ret = test_function (NULL, port, cipher_suite, proto_version); 587 #if 0 588 if (ret == 0) 589 { 590 fprintf (stdout, "[pass]\n"); 591 } 592 else 593 { 594 fprintf (stdout, "[fail]\n"); 595 } 596 #endif 597 teardown_testcase (d); 598 va_end (arg_list); 599 return ret; 600 } 601 602 603 static int inited_tls_is_gnutls = 0; 604 static int inited_tls_is_openssl = 0; 605 606 int 607 curl_tls_is_gnutls (void) 608 { 609 const char *tlslib; 610 if (inited_tls_is_gnutls) 611 return 1; 612 if (inited_tls_is_openssl) 613 return 0; 614 615 tlslib = curl_version_info (CURLVERSION_NOW)->ssl_version; 616 if (NULL == tlslib) 617 return 0; 618 if (0 == strncmp (tlslib, "GnuTLS/", 7)) 619 return 1; 620 621 /* Multi-backends handled during initialization by setting variable */ 622 return 0; 623 } 624 625 626 int 627 curl_tls_is_openssl (void) 628 { 629 const char *tlslib; 630 if (inited_tls_is_gnutls) 631 return 0; 632 if (inited_tls_is_openssl) 633 return 1; 634 635 tlslib = curl_version_info (CURLVERSION_NOW)->ssl_version; 636 if (NULL == tlslib) 637 return 0; 638 if (0 == strncmp (tlslib, "OpenSSL/", 8)) 639 return 1; 640 641 /* Multi-backends handled during initialization by setting variable */ 642 return 0; 643 } 644 645 646 int 647 curl_tls_is_nss (void) 648 { 649 const char *tlslib; 650 if (inited_tls_is_gnutls) 651 return 0; 652 if (inited_tls_is_openssl) 653 return 0; 654 655 tlslib = curl_version_info (CURLVERSION_NOW)->ssl_version; 656 if (NULL == tlslib) 657 return 0; 658 if (0 == strncmp (tlslib, "NSS/", 4)) 659 return 1; 660 661 /* Handle multi-backends with selected backend */ 662 if (NULL != strstr (tlslib," NSS/")) 663 return 1; 664 665 return 0; 666 } 667 668 669 int 670 curl_tls_is_schannel (void) 671 { 672 const char *tlslib; 673 if (inited_tls_is_gnutls) 674 return 0; 675 if (inited_tls_is_openssl) 676 return 0; 677 678 tlslib = curl_version_info (CURLVERSION_NOW)->ssl_version; 679 if (NULL == tlslib) 680 return 0; 681 if ((0 == strncmp (tlslib, "Schannel", 8)) || (0 == strncmp (tlslib, "WinSSL", 682 6))) 683 return 1; 684 685 /* Handle multi-backends with selected backend */ 686 if ((NULL != strstr (tlslib," Schannel")) || (NULL != strstr (tlslib, 687 " WinSSL"))) 688 return 1; 689 690 return 0; 691 } 692 693 694 int 695 curl_tls_is_sectransport (void) 696 { 697 const char *tlslib; 698 if (inited_tls_is_gnutls) 699 return 0; 700 if (inited_tls_is_openssl) 701 return 0; 702 703 tlslib = curl_version_info (CURLVERSION_NOW)->ssl_version; 704 if (NULL == tlslib) 705 return 0; 706 if (0 == strncmp (tlslib, "SecureTransport", 15)) 707 return 1; 708 709 /* Handle multi-backends with selected backend */ 710 if (NULL != strstr (tlslib," SecureTransport")) 711 return 1; 712 713 return 0; 714 } 715 716 717 int 718 testsuite_curl_global_init (void) 719 { 720 CURLcode res; 721 #if LIBCURL_VERSION_NUM >= 0x073800 722 if (CURLSSLSET_OK != curl_global_sslset (CURLSSLBACKEND_GNUTLS, NULL, NULL)) 723 { 724 CURLsslset e; 725 e = curl_global_sslset (CURLSSLBACKEND_OPENSSL, NULL, NULL); 726 if (CURLSSLSET_TOO_LATE == e) 727 fprintf (stderr, "WARNING: libcurl was already initialised.\n"); 728 else if (CURLSSLSET_OK == e) 729 inited_tls_is_openssl = 1; 730 } 731 else 732 inited_tls_is_gnutls = 1; 733 #endif /* LIBCURL_VERSION_NUM >= 0x07380 */ 734 res = curl_global_init (CURL_GLOBAL_ALL); 735 if (CURLE_OK != res) 736 { 737 fprintf (stderr, "libcurl initialisation error: %s\n", 738 curl_easy_strerror (res)); 739 return 0; 740 } 741 return 1; 742 } 743 744 745 /** 746 * Check whether program name contains specific @a marker string. 747 * Only last component in pathname is checked for marker presence, 748 * all leading directories names (if any) are ignored. Directories 749 * separators are handled correctly on both non-W32 and W32 750 * platforms. 751 * @param prog_name program name, may include path 752 * @param marker marker to look for. 753 * @return zero if any parameter is NULL or empty string or 754 * @a prog_name ends with slash or @a marker is not found in 755 * program name, non-zero if @a maker is found in program 756 * name. 757 */ 758 int 759 has_in_name (const char *prog_name, const char *marker) 760 { 761 size_t name_pos; 762 size_t pos; 763 764 if (! prog_name || ! marker || ! prog_name[0] || ! marker[0]) 765 return 0; 766 767 pos = 0; 768 name_pos = 0; 769 while (prog_name[pos]) 770 { 771 if ('/' == prog_name[pos]) 772 name_pos = pos + 1; 773 #if defined(_WIN32) || defined(__CYGWIN__) 774 else if ('\\' == prog_name[pos]) 775 name_pos = pos + 1; 776 #endif /* _WIN32 || __CYGWIN__ */ 777 pos++; 778 } 779 if (name_pos == pos) 780 return 0; 781 return strstr (prog_name + name_pos, marker) != (char *) 0; 782 }