libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

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                                           &copyBuffer))) ||
    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                                              &copyBuffer))) ||
    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 }