Annotation of embedaddon/curl/lib/vtls/gtls.c, revision 1.1.1.1

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

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