File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / vtls / gtls.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: /***************************************************************************
    2:  *                                  _   _ ____  _
    3:  *  Project                     ___| | | |  _ \| |
    4:  *                             / __| | | | |_) | |
    5:  *                            | (__| |_| |  _ <| |___
    6:  *                             \___|\___/|_| \_\_____|
    7:  *
    8:  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
    9:  *
   10:  * This software is licensed as described in the file COPYING, which
   11:  * you should have received as part of this distribution. The terms
   12:  * are also available at https://curl.haxx.se/docs/copyright.html.
   13:  *
   14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
   15:  * copies of the Software, and permit persons to whom the Software is
   16:  * furnished to do so, under the terms of the COPYING file.
   17:  *
   18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
   19:  * KIND, either express or implied.
   20:  *
   21:  ***************************************************************************/
   22: 
   23: /*
   24:  * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
   25:  * but vtls.c should ever call or use these functions.
   26:  *
   27:  * Note: don't use the GnuTLS' *_t variable type names in this source code,
   28:  * since they were not present in 1.0.X.
   29:  */
   30: 
   31: #include "curl_setup.h"
   32: 
   33: #ifdef USE_GNUTLS
   34: 
   35: #include <gnutls/abstract.h>
   36: #include <gnutls/gnutls.h>
   37: #include <gnutls/x509.h>
   38: 
   39: #ifdef USE_GNUTLS_NETTLE
   40: #include <gnutls/crypto.h>
   41: #include <nettle/md5.h>
   42: #include <nettle/sha2.h>
   43: #else
   44: #include <gcrypt.h>
   45: #endif
   46: 
   47: #include "urldata.h"
   48: #include "sendf.h"
   49: #include "inet_pton.h"
   50: #include "gtls.h"
   51: #include "vtls.h"
   52: #include "parsedate.h"
   53: #include "connect.h" /* for the connect timeout */
   54: #include "select.h"
   55: #include "strcase.h"
   56: #include "warnless.h"
   57: #include "x509asn1.h"
   58: #include "multiif.h"
   59: #include "curl_printf.h"
   60: #include "curl_memory.h"
   61: /* The last #include file should be: */
   62: #include "memdebug.h"
   63: 
   64: /* Enable GnuTLS debugging by defining GTLSDEBUG */
   65: /*#define GTLSDEBUG */
   66: 
   67: #ifdef GTLSDEBUG
   68: static void tls_log_func(int level, const char *str)
   69: {
   70:     fprintf(stderr, "|<%d>| %s", level, str);
   71: }
   72: #endif
   73: static bool gtls_inited = FALSE;
   74: 
   75: #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
   76: #error "too old GnuTLS version"
   77: #endif
   78: 
   79: # include <gnutls/ocsp.h>
   80: 
   81: struct ssl_backend_data {
   82:   gnutls_session_t session;
   83:   gnutls_certificate_credentials_t cred;
   84: #ifdef USE_TLS_SRP
   85:   gnutls_srp_client_credentials_t srp_client_cred;
   86: #endif
   87: };
   88: 
   89: static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
   90: {
   91:   curl_socket_t sock = *(curl_socket_t *)s;
   92:   ssize_t ret = swrite(sock, buf, len);
   93:   return ret;
   94: }
   95: 
   96: static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
   97: {
   98:   curl_socket_t sock = *(curl_socket_t *)s;
   99:   ssize_t ret = sread(sock, buf, len);
  100:   return ret;
  101: }
  102: 
  103: static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
  104: {
  105:   return gnutls_record_send((gnutls_session_t) s, buf, len);
  106: }
  107: 
  108: static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
  109: {
  110:   return gnutls_record_recv((gnutls_session_t) s, buf, len);
  111: }
  112: 
  113: /* Curl_gtls_init()
  114:  *
  115:  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
  116:  * are not thread-safe and thus this function itself is not thread-safe and
  117:  * must only be called from within curl_global_init() to keep the thread
  118:  * situation under control!
  119:  */
  120: static int Curl_gtls_init(void)
  121: {
  122:   int ret = 1;
  123:   if(!gtls_inited) {
  124:     ret = gnutls_global_init()?0:1;
  125: #ifdef GTLSDEBUG
  126:     gnutls_global_set_log_function(tls_log_func);
  127:     gnutls_global_set_log_level(2);
  128: #endif
  129:     gtls_inited = TRUE;
  130:   }
  131:   return ret;
  132: }
  133: 
  134: static void Curl_gtls_cleanup(void)
  135: {
  136:   if(gtls_inited) {
  137:     gnutls_global_deinit();
  138:     gtls_inited = FALSE;
  139:   }
  140: }
  141: 
  142: #ifndef CURL_DISABLE_VERBOSE_STRINGS
  143: static void showtime(struct Curl_easy *data,
  144:                      const char *text,
  145:                      time_t stamp)
  146: {
  147:   struct tm buffer;
  148:   const struct tm *tm = &buffer;
  149:   char str[96];
  150:   CURLcode result = Curl_gmtime(stamp, &buffer);
  151:   if(result)
  152:     return;
  153: 
  154:   msnprintf(str,
  155:             sizeof(str),
  156:             "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
  157:             text,
  158:             Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
  159:             tm->tm_mday,
  160:             Curl_month[tm->tm_mon],
  161:             tm->tm_year + 1900,
  162:             tm->tm_hour,
  163:             tm->tm_min,
  164:             tm->tm_sec);
  165:   infof(data, "%s\n", str);
  166: }
  167: #endif
  168: 
  169: static gnutls_datum_t load_file(const char *file)
  170: {
  171:   FILE *f;
  172:   gnutls_datum_t loaded_file = { NULL, 0 };
  173:   long filelen;
  174:   void *ptr;
  175: 
  176:   f = fopen(file, "rb");
  177:   if(!f)
  178:     return loaded_file;
  179:   if(fseek(f, 0, SEEK_END) != 0
  180:      || (filelen = ftell(f)) < 0
  181:      || fseek(f, 0, SEEK_SET) != 0
  182:      || !(ptr = malloc((size_t)filelen)))
  183:     goto out;
  184:   if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
  185:     free(ptr);
  186:     goto out;
  187:   }
  188: 
  189:   loaded_file.data = ptr;
  190:   loaded_file.size = (unsigned int)filelen;
  191: out:
  192:   fclose(f);
  193:   return loaded_file;
  194: }
  195: 
  196: static void unload_file(gnutls_datum_t data)
  197: {
  198:   free(data.data);
  199: }
  200: 
  201: 
  202: /* this function does a SSL/TLS (re-)handshake */
  203: static CURLcode handshake(struct connectdata *conn,
  204:                           int sockindex,
  205:                           bool duringconnect,
  206:                           bool nonblocking)
  207: {
  208:   struct Curl_easy *data = conn->data;
  209:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  210:   struct ssl_backend_data *backend = connssl->backend;
  211:   gnutls_session_t session = backend->session;
  212:   curl_socket_t sockfd = conn->sock[sockindex];
  213: 
  214:   for(;;) {
  215:     timediff_t timeout_ms;
  216:     int rc;
  217: 
  218:     /* check allowed time left */
  219:     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
  220: 
  221:     if(timeout_ms < 0) {
  222:       /* no need to continue if time already is up */
  223:       failf(data, "SSL connection timeout");
  224:       return CURLE_OPERATION_TIMEDOUT;
  225:     }
  226: 
  227:     /* if ssl is expecting something, check if it's available. */
  228:     if(connssl->connecting_state == ssl_connect_2_reading
  229:        || connssl->connecting_state == ssl_connect_2_writing) {
  230:       int what;
  231:       curl_socket_t writefd = ssl_connect_2_writing ==
  232:         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
  233:       curl_socket_t readfd = ssl_connect_2_reading ==
  234:         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
  235: 
  236:       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
  237:                                nonblocking?0:
  238:                                timeout_ms?(time_t)timeout_ms:1000);
  239:       if(what < 0) {
  240:         /* fatal error */
  241:         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
  242:         return CURLE_SSL_CONNECT_ERROR;
  243:       }
  244:       else if(0 == what) {
  245:         if(nonblocking)
  246:           return CURLE_OK;
  247:         else if(timeout_ms) {
  248:           /* timeout */
  249:           failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
  250:           return CURLE_OPERATION_TIMEDOUT;
  251:         }
  252:       }
  253:       /* socket is readable or writable */
  254:     }
  255: 
  256:     rc = gnutls_handshake(session);
  257: 
  258:     if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
  259:       connssl->connecting_state =
  260:         gnutls_record_get_direction(session)?
  261:         ssl_connect_2_writing:ssl_connect_2_reading;
  262:       continue;
  263:     }
  264:     else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
  265:       const char *strerr = NULL;
  266: 
  267:       if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
  268:         int alert = gnutls_alert_get(session);
  269:         strerr = gnutls_alert_get_name(alert);
  270:       }
  271: 
  272:       if(strerr == NULL)
  273:         strerr = gnutls_strerror(rc);
  274: 
  275:       infof(data, "gnutls_handshake() warning: %s\n", strerr);
  276:       continue;
  277:     }
  278:     else if(rc < 0) {
  279:       const char *strerr = NULL;
  280: 
  281:       if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
  282:         int alert = gnutls_alert_get(session);
  283:         strerr = gnutls_alert_get_name(alert);
  284:       }
  285: 
  286:       if(strerr == NULL)
  287:         strerr = gnutls_strerror(rc);
  288: 
  289:       failf(data, "gnutls_handshake() failed: %s", strerr);
  290:       return CURLE_SSL_CONNECT_ERROR;
  291:     }
  292: 
  293:     /* Reset our connect state machine */
  294:     connssl->connecting_state = ssl_connect_1;
  295:     return CURLE_OK;
  296:   }
  297: }
  298: 
  299: static gnutls_x509_crt_fmt_t do_file_type(const char *type)
  300: {
  301:   if(!type || !type[0])
  302:     return GNUTLS_X509_FMT_PEM;
  303:   if(strcasecompare(type, "PEM"))
  304:     return GNUTLS_X509_FMT_PEM;
  305:   if(strcasecompare(type, "DER"))
  306:     return GNUTLS_X509_FMT_DER;
  307:   return -1;
  308: }
  309: 
  310: #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
  311: /* If GnuTLS was compiled without support for SRP it will error out if SRP is
  312:    requested in the priority string, so treat it specially
  313:  */
  314: #define GNUTLS_SRP "+SRP"
  315: 
  316: static CURLcode
  317: set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
  318: {
  319:   struct Curl_easy *data = conn->data;
  320:   long ssl_version = SSL_CONN_CONFIG(version);
  321:   long ssl_version_max = SSL_CONN_CONFIG(version_max);
  322: 
  323:   if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
  324:     ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
  325:   }
  326:   switch(ssl_version | ssl_version_max) {
  327:   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
  328:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  329:       "+VERS-TLS1.0";
  330:     return CURLE_OK;
  331:   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
  332:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  333:       "+VERS-TLS1.0:+VERS-TLS1.1";
  334:     return CURLE_OK;
  335:   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
  336:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  337:       "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2";
  338:     return CURLE_OK;
  339:   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
  340:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  341:       "+VERS-TLS1.1";
  342:     return CURLE_OK;
  343:   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
  344:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  345:       "+VERS-TLS1.1:+VERS-TLS1.2";
  346:     return CURLE_OK;
  347:   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
  348:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  349:       "+VERS-TLS1.2";
  350:     return CURLE_OK;
  351:   case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
  352:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  353:       "+VERS-TLS1.3";
  354:     return CURLE_OK;
  355:   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
  356:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  357:       "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2"
  358:       ":+VERS-TLS1.3";
  359:     return CURLE_OK;
  360:   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
  361:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  362:       "+VERS-TLS1.1:+VERS-TLS1.2"
  363:       ":+VERS-TLS1.3";
  364:     return CURLE_OK;
  365:   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
  366:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  367:       "+VERS-TLS1.2"
  368:       ":+VERS-TLS1.3";
  369:     return CURLE_OK;
  370:   case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT:
  371:     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
  372:       "+VERS-TLS1.2"
  373:       ":+VERS-TLS1.3";
  374:     return CURLE_OK;
  375:   }
  376: 
  377:   failf(data, "GnuTLS: cannot set ssl protocol");
  378:   return CURLE_SSL_CONNECT_ERROR;
  379: }
  380: 
  381: static CURLcode
  382: gtls_connect_step1(struct connectdata *conn,
  383:                    int sockindex)
  384: {
  385:   struct Curl_easy *data = conn->data;
  386:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  387:   struct ssl_backend_data *backend = connssl->backend;
  388:   unsigned int init_flags;
  389:   gnutls_session_t session;
  390:   int rc;
  391:   bool sni = TRUE; /* default is SNI enabled */
  392:   void *transport_ptr = NULL;
  393:   gnutls_push_func gnutls_transport_push = NULL;
  394:   gnutls_pull_func gnutls_transport_pull = NULL;
  395: #ifdef ENABLE_IPV6
  396:   struct in6_addr addr;
  397: #else
  398:   struct in_addr addr;
  399: #endif
  400:   const char *prioritylist;
  401:   const char *err = NULL;
  402:   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
  403:     conn->host.name;
  404: 
  405:   if(connssl->state == ssl_connection_complete)
  406:     /* to make us tolerant against being called more than once for the
  407:        same connection */
  408:     return CURLE_OK;
  409: 
  410:   if(!gtls_inited)
  411:     Curl_gtls_init();
  412: 
  413:   if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
  414:     failf(data, "GnuTLS does not support SSLv2");
  415:     return CURLE_SSL_CONNECT_ERROR;
  416:   }
  417:   else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
  418:     sni = FALSE; /* SSLv3 has no SNI */
  419: 
  420:   /* allocate a cred struct */
  421:   rc = gnutls_certificate_allocate_credentials(&backend->cred);
  422:   if(rc != GNUTLS_E_SUCCESS) {
  423:     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
  424:     return CURLE_SSL_CONNECT_ERROR;
  425:   }
  426: 
  427: #ifdef USE_TLS_SRP
  428:   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
  429:     infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
  430: 
  431:     rc = gnutls_srp_allocate_client_credentials(
  432:            &backend->srp_client_cred);
  433:     if(rc != GNUTLS_E_SUCCESS) {
  434:       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
  435:             gnutls_strerror(rc));
  436:       return CURLE_OUT_OF_MEMORY;
  437:     }
  438: 
  439:     rc = gnutls_srp_set_client_credentials(backend->srp_client_cred,
  440:                                            SSL_SET_OPTION(username),
  441:                                            SSL_SET_OPTION(password));
  442:     if(rc != GNUTLS_E_SUCCESS) {
  443:       failf(data, "gnutls_srp_set_client_cred() failed: %s",
  444:             gnutls_strerror(rc));
  445:       return CURLE_BAD_FUNCTION_ARGUMENT;
  446:     }
  447:   }
  448: #endif
  449: 
  450:   if(SSL_CONN_CONFIG(CAfile)) {
  451:     /* set the trusted CA cert bundle file */
  452:     gnutls_certificate_set_verify_flags(backend->cred,
  453:                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
  454: 
  455:     rc = gnutls_certificate_set_x509_trust_file(backend->cred,
  456:                                                 SSL_CONN_CONFIG(CAfile),
  457:                                                 GNUTLS_X509_FMT_PEM);
  458:     if(rc < 0) {
  459:       infof(data, "error reading ca cert file %s (%s)\n",
  460:             SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
  461:       if(SSL_CONN_CONFIG(verifypeer))
  462:         return CURLE_SSL_CACERT_BADFILE;
  463:     }
  464:     else
  465:       infof(data, "found %d certificates in %s\n", rc,
  466:             SSL_CONN_CONFIG(CAfile));
  467:   }
  468: 
  469:   if(SSL_CONN_CONFIG(CApath)) {
  470:     /* set the trusted CA cert directory */
  471:     rc = gnutls_certificate_set_x509_trust_dir(backend->cred,
  472:                                                SSL_CONN_CONFIG(CApath),
  473:                                                GNUTLS_X509_FMT_PEM);
  474:     if(rc < 0) {
  475:       infof(data, "error reading ca cert file %s (%s)\n",
  476:             SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
  477:       if(SSL_CONN_CONFIG(verifypeer))
  478:         return CURLE_SSL_CACERT_BADFILE;
  479:     }
  480:     else
  481:       infof(data, "found %d certificates in %s\n",
  482:             rc, SSL_CONN_CONFIG(CApath));
  483:   }
  484: 
  485: #ifdef CURL_CA_FALLBACK
  486:   /* use system ca certificate store as fallback */
  487:   if(SSL_CONN_CONFIG(verifypeer) &&
  488:      !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
  489:     gnutls_certificate_set_x509_system_trust(backend->cred);
  490:   }
  491: #endif
  492: 
  493:   if(SSL_SET_OPTION(CRLfile)) {
  494:     /* set the CRL list file */
  495:     rc = gnutls_certificate_set_x509_crl_file(backend->cred,
  496:                                               SSL_SET_OPTION(CRLfile),
  497:                                               GNUTLS_X509_FMT_PEM);
  498:     if(rc < 0) {
  499:       failf(data, "error reading crl file %s (%s)",
  500:             SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
  501:       return CURLE_SSL_CRL_BADFILE;
  502:     }
  503:     else
  504:       infof(data, "found %d CRL in %s\n",
  505:             rc, SSL_SET_OPTION(CRLfile));
  506:   }
  507: 
  508:   /* Initialize TLS session as a client */
  509:   init_flags = GNUTLS_CLIENT;
  510: 
  511: #if defined(GNUTLS_FORCE_CLIENT_CERT)
  512:   init_flags |= GNUTLS_FORCE_CLIENT_CERT;
  513: #endif
  514: 
  515: #if defined(GNUTLS_NO_TICKETS)
  516:   /* Disable TLS session tickets */
  517:   init_flags |= GNUTLS_NO_TICKETS;
  518: #endif
  519: 
  520:   rc = gnutls_init(&backend->session, init_flags);
  521:   if(rc != GNUTLS_E_SUCCESS) {
  522:     failf(data, "gnutls_init() failed: %d", rc);
  523:     return CURLE_SSL_CONNECT_ERROR;
  524:   }
  525: 
  526:   /* convenient assign */
  527:   session = backend->session;
  528: 
  529:   if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
  530: #ifdef ENABLE_IPV6
  531:      (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
  532: #endif
  533:      sni &&
  534:      (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
  535:                              strlen(hostname)) < 0))
  536:     infof(data, "WARNING: failed to configure server name indication (SNI) "
  537:           "TLS extension\n");
  538: 
  539:   /* Use default priorities */
  540:   rc = gnutls_set_default_priority(session);
  541:   if(rc != GNUTLS_E_SUCCESS)
  542:     return CURLE_SSL_CONNECT_ERROR;
  543: 
  544:   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
  545:    * removed if a run-time error indicates that SRP is not supported by this
  546:    * GnuTLS version */
  547:   switch(SSL_CONN_CONFIG(version)) {
  548:     case CURL_SSLVERSION_SSLv3:
  549:       prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
  550:       break;
  551:     case CURL_SSLVERSION_DEFAULT:
  552:     case CURL_SSLVERSION_TLSv1:
  553:       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0"
  554: #ifdef HAS_TLS13
  555:                      ":+VERS-TLS1.3"
  556: #endif
  557:                      ;
  558:       break;
  559:     case CURL_SSLVERSION_TLSv1_0:
  560:     case CURL_SSLVERSION_TLSv1_1:
  561:     case CURL_SSLVERSION_TLSv1_2:
  562:     case CURL_SSLVERSION_TLSv1_3:
  563:       {
  564:         CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
  565:         if(result != CURLE_OK)
  566:           return result;
  567:         break;
  568:       }
  569:     case CURL_SSLVERSION_SSLv2:
  570:       failf(data, "GnuTLS does not support SSLv2");
  571:       return CURLE_SSL_CONNECT_ERROR;
  572:     default:
  573:       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
  574:       return CURLE_SSL_CONNECT_ERROR;
  575:   }
  576: 
  577: #ifdef USE_TLS_SRP
  578:   /* Only add SRP to the cipher list if SRP is requested. Otherwise
  579:    * GnuTLS will disable TLS 1.3 support. */
  580:   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
  581:     size_t len = strlen(prioritylist);
  582: 
  583:     char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
  584:     if(!prioritysrp)
  585:       return CURLE_OUT_OF_MEMORY;
  586:     strcpy(prioritysrp, prioritylist);
  587:     strcpy(prioritysrp + len, ":" GNUTLS_SRP);
  588: 
  589:     rc = gnutls_priority_set_direct(session, prioritysrp, &err);
  590:     free(prioritysrp);
  591: 
  592:     if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
  593:       infof(data, "This GnuTLS does not support SRP\n");
  594:     }
  595:   }
  596:   else {
  597: #endif
  598:     rc = gnutls_priority_set_direct(session, prioritylist, &err);
  599: #ifdef USE_TLS_SRP
  600:   }
  601: #endif
  602: 
  603:   if(rc != GNUTLS_E_SUCCESS) {
  604:     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
  605:           rc, err);
  606:     return CURLE_SSL_CONNECT_ERROR;
  607:   }
  608: 
  609:   if(conn->bits.tls_enable_alpn) {
  610:     int cur = 0;
  611:     gnutls_datum_t protocols[2];
  612: 
  613: #ifdef USE_NGHTTP2
  614:     if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
  615:        (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
  616:       protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
  617:       protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
  618:       cur++;
  619:       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
  620:     }
  621: #endif
  622: 
  623:     protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
  624:     protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
  625:     cur++;
  626:     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
  627: 
  628:     gnutls_alpn_set_protocols(session, protocols, cur, 0);
  629:   }
  630: 
  631:   if(SSL_SET_OPTION(cert)) {
  632:     if(SSL_SET_OPTION(key_passwd)) {
  633:       const unsigned int supported_key_encryption_algorithms =
  634:         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
  635:         GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
  636:         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
  637:         GNUTLS_PKCS_USE_PBES2_AES_256;
  638:       rc = gnutls_certificate_set_x509_key_file2(
  639:            backend->cred,
  640:            SSL_SET_OPTION(cert),
  641:            SSL_SET_OPTION(key) ?
  642:            SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
  643:            do_file_type(SSL_SET_OPTION(cert_type)),
  644:            SSL_SET_OPTION(key_passwd),
  645:            supported_key_encryption_algorithms);
  646:       if(rc != GNUTLS_E_SUCCESS) {
  647:         failf(data,
  648:               "error reading X.509 potentially-encrypted key file: %s",
  649:               gnutls_strerror(rc));
  650:         return CURLE_SSL_CONNECT_ERROR;
  651:       }
  652:     }
  653:     else {
  654:       if(gnutls_certificate_set_x509_key_file(
  655:            backend->cred,
  656:            SSL_SET_OPTION(cert),
  657:            SSL_SET_OPTION(key) ?
  658:            SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
  659:            do_file_type(SSL_SET_OPTION(cert_type)) ) !=
  660:          GNUTLS_E_SUCCESS) {
  661:         failf(data, "error reading X.509 key or certificate file");
  662:         return CURLE_SSL_CONNECT_ERROR;
  663:       }
  664:     }
  665:   }
  666: 
  667: #ifdef USE_TLS_SRP
  668:   /* put the credentials to the current session */
  669:   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
  670:     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
  671:                                 backend->srp_client_cred);
  672:     if(rc != GNUTLS_E_SUCCESS) {
  673:       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
  674:       return CURLE_SSL_CONNECT_ERROR;
  675:     }
  676:   }
  677:   else
  678: #endif
  679:   {
  680:     rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
  681:                                 backend->cred);
  682:     if(rc != GNUTLS_E_SUCCESS) {
  683:       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
  684:       return CURLE_SSL_CONNECT_ERROR;
  685:     }
  686:   }
  687: 
  688:   if(conn->proxy_ssl[sockindex].use) {
  689:     transport_ptr = conn->proxy_ssl[sockindex].backend->session;
  690:     gnutls_transport_push = Curl_gtls_push_ssl;
  691:     gnutls_transport_pull = Curl_gtls_pull_ssl;
  692:   }
  693:   else {
  694:     /* file descriptor for the socket */
  695:     transport_ptr = &conn->sock[sockindex];
  696:     gnutls_transport_push = Curl_gtls_push;
  697:     gnutls_transport_pull = Curl_gtls_pull;
  698:   }
  699: 
  700:   /* set the connection handle */
  701:   gnutls_transport_set_ptr(session, transport_ptr);
  702: 
  703:   /* register callback functions to send and receive data. */
  704:   gnutls_transport_set_push_function(session, gnutls_transport_push);
  705:   gnutls_transport_set_pull_function(session, gnutls_transport_pull);
  706: 
  707:   if(SSL_CONN_CONFIG(verifystatus)) {
  708:     rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
  709:     if(rc != GNUTLS_E_SUCCESS) {
  710:       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
  711:       return CURLE_SSL_CONNECT_ERROR;
  712:     }
  713:   }
  714: 
  715:   /* This might be a reconnect, so we check for a session ID in the cache
  716:      to speed up things */
  717:   if(SSL_SET_OPTION(primary.sessionid)) {
  718:     void *ssl_sessionid;
  719:     size_t ssl_idsize;
  720: 
  721:     Curl_ssl_sessionid_lock(conn);
  722:     if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
  723:       /* we got a session id, use it! */
  724:       gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
  725: 
  726:       /* Informational message */
  727:       infof(data, "SSL re-using session ID\n");
  728:     }
  729:     Curl_ssl_sessionid_unlock(conn);
  730:   }
  731: 
  732:   return CURLE_OK;
  733: }
  734: 
  735: static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
  736:                                     gnutls_x509_crt_t cert,
  737:                                     const char *pinnedpubkey)
  738: {
  739:   /* Scratch */
  740:   size_t len1 = 0, len2 = 0;
  741:   unsigned char *buff1 = NULL;
  742: 
  743:   gnutls_pubkey_t key = NULL;
  744: 
  745:   /* Result is returned to caller */
  746:   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
  747: 
  748:   /* if a path wasn't specified, don't pin */
  749:   if(NULL == pinnedpubkey)
  750:     return CURLE_OK;
  751: 
  752:   if(NULL == cert)
  753:     return result;
  754: 
  755:   do {
  756:     int ret;
  757: 
  758:     /* Begin Gyrations to get the public key     */
  759:     gnutls_pubkey_init(&key);
  760: 
  761:     ret = gnutls_pubkey_import_x509(key, cert, 0);
  762:     if(ret < 0)
  763:       break; /* failed */
  764: 
  765:     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
  766:     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
  767:       break; /* failed */
  768: 
  769:     buff1 = malloc(len1);
  770:     if(NULL == buff1)
  771:       break; /* failed */
  772: 
  773:     len2 = len1;
  774: 
  775:     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
  776:     if(ret < 0 || len1 != len2)
  777:       break; /* failed */
  778: 
  779:     /* End Gyrations */
  780: 
  781:     /* The one good exit point */
  782:     result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
  783:   } while(0);
  784: 
  785:   if(NULL != key)
  786:     gnutls_pubkey_deinit(key);
  787: 
  788:   Curl_safefree(buff1);
  789: 
  790:   return result;
  791: }
  792: 
  793: static Curl_recv gtls_recv;
  794: static Curl_send gtls_send;
  795: 
  796: static CURLcode
  797: gtls_connect_step3(struct connectdata *conn,
  798:                    int sockindex)
  799: {
  800:   unsigned int cert_list_size;
  801:   const gnutls_datum_t *chainp;
  802:   unsigned int verify_status = 0;
  803:   gnutls_x509_crt_t x509_cert, x509_issuer;
  804:   gnutls_datum_t issuerp;
  805:   gnutls_datum_t certfields;
  806:   char certname[65] = ""; /* limited to 64 chars by ASN.1 */
  807:   size_t size;
  808:   time_t certclock;
  809:   const char *ptr;
  810:   struct Curl_easy *data = conn->data;
  811:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  812:   struct ssl_backend_data *backend = connssl->backend;
  813:   gnutls_session_t session = backend->session;
  814:   int rc;
  815:   gnutls_datum_t proto;
  816:   CURLcode result = CURLE_OK;
  817: #ifndef CURL_DISABLE_VERBOSE_STRINGS
  818:   unsigned int algo;
  819:   unsigned int bits;
  820:   gnutls_protocol_t version = gnutls_protocol_get_version(session);
  821: #endif
  822:   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
  823:     conn->host.name;
  824: 
  825:   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
  826:   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
  827:                                      gnutls_cipher_get(session),
  828:                                      gnutls_mac_get(session));
  829: 
  830:   infof(data, "SSL connection using %s / %s\n",
  831:         gnutls_protocol_get_name(version), ptr);
  832: 
  833:   /* This function will return the peer's raw certificate (chain) as sent by
  834:      the peer. These certificates are in raw format (DER encoded for
  835:      X.509). In case of a X.509 then a certificate list may be present. The
  836:      first certificate in the list is the peer's certificate, following the
  837:      issuer's certificate, then the issuer's issuer etc. */
  838: 
  839:   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
  840:   if(!chainp) {
  841:     if(SSL_CONN_CONFIG(verifypeer) ||
  842:        SSL_CONN_CONFIG(verifyhost) ||
  843:        SSL_SET_OPTION(issuercert)) {
  844: #ifdef USE_TLS_SRP
  845:       if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
  846:          && SSL_SET_OPTION(username) != NULL
  847:          && !SSL_CONN_CONFIG(verifypeer)
  848:          && gnutls_cipher_get(session)) {
  849:         /* no peer cert, but auth is ok if we have SRP user and cipher and no
  850:            peer verify */
  851:       }
  852:       else {
  853: #endif
  854:         failf(data, "failed to get server cert");
  855:         return CURLE_PEER_FAILED_VERIFICATION;
  856: #ifdef USE_TLS_SRP
  857:       }
  858: #endif
  859:     }
  860:     infof(data, "\t common name: WARNING couldn't obtain\n");
  861:   }
  862: 
  863:   if(data->set.ssl.certinfo && chainp) {
  864:     unsigned int i;
  865: 
  866:     result = Curl_ssl_init_certinfo(data, cert_list_size);
  867:     if(result)
  868:       return result;
  869: 
  870:     for(i = 0; i < cert_list_size; i++) {
  871:       const char *beg = (const char *) chainp[i].data;
  872:       const char *end = beg + chainp[i].size;
  873: 
  874:       result = Curl_extract_certinfo(conn, i, beg, end);
  875:       if(result)
  876:         return result;
  877:     }
  878:   }
  879: 
  880:   if(SSL_CONN_CONFIG(verifypeer)) {
  881:     /* This function will try to verify the peer's certificate and return its
  882:        status (trusted, invalid etc.). The value of status should be one or
  883:        more of the gnutls_certificate_status_t enumerated elements bitwise
  884:        or'd. To avoid denial of service attacks some default upper limits
  885:        regarding the certificate key size and chain size are set. To override
  886:        them use gnutls_certificate_set_verify_limits(). */
  887: 
  888:     rc = gnutls_certificate_verify_peers2(session, &verify_status);
  889:     if(rc < 0) {
  890:       failf(data, "server cert verify failed: %d", rc);
  891:       return CURLE_SSL_CONNECT_ERROR;
  892:     }
  893: 
  894:     /* verify_status is a bitmask of gnutls_certificate_status bits */
  895:     if(verify_status & GNUTLS_CERT_INVALID) {
  896:       if(SSL_CONN_CONFIG(verifypeer)) {
  897:         failf(data, "server certificate verification failed. CAfile: %s "
  898:               "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
  899:               "none",
  900:               SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
  901:         return CURLE_PEER_FAILED_VERIFICATION;
  902:       }
  903:       else
  904:         infof(data, "\t server certificate verification FAILED\n");
  905:     }
  906:     else
  907:       infof(data, "\t server certificate verification OK\n");
  908:   }
  909:   else
  910:     infof(data, "\t server certificate verification SKIPPED\n");
  911: 
  912:   if(SSL_CONN_CONFIG(verifystatus)) {
  913:     if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
  914:       gnutls_datum_t status_request;
  915:       gnutls_ocsp_resp_t ocsp_resp;
  916: 
  917:       gnutls_ocsp_cert_status_t status;
  918:       gnutls_x509_crl_reason_t reason;
  919: 
  920:       rc = gnutls_ocsp_status_request_get(session, &status_request);
  921: 
  922:       infof(data, "\t server certificate status verification FAILED\n");
  923: 
  924:       if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
  925:         failf(data, "No OCSP response received");
  926:         return CURLE_SSL_INVALIDCERTSTATUS;
  927:       }
  928: 
  929:       if(rc < 0) {
  930:         failf(data, "Invalid OCSP response received");
  931:         return CURLE_SSL_INVALIDCERTSTATUS;
  932:       }
  933: 
  934:       gnutls_ocsp_resp_init(&ocsp_resp);
  935: 
  936:       rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
  937:       if(rc < 0) {
  938:         failf(data, "Invalid OCSP response received");
  939:         return CURLE_SSL_INVALIDCERTSTATUS;
  940:       }
  941: 
  942:       (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
  943:                                         &status, NULL, NULL, NULL, &reason);
  944: 
  945:       switch(status) {
  946:       case GNUTLS_OCSP_CERT_GOOD:
  947:         break;
  948: 
  949:       case GNUTLS_OCSP_CERT_REVOKED: {
  950:         const char *crl_reason;
  951: 
  952:         switch(reason) {
  953:           default:
  954:           case GNUTLS_X509_CRLREASON_UNSPECIFIED:
  955:             crl_reason = "unspecified reason";
  956:             break;
  957: 
  958:           case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
  959:             crl_reason = "private key compromised";
  960:             break;
  961: 
  962:           case GNUTLS_X509_CRLREASON_CACOMPROMISE:
  963:             crl_reason = "CA compromised";
  964:             break;
  965: 
  966:           case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
  967:             crl_reason = "affiliation has changed";
  968:             break;
  969: 
  970:           case GNUTLS_X509_CRLREASON_SUPERSEDED:
  971:             crl_reason = "certificate superseded";
  972:             break;
  973: 
  974:           case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
  975:             crl_reason = "operation has ceased";
  976:             break;
  977: 
  978:           case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
  979:             crl_reason = "certificate is on hold";
  980:             break;
  981: 
  982:           case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
  983:             crl_reason = "will be removed from delta CRL";
  984:             break;
  985: 
  986:           case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
  987:             crl_reason = "privilege withdrawn";
  988:             break;
  989: 
  990:           case GNUTLS_X509_CRLREASON_AACOMPROMISE:
  991:             crl_reason = "AA compromised";
  992:             break;
  993:         }
  994: 
  995:         failf(data, "Server certificate was revoked: %s", crl_reason);
  996:         break;
  997:       }
  998: 
  999:       default:
 1000:       case GNUTLS_OCSP_CERT_UNKNOWN:
 1001:         failf(data, "Server certificate status is unknown");
 1002:         break;
 1003:       }
 1004: 
 1005:       gnutls_ocsp_resp_deinit(ocsp_resp);
 1006: 
 1007:       return CURLE_SSL_INVALIDCERTSTATUS;
 1008:     }
 1009:     else
 1010:       infof(data, "\t server certificate status verification OK\n");
 1011:   }
 1012:   else
 1013:     infof(data, "\t server certificate status verification SKIPPED\n");
 1014: 
 1015:   /* initialize an X.509 certificate structure. */
 1016:   gnutls_x509_crt_init(&x509_cert);
 1017: 
 1018:   if(chainp)
 1019:     /* convert the given DER or PEM encoded Certificate to the native
 1020:        gnutls_x509_crt_t format */
 1021:     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
 1022: 
 1023:   if(SSL_SET_OPTION(issuercert)) {
 1024:     gnutls_x509_crt_init(&x509_issuer);
 1025:     issuerp = load_file(SSL_SET_OPTION(issuercert));
 1026:     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
 1027:     rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
 1028:     gnutls_x509_crt_deinit(x509_issuer);
 1029:     unload_file(issuerp);
 1030:     if(rc <= 0) {
 1031:       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
 1032:             SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
 1033:       gnutls_x509_crt_deinit(x509_cert);
 1034:       return CURLE_SSL_ISSUER_ERROR;
 1035:     }
 1036:     infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
 1037:           SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
 1038:   }
 1039: 
 1040:   size = sizeof(certname);
 1041:   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
 1042:                                      0, /* the first and only one */
 1043:                                      FALSE,
 1044:                                      certname,
 1045:                                      &size);
 1046:   if(rc) {
 1047:     infof(data, "error fetching CN from cert:%s\n",
 1048:           gnutls_strerror(rc));
 1049:   }
 1050: 
 1051:   /* This function will check if the given certificate's subject matches the
 1052:      given hostname. This is a basic implementation of the matching described
 1053:      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
 1054:      alternative name PKIX extension. Returns non zero on success, and zero on
 1055:      failure. */
 1056:   rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
 1057: #if GNUTLS_VERSION_NUMBER < 0x030306
 1058:   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
 1059:      addresses. */
 1060:   if(!rc) {
 1061: #ifdef ENABLE_IPV6
 1062:     #define use_addr in6_addr
 1063: #else
 1064:     #define use_addr in_addr
 1065: #endif
 1066:     unsigned char addrbuf[sizeof(struct use_addr)];
 1067:     size_t addrlen = 0;
 1068: 
 1069:     if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
 1070:       addrlen = 4;
 1071: #ifdef ENABLE_IPV6
 1072:     else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
 1073:       addrlen = 16;
 1074: #endif
 1075: 
 1076:     if(addrlen) {
 1077:       unsigned char certaddr[sizeof(struct use_addr)];
 1078:       int i;
 1079: 
 1080:       for(i = 0; ; i++) {
 1081:         size_t certaddrlen = sizeof(certaddr);
 1082:         int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
 1083:                                                        &certaddrlen, NULL);
 1084:         /* If this happens, it wasn't an IP address. */
 1085:         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
 1086:           continue;
 1087:         if(ret < 0)
 1088:           break;
 1089:         if(ret != GNUTLS_SAN_IPADDRESS)
 1090:           continue;
 1091:         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
 1092:           rc = 1;
 1093:           break;
 1094:         }
 1095:       }
 1096:     }
 1097:   }
 1098: #endif
 1099:   if(!rc) {
 1100:     const char * const dispname = SSL_IS_PROXY() ?
 1101:       conn->http_proxy.host.dispname : conn->host.dispname;
 1102: 
 1103:     if(SSL_CONN_CONFIG(verifyhost)) {
 1104:       failf(data, "SSL: certificate subject name (%s) does not match "
 1105:             "target host name '%s'", certname, dispname);
 1106:       gnutls_x509_crt_deinit(x509_cert);
 1107:       return CURLE_PEER_FAILED_VERIFICATION;
 1108:     }
 1109:     else
 1110:       infof(data, "\t common name: %s (does not match '%s')\n",
 1111:             certname, dispname);
 1112:   }
 1113:   else
 1114:     infof(data, "\t common name: %s (matched)\n", certname);
 1115: 
 1116:   /* Check for time-based validity */
 1117:   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
 1118: 
 1119:   if(certclock == (time_t)-1) {
 1120:     if(SSL_CONN_CONFIG(verifypeer)) {
 1121:       failf(data, "server cert expiration date verify failed");
 1122:       gnutls_x509_crt_deinit(x509_cert);
 1123:       return CURLE_SSL_CONNECT_ERROR;
 1124:     }
 1125:     else
 1126:       infof(data, "\t server certificate expiration date verify FAILED\n");
 1127:   }
 1128:   else {
 1129:     if(certclock < time(NULL)) {
 1130:       if(SSL_CONN_CONFIG(verifypeer)) {
 1131:         failf(data, "server certificate expiration date has passed.");
 1132:         gnutls_x509_crt_deinit(x509_cert);
 1133:         return CURLE_PEER_FAILED_VERIFICATION;
 1134:       }
 1135:       else
 1136:         infof(data, "\t server certificate expiration date FAILED\n");
 1137:     }
 1138:     else
 1139:       infof(data, "\t server certificate expiration date OK\n");
 1140:   }
 1141: 
 1142:   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
 1143: 
 1144:   if(certclock == (time_t)-1) {
 1145:     if(SSL_CONN_CONFIG(verifypeer)) {
 1146:       failf(data, "server cert activation date verify failed");
 1147:       gnutls_x509_crt_deinit(x509_cert);
 1148:       return CURLE_SSL_CONNECT_ERROR;
 1149:     }
 1150:     else
 1151:       infof(data, "\t server certificate activation date verify FAILED\n");
 1152:   }
 1153:   else {
 1154:     if(certclock > time(NULL)) {
 1155:       if(SSL_CONN_CONFIG(verifypeer)) {
 1156:         failf(data, "server certificate not activated yet.");
 1157:         gnutls_x509_crt_deinit(x509_cert);
 1158:         return CURLE_PEER_FAILED_VERIFICATION;
 1159:       }
 1160:       else
 1161:         infof(data, "\t server certificate activation date FAILED\n");
 1162:     }
 1163:     else
 1164:       infof(data, "\t server certificate activation date OK\n");
 1165:   }
 1166: 
 1167:   ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
 1168:         data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
 1169:   if(ptr) {
 1170:     result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
 1171:     if(result != CURLE_OK) {
 1172:       failf(data, "SSL: public key does not match pinned public key!");
 1173:       gnutls_x509_crt_deinit(x509_cert);
 1174:       return result;
 1175:     }
 1176:   }
 1177: 
 1178:   /* Show:
 1179: 
 1180:   - subject
 1181:   - start date
 1182:   - expire date
 1183:   - common name
 1184:   - issuer
 1185: 
 1186:   */
 1187: 
 1188: #ifndef CURL_DISABLE_VERBOSE_STRINGS
 1189:   /* public key algorithm's parameters */
 1190:   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
 1191:   infof(data, "\t certificate public key: %s\n",
 1192:         gnutls_pk_algorithm_get_name(algo));
 1193: 
 1194:   /* version of the X.509 certificate. */
 1195:   infof(data, "\t certificate version: #%d\n",
 1196:         gnutls_x509_crt_get_version(x509_cert));
 1197: 
 1198: 
 1199:   rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
 1200:   if(rc != 0)
 1201:     return CURLE_OUT_OF_MEMORY;
 1202:   infof(data, "\t subject: %s\n", certfields.data);
 1203: 
 1204:   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
 1205:   showtime(data, "start date", certclock);
 1206: 
 1207:   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
 1208:   showtime(data, "expire date", certclock);
 1209: 
 1210:   rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
 1211:   if(rc != 0)
 1212:     return CURLE_OUT_OF_MEMORY;
 1213:   infof(data, "\t issuer: %s\n", certfields.data);
 1214: #endif
 1215: 
 1216:   gnutls_x509_crt_deinit(x509_cert);
 1217: 
 1218:   if(conn->bits.tls_enable_alpn) {
 1219:     rc = gnutls_alpn_get_selected_protocol(session, &proto);
 1220:     if(rc == 0) {
 1221:       infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
 1222:           proto.data);
 1223: 
 1224: #ifdef USE_NGHTTP2
 1225:       if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
 1226:          !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
 1227:                  NGHTTP2_PROTO_VERSION_ID_LEN)) {
 1228:         conn->negnpn = CURL_HTTP_VERSION_2;
 1229:       }
 1230:       else
 1231: #endif
 1232:       if(proto.size == ALPN_HTTP_1_1_LENGTH &&
 1233:          !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
 1234:         conn->negnpn = CURL_HTTP_VERSION_1_1;
 1235:       }
 1236:     }
 1237:     else
 1238:       infof(data, "ALPN, server did not agree to a protocol\n");
 1239: 
 1240:     Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
 1241:                         BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
 1242:   }
 1243: 
 1244:   conn->ssl[sockindex].state = ssl_connection_complete;
 1245:   conn->recv[sockindex] = gtls_recv;
 1246:   conn->send[sockindex] = gtls_send;
 1247: 
 1248:   if(SSL_SET_OPTION(primary.sessionid)) {
 1249:     /* we always unconditionally get the session id here, as even if we
 1250:        already got it from the cache and asked to use it in the connection, it
 1251:        might've been rejected and then a new one is in use now and we need to
 1252:        detect that. */
 1253:     void *connect_sessionid;
 1254:     size_t connect_idsize = 0;
 1255: 
 1256:     /* get the session ID data size */
 1257:     gnutls_session_get_data(session, NULL, &connect_idsize);
 1258:     connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
 1259: 
 1260:     if(connect_sessionid) {
 1261:       bool incache;
 1262:       void *ssl_sessionid;
 1263: 
 1264:       /* extract session ID to the allocated buffer */
 1265:       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
 1266: 
 1267:       Curl_ssl_sessionid_lock(conn);
 1268:       incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
 1269:                                         sockindex));
 1270:       if(incache) {
 1271:         /* there was one before in the cache, so instead of risking that the
 1272:            previous one was rejected, we just kill that and store the new */
 1273:         Curl_ssl_delsessionid(conn, ssl_sessionid);
 1274:       }
 1275: 
 1276:       /* store this session id */
 1277:       result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
 1278:                                      sockindex);
 1279:       Curl_ssl_sessionid_unlock(conn);
 1280:       if(result) {
 1281:         free(connect_sessionid);
 1282:         result = CURLE_OUT_OF_MEMORY;
 1283:       }
 1284:     }
 1285:     else
 1286:       result = CURLE_OUT_OF_MEMORY;
 1287:   }
 1288: 
 1289:   return result;
 1290: }
 1291: 
 1292: 
 1293: /*
 1294:  * This function is called after the TCP connect has completed. Setup the TLS
 1295:  * layer and do all necessary magic.
 1296:  */
 1297: /* We use connssl->connecting_state to keep track of the connection status;
 1298:    there are three states: 'ssl_connect_1' (not started yet or complete),
 1299:    'ssl_connect_2_reading' (waiting for data from server), and
 1300:    'ssl_connect_2_writing' (waiting to be able to write).
 1301:  */
 1302: static CURLcode
 1303: gtls_connect_common(struct connectdata *conn,
 1304:                     int sockindex,
 1305:                     bool nonblocking,
 1306:                     bool *done)
 1307: {
 1308:   int rc;
 1309:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 1310: 
 1311:   /* Initiate the connection, if not already done */
 1312:   if(ssl_connect_1 == connssl->connecting_state) {
 1313:     rc = gtls_connect_step1(conn, sockindex);
 1314:     if(rc)
 1315:       return rc;
 1316:   }
 1317: 
 1318:   rc = handshake(conn, sockindex, TRUE, nonblocking);
 1319:   if(rc)
 1320:     /* handshake() sets its own error message with failf() */
 1321:     return rc;
 1322: 
 1323:   /* Finish connecting once the handshake is done */
 1324:   if(ssl_connect_1 == connssl->connecting_state) {
 1325:     rc = gtls_connect_step3(conn, sockindex);
 1326:     if(rc)
 1327:       return rc;
 1328:   }
 1329: 
 1330:   *done = ssl_connect_1 == connssl->connecting_state;
 1331: 
 1332:   return CURLE_OK;
 1333: }
 1334: 
 1335: static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
 1336:                                               int sockindex, bool *done)
 1337: {
 1338:   return gtls_connect_common(conn, sockindex, TRUE, done);
 1339: }
 1340: 
 1341: static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
 1342: {
 1343:   CURLcode result;
 1344:   bool done = FALSE;
 1345: 
 1346:   result = gtls_connect_common(conn, sockindex, FALSE, &done);
 1347:   if(result)
 1348:     return result;
 1349: 
 1350:   DEBUGASSERT(done);
 1351: 
 1352:   return CURLE_OK;
 1353: }
 1354: 
 1355: static bool Curl_gtls_data_pending(const struct connectdata *conn,
 1356:                                    int connindex)
 1357: {
 1358:   const struct ssl_connect_data *connssl = &conn->ssl[connindex];
 1359:   bool res = FALSE;
 1360:   struct ssl_backend_data *backend = connssl->backend;
 1361:   if(backend->session &&
 1362:      0 != gnutls_record_check_pending(backend->session))
 1363:     res = TRUE;
 1364: 
 1365:   connssl = &conn->proxy_ssl[connindex];
 1366:   if(backend->session &&
 1367:      0 != gnutls_record_check_pending(backend->session))
 1368:     res = TRUE;
 1369: 
 1370:   return res;
 1371: }
 1372: 
 1373: static ssize_t gtls_send(struct connectdata *conn,
 1374:                          int sockindex,
 1375:                          const void *mem,
 1376:                          size_t len,
 1377:                          CURLcode *curlcode)
 1378: {
 1379:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 1380:   struct ssl_backend_data *backend = connssl->backend;
 1381:   ssize_t rc = gnutls_record_send(backend->session, mem, len);
 1382: 
 1383:   if(rc < 0) {
 1384:     *curlcode = (rc == GNUTLS_E_AGAIN)
 1385:       ? CURLE_AGAIN
 1386:       : CURLE_SEND_ERROR;
 1387: 
 1388:     rc = -1;
 1389:   }
 1390: 
 1391:   return rc;
 1392: }
 1393: 
 1394: static void close_one(struct ssl_connect_data *connssl)
 1395: {
 1396:   struct ssl_backend_data *backend = connssl->backend;
 1397:   if(backend->session) {
 1398:     gnutls_bye(backend->session, GNUTLS_SHUT_WR);
 1399:     gnutls_deinit(backend->session);
 1400:     backend->session = NULL;
 1401:   }
 1402:   if(backend->cred) {
 1403:     gnutls_certificate_free_credentials(backend->cred);
 1404:     backend->cred = NULL;
 1405:   }
 1406: #ifdef USE_TLS_SRP
 1407:   if(backend->srp_client_cred) {
 1408:     gnutls_srp_free_client_credentials(backend->srp_client_cred);
 1409:     backend->srp_client_cred = NULL;
 1410:   }
 1411: #endif
 1412: }
 1413: 
 1414: static void Curl_gtls_close(struct connectdata *conn, int sockindex)
 1415: {
 1416:   close_one(&conn->ssl[sockindex]);
 1417:   close_one(&conn->proxy_ssl[sockindex]);
 1418: }
 1419: 
 1420: /*
 1421:  * This function is called to shut down the SSL layer but keep the
 1422:  * socket open (CCC - Clear Command Channel)
 1423:  */
 1424: static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
 1425: {
 1426:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 1427:   struct ssl_backend_data *backend = connssl->backend;
 1428:   int retval = 0;
 1429:   struct Curl_easy *data = conn->data;
 1430: 
 1431: #ifndef CURL_DISABLE_FTP
 1432:   /* This has only been tested on the proftpd server, and the mod_tls code
 1433:      sends a close notify alert without waiting for a close notify alert in
 1434:      response. Thus we wait for a close notify alert from the server, but
 1435:      we do not send one. Let's hope other servers do the same... */
 1436: 
 1437:   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
 1438:     gnutls_bye(backend->session, GNUTLS_SHUT_WR);
 1439: #endif
 1440: 
 1441:   if(backend->session) {
 1442:     ssize_t result;
 1443:     bool done = FALSE;
 1444:     char buf[120];
 1445: 
 1446:     while(!done) {
 1447:       int what = SOCKET_READABLE(conn->sock[sockindex],
 1448:                                  SSL_SHUTDOWN_TIMEOUT);
 1449:       if(what > 0) {
 1450:         /* Something to read, let's do it and hope that it is the close
 1451:            notify alert from the server */
 1452:         result = gnutls_record_recv(backend->session,
 1453:                                     buf, sizeof(buf));
 1454:         switch(result) {
 1455:         case 0:
 1456:           /* This is the expected response. There was no data but only
 1457:              the close notify alert */
 1458:           done = TRUE;
 1459:           break;
 1460:         case GNUTLS_E_AGAIN:
 1461:         case GNUTLS_E_INTERRUPTED:
 1462:           infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
 1463:           break;
 1464:         default:
 1465:           retval = -1;
 1466:           done = TRUE;
 1467:           break;
 1468:         }
 1469:       }
 1470:       else if(0 == what) {
 1471:         /* timeout */
 1472:         failf(data, "SSL shutdown timeout");
 1473:         done = TRUE;
 1474:       }
 1475:       else {
 1476:         /* anything that gets here is fatally bad */
 1477:         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
 1478:         retval = -1;
 1479:         done = TRUE;
 1480:       }
 1481:     }
 1482:     gnutls_deinit(backend->session);
 1483:   }
 1484:   gnutls_certificate_free_credentials(backend->cred);
 1485: 
 1486: #ifdef USE_TLS_SRP
 1487:   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
 1488:      && SSL_SET_OPTION(username) != NULL)
 1489:     gnutls_srp_free_client_credentials(backend->srp_client_cred);
 1490: #endif
 1491: 
 1492:   backend->cred = NULL;
 1493:   backend->session = NULL;
 1494: 
 1495:   return retval;
 1496: }
 1497: 
 1498: static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
 1499:                          int num,                  /* socketindex */
 1500:                          char *buf,                /* store read data here */
 1501:                          size_t buffersize,        /* max amount to read */
 1502:                          CURLcode *curlcode)
 1503: {
 1504:   struct ssl_connect_data *connssl = &conn->ssl[num];
 1505:   struct ssl_backend_data *backend = connssl->backend;
 1506:   ssize_t ret;
 1507: 
 1508:   ret = gnutls_record_recv(backend->session, buf, buffersize);
 1509:   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
 1510:     *curlcode = CURLE_AGAIN;
 1511:     return -1;
 1512:   }
 1513: 
 1514:   if(ret == GNUTLS_E_REHANDSHAKE) {
 1515:     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
 1516:        proper way" takes a whole lot of work. */
 1517:     CURLcode result = handshake(conn, num, FALSE, FALSE);
 1518:     if(result)
 1519:       /* handshake() writes error message on its own */
 1520:       *curlcode = result;
 1521:     else
 1522:       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
 1523:     return -1;
 1524:   }
 1525: 
 1526:   if(ret < 0) {
 1527:     failf(conn->data, "GnuTLS recv error (%d): %s",
 1528: 
 1529:           (int)ret, gnutls_strerror((int)ret));
 1530:     *curlcode = CURLE_RECV_ERROR;
 1531:     return -1;
 1532:   }
 1533: 
 1534:   return ret;
 1535: }
 1536: 
 1537: static void Curl_gtls_session_free(void *ptr)
 1538: {
 1539:   free(ptr);
 1540: }
 1541: 
 1542: static size_t Curl_gtls_version(char *buffer, size_t size)
 1543: {
 1544:   return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
 1545: }
 1546: 
 1547: #ifndef USE_GNUTLS_NETTLE
 1548: static int Curl_gtls_seed(struct Curl_easy *data)
 1549: {
 1550:   /* we have the "SSL is seeded" boolean static to prevent multiple
 1551:      time-consuming seedings in vain */
 1552:   static bool ssl_seeded = FALSE;
 1553: 
 1554:   /* Quickly add a bit of entropy */
 1555:   gcry_fast_random_poll();
 1556: 
 1557:   if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
 1558:      data->set.str[STRING_SSL_EGDSOCKET]) {
 1559:     ssl_seeded = TRUE;
 1560:   }
 1561:   return 0;
 1562: }
 1563: #endif
 1564: 
 1565: /* data might be NULL! */
 1566: static CURLcode Curl_gtls_random(struct Curl_easy *data,
 1567:                                  unsigned char *entropy, size_t length)
 1568: {
 1569: #if defined(USE_GNUTLS_NETTLE)
 1570:   int rc;
 1571:   (void)data;
 1572:   rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
 1573:   return rc?CURLE_FAILED_INIT:CURLE_OK;
 1574: #elif defined(USE_GNUTLS)
 1575:   if(data)
 1576:     Curl_gtls_seed(data); /* Initiate the seed if not already done */
 1577:   gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
 1578: #endif
 1579:   return CURLE_OK;
 1580: }
 1581: 
 1582: static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
 1583:                                  size_t tmplen,
 1584:                                  unsigned char *md5sum, /* output */
 1585:                                  size_t md5len)
 1586: {
 1587: #if defined(USE_GNUTLS_NETTLE)
 1588:   struct md5_ctx MD5pw;
 1589:   md5_init(&MD5pw);
 1590:   md5_update(&MD5pw, (unsigned int)tmplen, tmp);
 1591:   md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
 1592: #elif defined(USE_GNUTLS)
 1593:   gcry_md_hd_t MD5pw;
 1594:   gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
 1595:   gcry_md_write(MD5pw, tmp, tmplen);
 1596:   memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
 1597:   gcry_md_close(MD5pw);
 1598: #endif
 1599:   return CURLE_OK;
 1600: }
 1601: 
 1602: static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
 1603:                                 size_t tmplen,
 1604:                                 unsigned char *sha256sum, /* output */
 1605:                                 size_t sha256len)
 1606: {
 1607: #if defined(USE_GNUTLS_NETTLE)
 1608:   struct sha256_ctx SHA256pw;
 1609:   sha256_init(&SHA256pw);
 1610:   sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
 1611:   sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
 1612: #elif defined(USE_GNUTLS)
 1613:   gcry_md_hd_t SHA256pw;
 1614:   gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
 1615:   gcry_md_write(SHA256pw, tmp, tmplen);
 1616:   memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
 1617:   gcry_md_close(SHA256pw);
 1618: #endif
 1619:   return CURLE_OK;
 1620: }
 1621: 
 1622: static bool Curl_gtls_cert_status_request(void)
 1623: {
 1624:   return TRUE;
 1625: }
 1626: 
 1627: static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
 1628:                                      CURLINFO info UNUSED_PARAM)
 1629: {
 1630:   struct ssl_backend_data *backend = connssl->backend;
 1631:   (void)info;
 1632:   return backend->session;
 1633: }
 1634: 
 1635: const struct Curl_ssl Curl_ssl_gnutls = {
 1636:   { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
 1637: 
 1638:   SSLSUPP_CA_PATH  |
 1639:   SSLSUPP_CERTINFO |
 1640:   SSLSUPP_PINNEDPUBKEY |
 1641:   SSLSUPP_HTTPS_PROXY,
 1642: 
 1643:   sizeof(struct ssl_backend_data),
 1644: 
 1645:   Curl_gtls_init,                /* init */
 1646:   Curl_gtls_cleanup,             /* cleanup */
 1647:   Curl_gtls_version,             /* version */
 1648:   Curl_none_check_cxn,           /* check_cxn */
 1649:   Curl_gtls_shutdown,            /* shutdown */
 1650:   Curl_gtls_data_pending,        /* data_pending */
 1651:   Curl_gtls_random,              /* random */
 1652:   Curl_gtls_cert_status_request, /* cert_status_request */
 1653:   Curl_gtls_connect,             /* connect */
 1654:   Curl_gtls_connect_nonblocking, /* connect_nonblocking */
 1655:   Curl_gtls_get_internals,       /* get_internals */
 1656:   Curl_gtls_close,               /* close_one */
 1657:   Curl_none_close_all,           /* close_all */
 1658:   Curl_gtls_session_free,        /* session_free */
 1659:   Curl_none_set_engine,          /* set_engine */
 1660:   Curl_none_set_engine_default,  /* set_engine_default */
 1661:   Curl_none_engines_list,        /* engines_list */
 1662:   Curl_none_false_start,         /* false_start */
 1663:   Curl_gtls_md5sum,              /* md5sum */
 1664:   Curl_gtls_sha256sum            /* sha256sum */
 1665: };
 1666: 
 1667: #endif /* USE_GNUTLS */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>