gtls.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 /*
00024  * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
00025  * but vtls.c should ever call or use these functions.
00026  *
00027  * Note: don't use the GnuTLS' *_t variable type names in this source code,
00028  * since they were not present in 1.0.X.
00029  */
00030 
00031 #include "curl_setup.h"
00032 
00033 #ifdef USE_GNUTLS
00034 
00035 #include <gnutls/abstract.h>
00036 #include <gnutls/gnutls.h>
00037 #include <gnutls/x509.h>
00038 
00039 #ifdef USE_GNUTLS_NETTLE
00040 #include <gnutls/crypto.h>
00041 #include <nettle/md5.h>
00042 #include <nettle/sha2.h>
00043 #else
00044 #include <gcrypt.h>
00045 #endif
00046 
00047 #include "urldata.h"
00048 #include "sendf.h"
00049 #include "inet_pton.h"
00050 #include "gtls.h"
00051 #include "vtls.h"
00052 #include "parsedate.h"
00053 #include "connect.h" /* for the connect timeout */
00054 #include "select.h"
00055 #include "strcase.h"
00056 #include "warnless.h"
00057 #include "x509asn1.h"
00058 #include "curl_printf.h"
00059 #include "curl_memory.h"
00060 /* The last #include file should be: */
00061 #include "memdebug.h"
00062 
00063 /*
00064  Some hackish cast macros based on:
00065  https://developer.gnome.org/glib/unstable/glib-Type-Conversion-Macros.html
00066 */
00067 #ifndef GNUTLS_POINTER_TO_INT_CAST
00068 #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
00069 #endif
00070 #ifndef GNUTLS_INT_TO_POINTER_CAST
00071 #define GNUTLS_INT_TO_POINTER_CAST(i) ((void *) (long) (i))
00072 #endif
00073 
00074 /* Enable GnuTLS debugging by defining GTLSDEBUG */
00075 /*#define GTLSDEBUG */
00076 
00077 #ifdef GTLSDEBUG
00078 static void tls_log_func(int level, const char *str)
00079 {
00080     fprintf(stderr, "|<%d>| %s", level, str);
00081 }
00082 #endif
00083 static bool gtls_inited = FALSE;
00084 
00085 #if defined(GNUTLS_VERSION_NUMBER)
00086 #  if (GNUTLS_VERSION_NUMBER >= 0x020c00)
00087 #    undef gnutls_transport_set_lowat
00088 #    define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
00089 #    define USE_GNUTLS_PRIORITY_SET_DIRECT 1
00090 #  endif
00091 #  if (GNUTLS_VERSION_NUMBER >= 0x020c03)
00092 #    define GNUTLS_MAPS_WINSOCK_ERRORS 1
00093 #  endif
00094 
00095 #  if (GNUTLS_VERSION_NUMBER >= 0x030200)
00096 #    define HAS_ALPN
00097 #  endif
00098 
00099 #  if (GNUTLS_VERSION_NUMBER >= 0x03020d)
00100 #    define HAS_OCSP
00101 #  endif
00102 
00103 #  if (GNUTLS_VERSION_NUMBER >= 0x030306)
00104 #    define HAS_CAPATH
00105 #  endif
00106 #endif
00107 
00108 #ifdef HAS_OCSP
00109 # include <gnutls/ocsp.h>
00110 #endif
00111 
00112 /*
00113  * Custom push and pull callback functions used by GNU TLS to read and write
00114  * to the socket.  These functions are simple wrappers to send() and recv()
00115  * (although here using the sread/swrite macros as defined by
00116  * curl_setup_once.h).
00117  * We use custom functions rather than the GNU TLS defaults because it allows
00118  * us to get specific about the fourth "flags" argument, and to use arbitrary
00119  * private data with gnutls_transport_set_ptr if we wish.
00120  *
00121  * When these custom push and pull callbacks fail, GNU TLS checks its own
00122  * session-specific error variable, and when not set also its own global
00123  * errno variable, in order to take appropriate action. GNU TLS does not
00124  * require that the transport is actually a socket. This implies that for
00125  * Windows builds these callbacks should ideally set the session-specific
00126  * error variable using function gnutls_transport_set_errno or as a last
00127  * resort global errno variable using gnutls_transport_set_global_errno,
00128  * with a transport agnostic error value. This implies that some winsock
00129  * error translation must take place in these callbacks.
00130  *
00131  * Paragraph above applies to GNU TLS versions older than 2.12.3, since
00132  * this version GNU TLS does its own internal winsock error translation
00133  * using system_errno() function.
00134  */
00135 
00136 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
00137 #  define gtls_EINTR  4
00138 #  define gtls_EIO    5
00139 #  define gtls_EAGAIN 11
00140 static int gtls_mapped_sockerrno(void)
00141 {
00142   switch(SOCKERRNO) {
00143   case WSAEWOULDBLOCK:
00144     return gtls_EAGAIN;
00145   case WSAEINTR:
00146     return gtls_EINTR;
00147   default:
00148     break;
00149   }
00150   return gtls_EIO;
00151 }
00152 #endif
00153 
00154 static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
00155 {
00156   ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
00157 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
00158   if(ret < 0)
00159     gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
00160 #endif
00161   return ret;
00162 }
00163 
00164 static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
00165 {
00166   ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
00167 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
00168   if(ret < 0)
00169     gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
00170 #endif
00171   return ret;
00172 }
00173 
00174 static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
00175 {
00176   return gnutls_record_send((gnutls_session_t) s, buf, len);
00177 }
00178 
00179 static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
00180 {
00181   return gnutls_record_recv((gnutls_session_t) s, buf, len);
00182 }
00183 
00184 /* Curl_gtls_init()
00185  *
00186  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
00187  * are not thread-safe and thus this function itself is not thread-safe and
00188  * must only be called from within curl_global_init() to keep the thread
00189  * situation under control!
00190  */
00191 int Curl_gtls_init(void)
00192 {
00193   int ret = 1;
00194   if(!gtls_inited) {
00195     ret = gnutls_global_init()?0:1;
00196 #ifdef GTLSDEBUG
00197     gnutls_global_set_log_function(tls_log_func);
00198     gnutls_global_set_log_level(2);
00199 #endif
00200     gtls_inited = TRUE;
00201   }
00202   return ret;
00203 }
00204 
00205 int Curl_gtls_cleanup(void)
00206 {
00207   if(gtls_inited) {
00208     gnutls_global_deinit();
00209     gtls_inited = FALSE;
00210   }
00211   return 1;
00212 }
00213 
00214 static void showtime(struct Curl_easy *data,
00215                      const char *text,
00216                      time_t stamp)
00217 {
00218   struct tm buffer;
00219   const struct tm *tm = &buffer;
00220   CURLcode result = Curl_gmtime(stamp, &buffer);
00221   if(result)
00222     return;
00223 
00224   snprintf(data->state.buffer,
00225            BUFSIZE,
00226            "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
00227            text,
00228            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
00229            tm->tm_mday,
00230            Curl_month[tm->tm_mon],
00231            tm->tm_year + 1900,
00232            tm->tm_hour,
00233            tm->tm_min,
00234            tm->tm_sec);
00235   infof(data, "%s\n", data->state.buffer);
00236 }
00237 
00238 static gnutls_datum_t load_file(const char *file)
00239 {
00240   FILE *f;
00241   gnutls_datum_t loaded_file = { NULL, 0 };
00242   long filelen;
00243   void *ptr;
00244 
00245   f = fopen(file, "rb");
00246   if(!f)
00247     return loaded_file;
00248   if(fseek(f, 0, SEEK_END) != 0
00249      || (filelen = ftell(f)) < 0
00250      || fseek(f, 0, SEEK_SET) != 0
00251      || !(ptr = malloc((size_t)filelen)))
00252     goto out;
00253   if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
00254     free(ptr);
00255     goto out;
00256   }
00257 
00258   loaded_file.data = ptr;
00259   loaded_file.size = (unsigned int)filelen;
00260 out:
00261   fclose(f);
00262   return loaded_file;
00263 }
00264 
00265 static void unload_file(gnutls_datum_t data)
00266 {
00267   free(data.data);
00268 }
00269 
00270 
00271 /* this function does a SSL/TLS (re-)handshake */
00272 static CURLcode handshake(struct connectdata *conn,
00273                           int sockindex,
00274                           bool duringconnect,
00275                           bool nonblocking)
00276 {
00277   struct Curl_easy *data = conn->data;
00278   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00279   gnutls_session_t session = conn->ssl[sockindex].session;
00280   curl_socket_t sockfd = conn->sock[sockindex];
00281   long timeout_ms;
00282   int rc;
00283   int what;
00284 
00285   for(;;) {
00286     /* check allowed time left */
00287     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
00288 
00289     if(timeout_ms < 0) {
00290       /* no need to continue if time already is up */
00291       failf(data, "SSL connection timeout");
00292       return CURLE_OPERATION_TIMEDOUT;
00293     }
00294 
00295     /* if ssl is expecting something, check if it's available. */
00296     if(connssl->connecting_state == ssl_connect_2_reading
00297        || connssl->connecting_state == ssl_connect_2_writing) {
00298 
00299       curl_socket_t writefd = ssl_connect_2_writing==
00300         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
00301       curl_socket_t readfd = ssl_connect_2_reading==
00302         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
00303 
00304       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
00305                                nonblocking?0:
00306                                timeout_ms?timeout_ms:1000);
00307       if(what < 0) {
00308         /* fatal error */
00309         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
00310         return CURLE_SSL_CONNECT_ERROR;
00311       }
00312       else if(0 == what) {
00313         if(nonblocking)
00314           return CURLE_OK;
00315         else if(timeout_ms) {
00316           /* timeout */
00317           failf(data, "SSL connection timeout at %ld", timeout_ms);
00318           return CURLE_OPERATION_TIMEDOUT;
00319         }
00320       }
00321       /* socket is readable or writable */
00322     }
00323 
00324     rc = gnutls_handshake(session);
00325 
00326     if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
00327       connssl->connecting_state =
00328         gnutls_record_get_direction(session)?
00329         ssl_connect_2_writing:ssl_connect_2_reading;
00330       continue;
00331     }
00332     else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
00333       const char *strerr = NULL;
00334 
00335       if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
00336         int alert = gnutls_alert_get(session);
00337         strerr = gnutls_alert_get_name(alert);
00338       }
00339 
00340       if(strerr == NULL)
00341         strerr = gnutls_strerror(rc);
00342 
00343       infof(data, "gnutls_handshake() warning: %s\n", strerr);
00344       continue;
00345     }
00346     else if(rc < 0) {
00347       const char *strerr = NULL;
00348 
00349       if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
00350         int alert = gnutls_alert_get(session);
00351         strerr = gnutls_alert_get_name(alert);
00352       }
00353 
00354       if(strerr == NULL)
00355         strerr = gnutls_strerror(rc);
00356 
00357       failf(data, "gnutls_handshake() failed: %s", strerr);
00358       return CURLE_SSL_CONNECT_ERROR;
00359     }
00360 
00361     /* Reset our connect state machine */
00362     connssl->connecting_state = ssl_connect_1;
00363     return CURLE_OK;
00364   }
00365 }
00366 
00367 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
00368 {
00369   if(!type || !type[0])
00370     return GNUTLS_X509_FMT_PEM;
00371   if(strcasecompare(type, "PEM"))
00372     return GNUTLS_X509_FMT_PEM;
00373   if(strcasecompare(type, "DER"))
00374     return GNUTLS_X509_FMT_DER;
00375   return -1;
00376 }
00377 
00378 static CURLcode
00379 gtls_connect_step1(struct connectdata *conn,
00380                    int sockindex)
00381 {
00382   struct Curl_easy *data = conn->data;
00383   gnutls_session_t session;
00384   int rc;
00385   bool sni = TRUE; /* default is SNI enabled */
00386   void *transport_ptr = NULL;
00387   gnutls_push_func gnutls_transport_push = NULL;
00388   gnutls_pull_func gnutls_transport_pull = NULL;
00389 #ifdef ENABLE_IPV6
00390   struct in6_addr addr;
00391 #else
00392   struct in_addr addr;
00393 #endif
00394 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
00395   static const int cipher_priority[] = {
00396   /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
00397      but this code path is only ever used for ver. < 2.12.0.
00398      GNUTLS_CIPHER_AES_128_GCM,
00399      GNUTLS_CIPHER_AES_256_GCM,
00400   */
00401     GNUTLS_CIPHER_AES_128_CBC,
00402     GNUTLS_CIPHER_AES_256_CBC,
00403     GNUTLS_CIPHER_CAMELLIA_128_CBC,
00404     GNUTLS_CIPHER_CAMELLIA_256_CBC,
00405     GNUTLS_CIPHER_3DES_CBC,
00406   };
00407   static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
00408   static int protocol_priority[] = { 0, 0, 0, 0 };
00409 #else
00410 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
00411 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
00412    requested in the priority string, so treat it specially
00413  */
00414 #define GNUTLS_SRP "+SRP"
00415   const char *prioritylist;
00416   const char *err = NULL;
00417 #endif
00418 
00419   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
00420     conn->host.name;
00421 
00422   if(conn->ssl[sockindex].state == ssl_connection_complete)
00423     /* to make us tolerant against being called more than once for the
00424        same connection */
00425     return CURLE_OK;
00426 
00427   if(!gtls_inited)
00428     Curl_gtls_init();
00429 
00430   if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
00431     failf(data, "GnuTLS does not support SSLv2");
00432     return CURLE_SSL_CONNECT_ERROR;
00433   }
00434   else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
00435     sni = FALSE; /* SSLv3 has no SNI */
00436 
00437   /* allocate a cred struct */
00438   rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
00439   if(rc != GNUTLS_E_SUCCESS) {
00440     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
00441     return CURLE_SSL_CONNECT_ERROR;
00442   }
00443 
00444 #ifdef USE_TLS_SRP
00445   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
00446     infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
00447 
00448     rc = gnutls_srp_allocate_client_credentials(
00449            &conn->ssl[sockindex].srp_client_cred);
00450     if(rc != GNUTLS_E_SUCCESS) {
00451       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
00452             gnutls_strerror(rc));
00453       return CURLE_OUT_OF_MEMORY;
00454     }
00455 
00456     rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
00457                                            srp_client_cred,
00458                                            SSL_SET_OPTION(username),
00459                                            SSL_SET_OPTION(password));
00460     if(rc != GNUTLS_E_SUCCESS) {
00461       failf(data, "gnutls_srp_set_client_cred() failed: %s",
00462             gnutls_strerror(rc));
00463       return CURLE_BAD_FUNCTION_ARGUMENT;
00464     }
00465   }
00466 #endif
00467 
00468   if(SSL_CONN_CONFIG(CAfile)) {
00469     /* set the trusted CA cert bundle file */
00470     gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
00471                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
00472 
00473     rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
00474                                                 SSL_CONN_CONFIG(CAfile),
00475                                                 GNUTLS_X509_FMT_PEM);
00476     if(rc < 0) {
00477       infof(data, "error reading ca cert file %s (%s)\n",
00478             SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
00479       if(SSL_CONN_CONFIG(verifypeer))
00480         return CURLE_SSL_CACERT_BADFILE;
00481     }
00482     else
00483       infof(data, "found %d certificates in %s\n", rc,
00484             SSL_CONN_CONFIG(CAfile));
00485   }
00486 
00487 #ifdef HAS_CAPATH
00488   if(SSL_CONN_CONFIG(CApath)) {
00489     /* set the trusted CA cert directory */
00490     rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
00491                                                SSL_CONN_CONFIG(CApath),
00492                                                GNUTLS_X509_FMT_PEM);
00493     if(rc < 0) {
00494       infof(data, "error reading ca cert file %s (%s)\n",
00495             SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
00496       if(SSL_CONN_CONFIG(verifypeer))
00497         return CURLE_SSL_CACERT_BADFILE;
00498     }
00499     else
00500       infof(data, "found %d certificates in %s\n",
00501             rc, SSL_CONN_CONFIG(CApath));
00502   }
00503 #endif
00504 
00505 #ifdef CURL_CA_FALLBACK
00506   /* use system ca certificate store as fallback */
00507   if(SSL_CONN_CONFIG(verifypeer) &&
00508      !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
00509     gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
00510   }
00511 #endif
00512 
00513   if(SSL_SET_OPTION(CRLfile)) {
00514     /* set the CRL list file */
00515     rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
00516                                               SSL_SET_OPTION(CRLfile),
00517                                               GNUTLS_X509_FMT_PEM);
00518     if(rc < 0) {
00519       failf(data, "error reading crl file %s (%s)",
00520             SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
00521       return CURLE_SSL_CRL_BADFILE;
00522     }
00523     else
00524       infof(data, "found %d CRL in %s\n",
00525             rc, SSL_SET_OPTION(CRLfile));
00526   }
00527 
00528   /* Initialize TLS session as a client */
00529   rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
00530   if(rc != GNUTLS_E_SUCCESS) {
00531     failf(data, "gnutls_init() failed: %d", rc);
00532     return CURLE_SSL_CONNECT_ERROR;
00533   }
00534 
00535   /* convenient assign */
00536   session = conn->ssl[sockindex].session;
00537 
00538   if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
00539 #ifdef ENABLE_IPV6
00540      (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
00541 #endif
00542      sni &&
00543      (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
00544                              strlen(hostname)) < 0))
00545     infof(data, "WARNING: failed to configure server name indication (SNI) "
00546           "TLS extension\n");
00547 
00548   /* Use default priorities */
00549   rc = gnutls_set_default_priority(session);
00550   if(rc != GNUTLS_E_SUCCESS)
00551     return CURLE_SSL_CONNECT_ERROR;
00552 
00553 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
00554   rc = gnutls_cipher_set_priority(session, cipher_priority);
00555   if(rc != GNUTLS_E_SUCCESS)
00556     return CURLE_SSL_CONNECT_ERROR;
00557 
00558   /* Sets the priority on the certificate types supported by gnutls. Priority
00559    is higher for types specified before others. After specifying the types
00560    you want, you must append a 0. */
00561   rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
00562   if(rc != GNUTLS_E_SUCCESS)
00563     return CURLE_SSL_CONNECT_ERROR;
00564 
00565   if(SSL_CONN_CONFIG(cipher_list) != NULL) {
00566     failf(data, "can't pass a custom cipher list to older GnuTLS"
00567           " versions");
00568     return CURLE_SSL_CONNECT_ERROR;
00569   }
00570 
00571   switch(SSL_CONN_CONFIG(version) {
00572     case CURL_SSLVERSION_SSLv3:
00573       protocol_priority[0] = GNUTLS_SSL3;
00574       break;
00575     case CURL_SSLVERSION_DEFAULT:
00576     case CURL_SSLVERSION_TLSv1:
00577       protocol_priority[0] = GNUTLS_TLS1_0;
00578       protocol_priority[1] = GNUTLS_TLS1_1;
00579       protocol_priority[2] = GNUTLS_TLS1_2;
00580       break;
00581     case CURL_SSLVERSION_TLSv1_0:
00582       protocol_priority[0] = GNUTLS_TLS1_0;
00583       break;
00584     case CURL_SSLVERSION_TLSv1_1:
00585       protocol_priority[0] = GNUTLS_TLS1_1;
00586       break;
00587     case CURL_SSLVERSION_TLSv1_2:
00588       protocol_priority[0] = GNUTLS_TLS1_2;
00589       break;
00590     case CURL_SSLVERSION_TLSv1_3:
00591       failf(data, "GnuTLS: TLS 1.3 is not yet supported");
00592       return CURLE_SSL_CONNECT_ERROR;
00593     case CURL_SSLVERSION_SSLv2:
00594       failf(data, "GnuTLS does not support SSLv2");
00595       return CURLE_SSL_CONNECT_ERROR;
00596     default:
00597       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
00598       return CURLE_SSL_CONNECT_ERROR;
00599   }
00600   rc = gnutls_protocol_set_priority(session, protocol_priority);
00601   if(rc != GNUTLS_E_SUCCESS) {
00602     failf(data, "Did you pass a valid GnuTLS cipher list?");
00603     return CURLE_SSL_CONNECT_ERROR;
00604   }
00605 
00606 #else
00607   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
00608    * removed if a run-time error indicates that SRP is not supported by this
00609    * GnuTLS version */
00610   switch(SSL_CONN_CONFIG(version)) {
00611     case CURL_SSLVERSION_SSLv3:
00612       prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
00613       sni = false;
00614       break;
00615     case CURL_SSLVERSION_DEFAULT:
00616     case CURL_SSLVERSION_TLSv1:
00617       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
00618       break;
00619     case CURL_SSLVERSION_TLSv1_0:
00620       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
00621                      "+VERS-TLS1.0:" GNUTLS_SRP;
00622       break;
00623     case CURL_SSLVERSION_TLSv1_1:
00624       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
00625                      "+VERS-TLS1.1:" GNUTLS_SRP;
00626       break;
00627     case CURL_SSLVERSION_TLSv1_2:
00628       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
00629                      "+VERS-TLS1.2:" GNUTLS_SRP;
00630       break;
00631     case CURL_SSLVERSION_TLSv1_3:
00632       failf(data, "GnuTLS: TLS 1.3 is not yet supported");
00633       return CURLE_SSL_CONNECT_ERROR;
00634     case CURL_SSLVERSION_SSLv2:
00635       failf(data, "GnuTLS does not support SSLv2");
00636       return CURLE_SSL_CONNECT_ERROR;
00637     default:
00638       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
00639       return CURLE_SSL_CONNECT_ERROR;
00640   }
00641   rc = gnutls_priority_set_direct(session, prioritylist, &err);
00642   if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
00643     if(!strcmp(err, GNUTLS_SRP)) {
00644       /* This GnuTLS was probably compiled without support for SRP.
00645        * Note that fact and try again without it. */
00646       int validprioritylen = curlx_uztosi(err - prioritylist);
00647       char *prioritycopy = strdup(prioritylist);
00648       if(!prioritycopy)
00649         return CURLE_OUT_OF_MEMORY;
00650 
00651       infof(data, "This GnuTLS does not support SRP\n");
00652       if(validprioritylen)
00653         /* Remove the :+SRP */
00654         prioritycopy[validprioritylen - 1] = 0;
00655       rc = gnutls_priority_set_direct(session, prioritycopy, &err);
00656       free(prioritycopy);
00657     }
00658   }
00659   if(rc != GNUTLS_E_SUCCESS) {
00660     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
00661           rc, err);
00662     return CURLE_SSL_CONNECT_ERROR;
00663   }
00664 #endif
00665 
00666 #ifdef HAS_ALPN
00667   if(conn->bits.tls_enable_alpn) {
00668     int cur = 0;
00669     gnutls_datum_t protocols[2];
00670 
00671 #ifdef USE_NGHTTP2
00672     if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
00673       protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
00674       protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
00675       cur++;
00676       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
00677     }
00678 #endif
00679 
00680     protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
00681     protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
00682     cur++;
00683     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
00684 
00685     gnutls_alpn_set_protocols(session, protocols, cur, 0);
00686   }
00687 #endif
00688 
00689   if(SSL_SET_OPTION(cert)) {
00690     if(SSL_SET_OPTION(key_passwd)) {
00691 #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
00692       const unsigned int supported_key_encryption_algorithms =
00693         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
00694         GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
00695         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
00696         GNUTLS_PKCS_USE_PBES2_AES_256;
00697       rc = gnutls_certificate_set_x509_key_file2(
00698            conn->ssl[sockindex].cred,
00699            SSL_SET_OPTION(cert),
00700            SSL_SET_OPTION(key) ?
00701            SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
00702            do_file_type(SSL_SET_OPTION(cert_type)),
00703            SSL_SET_OPTION(key_passwd),
00704            supported_key_encryption_algorithms);
00705       if(rc != GNUTLS_E_SUCCESS) {
00706         failf(data,
00707               "error reading X.509 potentially-encrypted key file: %s",
00708               gnutls_strerror(rc));
00709         return CURLE_SSL_CONNECT_ERROR;
00710       }
00711 #else
00712       failf(data, "gnutls lacks support for encrypted key files");
00713       return CURLE_SSL_CONNECT_ERROR;
00714 #endif
00715     }
00716     else {
00717       if(gnutls_certificate_set_x509_key_file(
00718            conn->ssl[sockindex].cred,
00719            SSL_SET_OPTION(cert),
00720            SSL_SET_OPTION(key) ?
00721            SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
00722            do_file_type(SSL_SET_OPTION(cert_type)) ) !=
00723          GNUTLS_E_SUCCESS) {
00724         failf(data, "error reading X.509 key or certificate file");
00725         return CURLE_SSL_CONNECT_ERROR;
00726       }
00727     }
00728   }
00729 
00730 #ifdef USE_TLS_SRP
00731   /* put the credentials to the current session */
00732   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
00733     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
00734                                 conn->ssl[sockindex].srp_client_cred);
00735     if(rc != GNUTLS_E_SUCCESS) {
00736       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
00737       return CURLE_SSL_CONNECT_ERROR;
00738     }
00739   }
00740   else
00741 #endif
00742   {
00743     rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
00744                                 conn->ssl[sockindex].cred);
00745     if(rc != GNUTLS_E_SUCCESS) {
00746       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
00747       return CURLE_SSL_CONNECT_ERROR;
00748     }
00749   }
00750 
00751   if(conn->proxy_ssl[sockindex].use) {
00752     transport_ptr = conn->proxy_ssl[sockindex].session;
00753     gnutls_transport_push = Curl_gtls_push_ssl;
00754     gnutls_transport_pull = Curl_gtls_pull_ssl;
00755   }
00756   else {
00757     /* file descriptor for the socket */
00758     transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]);
00759     gnutls_transport_push = Curl_gtls_push;
00760     gnutls_transport_pull = Curl_gtls_pull;
00761   }
00762 
00763   /* set the connection handle */
00764   gnutls_transport_set_ptr(session, transport_ptr);
00765 
00766   /* register callback functions to send and receive data. */
00767   gnutls_transport_set_push_function(session, gnutls_transport_push);
00768   gnutls_transport_set_pull_function(session, gnutls_transport_pull);
00769 
00770   /* lowat must be set to zero when using custom push and pull functions. */
00771   gnutls_transport_set_lowat(session, 0);
00772 
00773 #ifdef HAS_OCSP
00774   if(SSL_CONN_CONFIG(verifystatus)) {
00775     rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
00776     if(rc != GNUTLS_E_SUCCESS) {
00777       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
00778       return CURLE_SSL_CONNECT_ERROR;
00779     }
00780   }
00781 #endif
00782 
00783   /* This might be a reconnect, so we check for a session ID in the cache
00784      to speed up things */
00785   if(data->set.general_ssl.sessionid) {
00786     void *ssl_sessionid;
00787     size_t ssl_idsize;
00788 
00789     Curl_ssl_sessionid_lock(conn);
00790     if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
00791       /* we got a session id, use it! */
00792       gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
00793 
00794       /* Informational message */
00795       infof(data, "SSL re-using session ID\n");
00796     }
00797     Curl_ssl_sessionid_unlock(conn);
00798   }
00799 
00800   return CURLE_OK;
00801 }
00802 
00803 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
00804                                     gnutls_x509_crt_t cert,
00805                                     const char *pinnedpubkey)
00806 {
00807   /* Scratch */
00808   size_t len1 = 0, len2 = 0;
00809   unsigned char *buff1 = NULL;
00810 
00811   gnutls_pubkey_t key = NULL;
00812 
00813   /* Result is returned to caller */
00814   int ret = 0;
00815   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00816 
00817   /* if a path wasn't specified, don't pin */
00818   if(NULL == pinnedpubkey)
00819     return CURLE_OK;
00820 
00821   if(NULL == cert)
00822     return result;
00823 
00824   do {
00825     /* Begin Gyrations to get the public key     */
00826     gnutls_pubkey_init(&key);
00827 
00828     ret = gnutls_pubkey_import_x509(key, cert, 0);
00829     if(ret < 0)
00830       break; /* failed */
00831 
00832     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
00833     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
00834       break; /* failed */
00835 
00836     buff1 = malloc(len1);
00837     if(NULL == buff1)
00838       break; /* failed */
00839 
00840     len2 = len1;
00841 
00842     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
00843     if(ret < 0 || len1 != len2)
00844       break; /* failed */
00845 
00846     /* End Gyrations */
00847 
00848     /* The one good exit point */
00849     result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
00850   } while(0);
00851 
00852   if(NULL != key)
00853     gnutls_pubkey_deinit(key);
00854 
00855   Curl_safefree(buff1);
00856 
00857   return result;
00858 }
00859 
00860 static Curl_recv gtls_recv;
00861 static Curl_send gtls_send;
00862 
00863 static CURLcode
00864 gtls_connect_step3(struct connectdata *conn,
00865                    int sockindex)
00866 {
00867   unsigned int cert_list_size;
00868   const gnutls_datum_t *chainp;
00869   unsigned int verify_status = 0;
00870   gnutls_x509_crt_t x509_cert, x509_issuer;
00871   gnutls_datum_t issuerp;
00872   char certbuf[256] = ""; /* big enough? */
00873   size_t size;
00874   unsigned int algo;
00875   unsigned int bits;
00876   time_t certclock;
00877   const char *ptr;
00878   struct Curl_easy *data = conn->data;
00879   gnutls_session_t session = conn->ssl[sockindex].session;
00880   int rc;
00881 #ifdef HAS_ALPN
00882   gnutls_datum_t proto;
00883 #endif
00884   CURLcode result = CURLE_OK;
00885   gnutls_protocol_t version = gnutls_protocol_get_version(session);
00886   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
00887     conn->host.name;
00888 
00889   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
00890   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
00891                                      gnutls_cipher_get(session),
00892                                      gnutls_mac_get(session));
00893 
00894   infof(data, "SSL connection using %s / %s\n",
00895         gnutls_protocol_get_name(version), ptr);
00896 
00897   /* This function will return the peer's raw certificate (chain) as sent by
00898      the peer. These certificates are in raw format (DER encoded for
00899      X.509). In case of a X.509 then a certificate list may be present. The
00900      first certificate in the list is the peer's certificate, following the
00901      issuer's certificate, then the issuer's issuer etc. */
00902 
00903   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
00904   if(!chainp) {
00905     if(SSL_CONN_CONFIG(verifypeer) ||
00906        SSL_CONN_CONFIG(verifyhost) ||
00907        SSL_SET_OPTION(issuercert)) {
00908 #ifdef USE_TLS_SRP
00909       if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
00910          && SSL_SET_OPTION(username) != NULL
00911          && !SSL_CONN_CONFIG(verifypeer)
00912          && gnutls_cipher_get(session)) {
00913         /* no peer cert, but auth is ok if we have SRP user and cipher and no
00914            peer verify */
00915       }
00916       else {
00917 #endif
00918         failf(data, "failed to get server cert");
00919         return CURLE_PEER_FAILED_VERIFICATION;
00920 #ifdef USE_TLS_SRP
00921       }
00922 #endif
00923     }
00924     infof(data, "\t common name: WARNING couldn't obtain\n");
00925   }
00926 
00927   if(data->set.ssl.certinfo && chainp) {
00928     unsigned int i;
00929 
00930     result = Curl_ssl_init_certinfo(data, cert_list_size);
00931     if(result)
00932       return result;
00933 
00934     for(i = 0; i < cert_list_size; i++) {
00935       const char *beg = (const char *) chainp[i].data;
00936       const char *end = beg + chainp[i].size;
00937 
00938       result = Curl_extract_certinfo(conn, i, beg, end);
00939       if(result)
00940         return result;
00941     }
00942   }
00943 
00944   if(SSL_CONN_CONFIG(verifypeer)) {
00945     /* This function will try to verify the peer's certificate and return its
00946        status (trusted, invalid etc.). The value of status should be one or
00947        more of the gnutls_certificate_status_t enumerated elements bitwise
00948        or'd. To avoid denial of service attacks some default upper limits
00949        regarding the certificate key size and chain size are set. To override
00950        them use gnutls_certificate_set_verify_limits(). */
00951 
00952     rc = gnutls_certificate_verify_peers2(session, &verify_status);
00953     if(rc < 0) {
00954       failf(data, "server cert verify failed: %d", rc);
00955       return CURLE_SSL_CONNECT_ERROR;
00956     }
00957 
00958     /* verify_status is a bitmask of gnutls_certificate_status bits */
00959     if(verify_status & GNUTLS_CERT_INVALID) {
00960       if(SSL_CONN_CONFIG(verifypeer)) {
00961         failf(data, "server certificate verification failed. CAfile: %s "
00962               "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
00963               "none",
00964               SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
00965         return CURLE_SSL_CACERT;
00966       }
00967       else
00968         infof(data, "\t server certificate verification FAILED\n");
00969     }
00970     else
00971       infof(data, "\t server certificate verification OK\n");
00972   }
00973   else
00974     infof(data, "\t server certificate verification SKIPPED\n");
00975 
00976 #ifdef HAS_OCSP
00977   if(SSL_CONN_CONFIG(verifystatus)) {
00978     if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
00979       gnutls_datum_t status_request;
00980       gnutls_ocsp_resp_t ocsp_resp;
00981 
00982       gnutls_ocsp_cert_status_t status;
00983       gnutls_x509_crl_reason_t reason;
00984 
00985       rc = gnutls_ocsp_status_request_get(session, &status_request);
00986 
00987       infof(data, "\t server certificate status verification FAILED\n");
00988 
00989       if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
00990         failf(data, "No OCSP response received");
00991         return CURLE_SSL_INVALIDCERTSTATUS;
00992       }
00993 
00994       if(rc < 0) {
00995         failf(data, "Invalid OCSP response received");
00996         return CURLE_SSL_INVALIDCERTSTATUS;
00997       }
00998 
00999       gnutls_ocsp_resp_init(&ocsp_resp);
01000 
01001       rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
01002       if(rc < 0) {
01003         failf(data, "Invalid OCSP response received");
01004         return CURLE_SSL_INVALIDCERTSTATUS;
01005       }
01006 
01007       rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
01008                                        &status, NULL, NULL, NULL, &reason);
01009 
01010       switch(status) {
01011       case GNUTLS_OCSP_CERT_GOOD:
01012         break;
01013 
01014       case GNUTLS_OCSP_CERT_REVOKED: {
01015         const char *crl_reason;
01016 
01017         switch(reason) {
01018           default:
01019           case GNUTLS_X509_CRLREASON_UNSPECIFIED:
01020             crl_reason = "unspecified reason";
01021             break;
01022 
01023           case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
01024             crl_reason = "private key compromised";
01025             break;
01026 
01027           case GNUTLS_X509_CRLREASON_CACOMPROMISE:
01028             crl_reason = "CA compromised";
01029             break;
01030 
01031           case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
01032             crl_reason = "affiliation has changed";
01033             break;
01034 
01035           case GNUTLS_X509_CRLREASON_SUPERSEDED:
01036             crl_reason = "certificate superseded";
01037             break;
01038 
01039           case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
01040             crl_reason = "operation has ceased";
01041             break;
01042 
01043           case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
01044             crl_reason = "certificate is on hold";
01045             break;
01046 
01047           case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
01048             crl_reason = "will be removed from delta CRL";
01049             break;
01050 
01051           case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
01052             crl_reason = "privilege withdrawn";
01053             break;
01054 
01055           case GNUTLS_X509_CRLREASON_AACOMPROMISE:
01056             crl_reason = "AA compromised";
01057             break;
01058         }
01059 
01060         failf(data, "Server certificate was revoked: %s", crl_reason);
01061         break;
01062       }
01063 
01064       default:
01065       case GNUTLS_OCSP_CERT_UNKNOWN:
01066         failf(data, "Server certificate status is unknown");
01067         break;
01068       }
01069 
01070       gnutls_ocsp_resp_deinit(ocsp_resp);
01071 
01072       return CURLE_SSL_INVALIDCERTSTATUS;
01073     }
01074     else
01075       infof(data, "\t server certificate status verification OK\n");
01076   }
01077   else
01078     infof(data, "\t server certificate status verification SKIPPED\n");
01079 #endif
01080 
01081   /* initialize an X.509 certificate structure. */
01082   gnutls_x509_crt_init(&x509_cert);
01083 
01084   if(chainp)
01085     /* convert the given DER or PEM encoded Certificate to the native
01086        gnutls_x509_crt_t format */
01087     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
01088 
01089   if(SSL_SET_OPTION(issuercert)) {
01090     gnutls_x509_crt_init(&x509_issuer);
01091     issuerp = load_file(SSL_SET_OPTION(issuercert));
01092     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
01093     rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
01094     gnutls_x509_crt_deinit(x509_issuer);
01095     unload_file(issuerp);
01096     if(rc <= 0) {
01097       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
01098             SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
01099       gnutls_x509_crt_deinit(x509_cert);
01100       return CURLE_SSL_ISSUER_ERROR;
01101     }
01102     infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
01103           SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
01104   }
01105 
01106   size=sizeof(certbuf);
01107   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
01108                                      0, /* the first and only one */
01109                                      FALSE,
01110                                      certbuf,
01111                                      &size);
01112   if(rc) {
01113     infof(data, "error fetching CN from cert:%s\n",
01114           gnutls_strerror(rc));
01115   }
01116 
01117   /* This function will check if the given certificate's subject matches the
01118      given hostname. This is a basic implementation of the matching described
01119      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
01120      alternative name PKIX extension. Returns non zero on success, and zero on
01121      failure. */
01122   rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
01123 #if GNUTLS_VERSION_NUMBER < 0x030306
01124   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
01125      addresses. */
01126   if(!rc) {
01127 #ifdef ENABLE_IPV6
01128     #define use_addr in6_addr
01129 #else
01130     #define use_addr in_addr
01131 #endif
01132     unsigned char addrbuf[sizeof(struct use_addr)];
01133     unsigned char certaddr[sizeof(struct use_addr)];
01134     size_t addrlen = 0, certaddrlen;
01135     int i;
01136     int ret = 0;
01137 
01138     if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
01139       addrlen = 4;
01140 #ifdef ENABLE_IPV6
01141     else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
01142       addrlen = 16;
01143 #endif
01144 
01145     if(addrlen) {
01146       for(i=0; ; i++) {
01147         certaddrlen = sizeof(certaddr);
01148         ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
01149                                                    &certaddrlen, NULL);
01150         /* If this happens, it wasn't an IP address. */
01151         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
01152           continue;
01153         if(ret < 0)
01154           break;
01155         if(ret != GNUTLS_SAN_IPADDRESS)
01156           continue;
01157         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
01158           rc = 1;
01159           break;
01160         }
01161       }
01162     }
01163   }
01164 #endif
01165   if(!rc) {
01166     const char * const dispname = SSL_IS_PROXY() ?
01167       conn->http_proxy.host.dispname : conn->host.dispname;
01168 
01169     if(SSL_CONN_CONFIG(verifyhost)) {
01170       failf(data, "SSL: certificate subject name (%s) does not match "
01171             "target host name '%s'", certbuf, dispname);
01172       gnutls_x509_crt_deinit(x509_cert);
01173       return CURLE_PEER_FAILED_VERIFICATION;
01174     }
01175     else
01176       infof(data, "\t common name: %s (does not match '%s')\n",
01177             certbuf, dispname);
01178   }
01179   else
01180     infof(data, "\t common name: %s (matched)\n", certbuf);
01181 
01182   /* Check for time-based validity */
01183   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
01184 
01185   if(certclock == (time_t)-1) {
01186     if(SSL_CONN_CONFIG(verifypeer)) {
01187       failf(data, "server cert expiration date verify failed");
01188       gnutls_x509_crt_deinit(x509_cert);
01189       return CURLE_SSL_CONNECT_ERROR;
01190     }
01191     else
01192       infof(data, "\t server certificate expiration date verify FAILED\n");
01193   }
01194   else {
01195     if(certclock < time(NULL)) {
01196       if(SSL_CONN_CONFIG(verifypeer)) {
01197         failf(data, "server certificate expiration date has passed.");
01198         gnutls_x509_crt_deinit(x509_cert);
01199         return CURLE_PEER_FAILED_VERIFICATION;
01200       }
01201       else
01202         infof(data, "\t server certificate expiration date FAILED\n");
01203     }
01204     else
01205       infof(data, "\t server certificate expiration date OK\n");
01206   }
01207 
01208   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
01209 
01210   if(certclock == (time_t)-1) {
01211     if(SSL_CONN_CONFIG(verifypeer)) {
01212       failf(data, "server cert activation date verify failed");
01213       gnutls_x509_crt_deinit(x509_cert);
01214       return CURLE_SSL_CONNECT_ERROR;
01215     }
01216     else
01217       infof(data, "\t server certificate activation date verify FAILED\n");
01218   }
01219   else {
01220     if(certclock > time(NULL)) {
01221       if(SSL_CONN_CONFIG(verifypeer)) {
01222         failf(data, "server certificate not activated yet.");
01223         gnutls_x509_crt_deinit(x509_cert);
01224         return CURLE_PEER_FAILED_VERIFICATION;
01225       }
01226       else
01227         infof(data, "\t server certificate activation date FAILED\n");
01228     }
01229     else
01230       infof(data, "\t server certificate activation date OK\n");
01231   }
01232 
01233   ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
01234         data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
01235   if(ptr) {
01236     result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
01237     if(result != CURLE_OK) {
01238       failf(data, "SSL: public key does not match pinned public key!");
01239       gnutls_x509_crt_deinit(x509_cert);
01240       return result;
01241     }
01242   }
01243 
01244   /* Show:
01245 
01246   - subject
01247   - start date
01248   - expire date
01249   - common name
01250   - issuer
01251 
01252   */
01253 
01254   /* public key algorithm's parameters */
01255   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
01256   infof(data, "\t certificate public key: %s\n",
01257         gnutls_pk_algorithm_get_name(algo));
01258 
01259   /* version of the X.509 certificate. */
01260   infof(data, "\t certificate version: #%d\n",
01261         gnutls_x509_crt_get_version(x509_cert));
01262 
01263 
01264   size = sizeof(certbuf);
01265   gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
01266   infof(data, "\t subject: %s\n", certbuf);
01267 
01268   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
01269   showtime(data, "start date", certclock);
01270 
01271   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
01272   showtime(data, "expire date", certclock);
01273 
01274   size = sizeof(certbuf);
01275   gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
01276   infof(data, "\t issuer: %s\n", certbuf);
01277 
01278   gnutls_x509_crt_deinit(x509_cert);
01279 
01280   /* compression algorithm (if any) */
01281   ptr = gnutls_compression_get_name(gnutls_compression_get(session));
01282   /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
01283   infof(data, "\t compression: %s\n", ptr);
01284 
01285 #ifdef HAS_ALPN
01286   if(conn->bits.tls_enable_alpn) {
01287     rc = gnutls_alpn_get_selected_protocol(session, &proto);
01288     if(rc == 0) {
01289       infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
01290           proto.data);
01291 
01292 #ifdef USE_NGHTTP2
01293       if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
01294          !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
01295                  NGHTTP2_PROTO_VERSION_ID_LEN)) {
01296         conn->negnpn = CURL_HTTP_VERSION_2;
01297       }
01298       else
01299 #endif
01300       if(proto.size == ALPN_HTTP_1_1_LENGTH &&
01301          !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
01302         conn->negnpn = CURL_HTTP_VERSION_1_1;
01303       }
01304     }
01305     else
01306       infof(data, "ALPN, server did not agree to a protocol\n");
01307   }
01308 #endif
01309 
01310   conn->ssl[sockindex].state = ssl_connection_complete;
01311   conn->recv[sockindex] = gtls_recv;
01312   conn->send[sockindex] = gtls_send;
01313 
01314   if(data->set.general_ssl.sessionid) {
01315     /* we always unconditionally get the session id here, as even if we
01316        already got it from the cache and asked to use it in the connection, it
01317        might've been rejected and then a new one is in use now and we need to
01318        detect that. */
01319     bool incache;
01320     void *ssl_sessionid;
01321     void *connect_sessionid;
01322     size_t connect_idsize = 0;
01323 
01324     /* get the session ID data size */
01325     gnutls_session_get_data(session, NULL, &connect_idsize);
01326     connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
01327 
01328     if(connect_sessionid) {
01329       /* extract session ID to the allocated buffer */
01330       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
01331 
01332       Curl_ssl_sessionid_lock(conn);
01333       incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
01334                                         sockindex));
01335       if(incache) {
01336         /* there was one before in the cache, so instead of risking that the
01337            previous one was rejected, we just kill that and store the new */
01338         Curl_ssl_delsessionid(conn, ssl_sessionid);
01339       }
01340 
01341       /* store this session id */
01342       result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
01343                                      sockindex);
01344       Curl_ssl_sessionid_unlock(conn);
01345       if(result) {
01346         free(connect_sessionid);
01347         result = CURLE_OUT_OF_MEMORY;
01348       }
01349     }
01350     else
01351       result = CURLE_OUT_OF_MEMORY;
01352   }
01353 
01354   return result;
01355 }
01356 
01357 
01358 /*
01359  * This function is called after the TCP connect has completed. Setup the TLS
01360  * layer and do all necessary magic.
01361  */
01362 /* We use connssl->connecting_state to keep track of the connection status;
01363    there are three states: 'ssl_connect_1' (not started yet or complete),
01364    'ssl_connect_2_reading' (waiting for data from server), and
01365    'ssl_connect_2_writing' (waiting to be able to write).
01366  */
01367 static CURLcode
01368 gtls_connect_common(struct connectdata *conn,
01369                     int sockindex,
01370                     bool nonblocking,
01371                     bool *done)
01372 {
01373   int rc;
01374   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01375 
01376   /* Initiate the connection, if not already done */
01377   if(ssl_connect_1==connssl->connecting_state) {
01378     rc = gtls_connect_step1(conn, sockindex);
01379     if(rc)
01380       return rc;
01381   }
01382 
01383   rc = handshake(conn, sockindex, TRUE, nonblocking);
01384   if(rc)
01385     /* handshake() sets its own error message with failf() */
01386     return rc;
01387 
01388   /* Finish connecting once the handshake is done */
01389   if(ssl_connect_1==connssl->connecting_state) {
01390     rc = gtls_connect_step3(conn, sockindex);
01391     if(rc)
01392       return rc;
01393   }
01394 
01395   *done = ssl_connect_1==connssl->connecting_state;
01396 
01397   return CURLE_OK;
01398 }
01399 
01400 CURLcode
01401 Curl_gtls_connect_nonblocking(struct connectdata *conn,
01402                               int sockindex,
01403                               bool *done)
01404 {
01405   return gtls_connect_common(conn, sockindex, TRUE, done);
01406 }
01407 
01408 CURLcode
01409 Curl_gtls_connect(struct connectdata *conn,
01410                   int sockindex)
01411 
01412 {
01413   CURLcode result;
01414   bool done = FALSE;
01415 
01416   result = gtls_connect_common(conn, sockindex, FALSE, &done);
01417   if(result)
01418     return result;
01419 
01420   DEBUGASSERT(done);
01421 
01422   return CURLE_OK;
01423 }
01424 
01425 bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
01426 {
01427   bool res = FALSE;
01428   if(conn->ssl[connindex].session &&
01429      0 != gnutls_record_check_pending(conn->ssl[connindex].session))
01430     res = TRUE;
01431 
01432   if(conn->proxy_ssl[connindex].session &&
01433      0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
01434     res = TRUE;
01435 
01436   return res;
01437 }
01438 
01439 static ssize_t gtls_send(struct connectdata *conn,
01440                          int sockindex,
01441                          const void *mem,
01442                          size_t len,
01443                          CURLcode *curlcode)
01444 {
01445   ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
01446 
01447   if(rc < 0) {
01448     *curlcode = (rc == GNUTLS_E_AGAIN)
01449       ? CURLE_AGAIN
01450       : CURLE_SEND_ERROR;
01451 
01452     rc = -1;
01453   }
01454 
01455   return rc;
01456 }
01457 
01458 static void close_one(struct ssl_connect_data *ssl)
01459 {
01460   if(ssl->session) {
01461     gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
01462     gnutls_deinit(ssl->session);
01463     ssl->session = NULL;
01464   }
01465   if(ssl->cred) {
01466     gnutls_certificate_free_credentials(ssl->cred);
01467     ssl->cred = NULL;
01468   }
01469 #ifdef USE_TLS_SRP
01470   if(ssl->srp_client_cred) {
01471     gnutls_srp_free_client_credentials(ssl->srp_client_cred);
01472     ssl->srp_client_cred = NULL;
01473   }
01474 #endif
01475 }
01476 
01477 void Curl_gtls_close(struct connectdata *conn, int sockindex)
01478 {
01479   close_one(&conn->ssl[sockindex]);
01480   close_one(&conn->proxy_ssl[sockindex]);
01481 }
01482 
01483 /*
01484  * This function is called to shut down the SSL layer but keep the
01485  * socket open (CCC - Clear Command Channel)
01486  */
01487 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
01488 {
01489   ssize_t result;
01490   int retval = 0;
01491   struct Curl_easy *data = conn->data;
01492   int done = 0;
01493   char buf[120];
01494 
01495   /* This has only been tested on the proftpd server, and the mod_tls code
01496      sends a close notify alert without waiting for a close notify alert in
01497      response. Thus we wait for a close notify alert from the server, but
01498      we do not send one. Let's hope other servers do the same... */
01499 
01500   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
01501       gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
01502 
01503   if(conn->ssl[sockindex].session) {
01504     while(!done) {
01505       int what = SOCKET_READABLE(conn->sock[sockindex],
01506                                  SSL_SHUTDOWN_TIMEOUT);
01507       if(what > 0) {
01508         /* Something to read, let's do it and hope that it is the close
01509            notify alert from the server */
01510         result = gnutls_record_recv(conn->ssl[sockindex].session,
01511                                     buf, sizeof(buf));
01512         switch(result) {
01513         case 0:
01514           /* This is the expected response. There was no data but only
01515              the close notify alert */
01516           done = 1;
01517           break;
01518         case GNUTLS_E_AGAIN:
01519         case GNUTLS_E_INTERRUPTED:
01520           infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
01521           break;
01522         default:
01523           retval = -1;
01524           done = 1;
01525           break;
01526         }
01527       }
01528       else if(0 == what) {
01529         /* timeout */
01530         failf(data, "SSL shutdown timeout");
01531         done = 1;
01532         break;
01533       }
01534       else {
01535         /* anything that gets here is fatally bad */
01536         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
01537         retval = -1;
01538         done = 1;
01539       }
01540     }
01541     gnutls_deinit(conn->ssl[sockindex].session);
01542   }
01543   gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
01544 
01545 #ifdef USE_TLS_SRP
01546   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
01547      && SSL_SET_OPTION(username) != NULL)
01548     gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
01549 #endif
01550 
01551   conn->ssl[sockindex].cred = NULL;
01552   conn->ssl[sockindex].session = NULL;
01553 
01554   return retval;
01555 }
01556 
01557 static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
01558                          int num,                  /* socketindex */
01559                          char *buf,                /* store read data here */
01560                          size_t buffersize,        /* max amount to read */
01561                          CURLcode *curlcode)
01562 {
01563   ssize_t ret;
01564 
01565   ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
01566   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
01567     *curlcode = CURLE_AGAIN;
01568     return -1;
01569   }
01570 
01571   if(ret == GNUTLS_E_REHANDSHAKE) {
01572     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
01573        proper way" takes a whole lot of work. */
01574     CURLcode result = handshake(conn, num, FALSE, FALSE);
01575     if(result)
01576       /* handshake() writes error message on its own */
01577       *curlcode = result;
01578     else
01579       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
01580     return -1;
01581   }
01582 
01583   if(ret < 0) {
01584     failf(conn->data, "GnuTLS recv error (%d): %s",
01585           (int)ret, gnutls_strerror((int)ret));
01586     *curlcode = CURLE_RECV_ERROR;
01587     return -1;
01588   }
01589 
01590   return ret;
01591 }
01592 
01593 void Curl_gtls_session_free(void *ptr)
01594 {
01595   free(ptr);
01596 }
01597 
01598 size_t Curl_gtls_version(char *buffer, size_t size)
01599 {
01600   return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
01601 }
01602 
01603 #ifndef USE_GNUTLS_NETTLE
01604 static int Curl_gtls_seed(struct Curl_easy *data)
01605 {
01606   /* we have the "SSL is seeded" boolean static to prevent multiple
01607      time-consuming seedings in vain */
01608   static bool ssl_seeded = FALSE;
01609 
01610   /* Quickly add a bit of entropy */
01611   gcry_fast_random_poll();
01612 
01613   if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
01614      data->set.str[STRING_SSL_EGDSOCKET]) {
01615 
01616     /* TODO: to a good job seeding the RNG
01617        This may involve the gcry_control function and these options:
01618        GCRYCTL_SET_RANDOM_SEED_FILE
01619        GCRYCTL_SET_RNDEGD_SOCKET
01620     */
01621     ssl_seeded = TRUE;
01622   }
01623   return 0;
01624 }
01625 #endif
01626 
01627 /* data might be NULL! */
01628 int Curl_gtls_random(struct Curl_easy *data,
01629                      unsigned char *entropy,
01630                      size_t length)
01631 {
01632 #if defined(USE_GNUTLS_NETTLE)
01633   (void)data;
01634   gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
01635 #elif defined(USE_GNUTLS)
01636   if(data)
01637     Curl_gtls_seed(data); /* Initiate the seed if not already done */
01638   gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
01639 #endif
01640   return 0;
01641 }
01642 
01643 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
01644                       size_t tmplen,
01645                       unsigned char *md5sum, /* output */
01646                       size_t md5len)
01647 {
01648 #if defined(USE_GNUTLS_NETTLE)
01649   struct md5_ctx MD5pw;
01650   md5_init(&MD5pw);
01651   md5_update(&MD5pw, (unsigned int)tmplen, tmp);
01652   md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
01653 #elif defined(USE_GNUTLS)
01654   gcry_md_hd_t MD5pw;
01655   gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
01656   gcry_md_write(MD5pw, tmp, tmplen);
01657   memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
01658   gcry_md_close(MD5pw);
01659 #endif
01660 }
01661 
01662 void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
01663                       size_t tmplen,
01664                       unsigned char *sha256sum, /* output */
01665                       size_t sha256len)
01666 {
01667 #if defined(USE_GNUTLS_NETTLE)
01668   struct sha256_ctx SHA256pw;
01669   sha256_init(&SHA256pw);
01670   sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
01671   sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
01672 #elif defined(USE_GNUTLS)
01673   gcry_md_hd_t SHA256pw;
01674   gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
01675   gcry_md_write(SHA256pw, tmp, tmplen);
01676   memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
01677   gcry_md_close(SHA256pw);
01678 #endif
01679 }
01680 
01681 bool Curl_gtls_cert_status_request(void)
01682 {
01683 #ifdef HAS_OCSP
01684   return TRUE;
01685 #else
01686   return FALSE;
01687 #endif
01688 }
01689 
01690 #endif /* USE_GNUTLS */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:04