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