1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
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.se/docs/copyright.html.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 * SPDX-License-Identifier: curl
23 ***************************************************************************/
26 * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
27 * but vtls.c should ever call or use these functions.
29 * Note: don't use the GnuTLS' *_t variable type names in this source code,
30 * since they were not present in 1.0.X.
33 #include "curl_setup.h"
37 #include <gnutls/abstract.h>
38 #include <gnutls/gnutls.h>
39 #include <gnutls/x509.h>
40 #include <gnutls/crypto.h>
41 #include <nettle/sha2.h>
45 #include "inet_pton.h"
48 #include "vauth/vauth.h"
49 #include "parsedate.h"
50 #include "connect.h" /* for the connect timeout */
56 #include "curl_printf.h"
57 #include "curl_memory.h"
58 /* The last #include file should be: */
61 #ifdef HAVE_GNUTLS_SRP
62 /* the function exists */
64 /* the functionality is not disabled */
65 #define USE_GNUTLS_SRP
69 /* Enable GnuTLS debugging by defining GTLSDEBUG */
70 /*#define GTLSDEBUG */
73 static void tls_log_func(int level, const char *str)
75 fprintf(stderr, "|<%d>| %s", level, str);
78 static bool gtls_inited = FALSE;
80 #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
81 #error "too old GnuTLS version"
84 # include <gnutls/ocsp.h>
86 struct ssl_backend_data {
87 gnutls_session_t session;
88 gnutls_certificate_credentials_t cred;
90 gnutls_srp_client_credentials_t srp_client_cred;
94 static ssize_t gtls_push(void *s, const void *buf, size_t len)
96 curl_socket_t sock = *(curl_socket_t *)s;
97 ssize_t ret = swrite(sock, buf, len);
101 static ssize_t gtls_pull(void *s, void *buf, size_t len)
103 curl_socket_t sock = *(curl_socket_t *)s;
104 ssize_t ret = sread(sock, buf, len);
108 static ssize_t gtls_push_ssl(void *s, const void *buf, size_t len)
110 return gnutls_record_send((gnutls_session_t) s, buf, len);
113 static ssize_t gtls_pull_ssl(void *s, void *buf, size_t len)
115 return gnutls_record_recv((gnutls_session_t) s, buf, len);
120 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
121 * are not thread-safe and thus this function itself is not thread-safe and
122 * must only be called from within curl_global_init() to keep the thread
123 * situation under control!
125 static int gtls_init(void)
129 ret = gnutls_global_init()?0:1;
131 gnutls_global_set_log_function(tls_log_func);
132 gnutls_global_set_log_level(2);
139 static void gtls_cleanup(void)
142 gnutls_global_deinit();
147 #ifndef CURL_DISABLE_VERBOSE_STRINGS
148 static void showtime(struct Curl_easy *data,
153 const struct tm *tm = &buffer;
155 CURLcode result = Curl_gmtime(stamp, &buffer);
161 " %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
163 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
165 Curl_month[tm->tm_mon],
170 infof(data, "%s", str);
174 static gnutls_datum_t load_file(const char *file)
177 gnutls_datum_t loaded_file = { NULL, 0 };
181 f = fopen(file, "rb");
184 if(fseek(f, 0, SEEK_END) != 0
185 || (filelen = ftell(f)) < 0
186 || fseek(f, 0, SEEK_SET) != 0
187 || !(ptr = malloc((size_t)filelen)))
189 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
194 loaded_file.data = ptr;
195 loaded_file.size = (unsigned int)filelen;
201 static void unload_file(gnutls_datum_t data)
207 /* this function does a SSL/TLS (re-)handshake */
208 static CURLcode handshake(struct Curl_easy *data,
209 struct connectdata *conn,
214 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
215 struct ssl_backend_data *backend = connssl->backend;
216 gnutls_session_t session;
217 curl_socket_t sockfd = conn->sock[sockindex];
219 DEBUGASSERT(backend);
220 session = backend->session;
223 timediff_t timeout_ms;
226 /* check allowed time left */
227 timeout_ms = Curl_timeleft(data, NULL, duringconnect);
230 /* no need to continue if time already is up */
231 failf(data, "SSL connection timeout");
232 return CURLE_OPERATION_TIMEDOUT;
235 /* if ssl is expecting something, check if it's available. */
236 if(connssl->connecting_state == ssl_connect_2_reading
237 || connssl->connecting_state == ssl_connect_2_writing) {
239 curl_socket_t writefd = ssl_connect_2_writing ==
240 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
241 curl_socket_t readfd = ssl_connect_2_reading ==
242 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
244 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
246 timeout_ms?timeout_ms:1000);
249 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
250 return CURLE_SSL_CONNECT_ERROR;
255 else if(timeout_ms) {
257 failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
258 return CURLE_OPERATION_TIMEDOUT;
261 /* socket is readable or writable */
264 rc = gnutls_handshake(session);
266 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
267 connssl->connecting_state =
268 gnutls_record_get_direction(session)?
269 ssl_connect_2_writing:ssl_connect_2_reading;
272 else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
273 const char *strerr = NULL;
275 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
276 int alert = gnutls_alert_get(session);
277 strerr = gnutls_alert_get_name(alert);
281 strerr = gnutls_strerror(rc);
283 infof(data, "gnutls_handshake() warning: %s", strerr);
287 const char *strerr = NULL;
289 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
290 int alert = gnutls_alert_get(session);
291 strerr = gnutls_alert_get_name(alert);
295 strerr = gnutls_strerror(rc);
297 failf(data, "gnutls_handshake() failed: %s", strerr);
298 return CURLE_SSL_CONNECT_ERROR;
301 /* Reset our connect state machine */
302 connssl->connecting_state = ssl_connect_1;
307 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
309 if(!type || !type[0])
310 return GNUTLS_X509_FMT_PEM;
311 if(strcasecompare(type, "PEM"))
312 return GNUTLS_X509_FMT_PEM;
313 if(strcasecompare(type, "DER"))
314 return GNUTLS_X509_FMT_DER;
315 return GNUTLS_X509_FMT_PEM; /* default to PEM */
318 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
319 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
320 requested in the priority string, so treat it specially
322 #define GNUTLS_SRP "+SRP"
325 set_ssl_version_min_max(struct Curl_easy *data,
326 const char **prioritylist,
327 const char *tls13support)
329 struct connectdata *conn = data->conn;
330 long ssl_version = SSL_CONN_CONFIG(version);
331 long ssl_version_max = SSL_CONN_CONFIG(version_max);
333 if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
334 (ssl_version == CURL_SSLVERSION_TLSv1))
335 ssl_version = CURL_SSLVERSION_TLSv1_0;
336 if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
337 ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
339 /* If the running GnuTLS doesn't support TLS 1.3, we must not specify a
340 prioritylist involving that since it will make GnuTLS return an en
342 if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
343 (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
344 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
347 else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
348 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
351 switch(ssl_version | ssl_version_max) {
352 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
353 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
356 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
357 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
358 "+VERS-TLS1.1:+VERS-TLS1.0";
360 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
361 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
362 "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
364 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
365 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
368 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
369 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
370 "+VERS-TLS1.2:+VERS-TLS1.1";
372 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
373 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
376 case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
377 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
380 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
381 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
383 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
384 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
385 "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
387 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
388 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
389 "+VERS-TLS1.3:+VERS-TLS1.2";
393 failf(data, "GnuTLS: cannot set ssl protocol");
394 return CURLE_SSL_CONNECT_ERROR;
398 gtls_connect_step1(struct Curl_easy *data,
399 struct connectdata *conn,
402 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
403 struct ssl_backend_data *backend = connssl->backend;
404 unsigned int init_flags;
405 gnutls_session_t session;
407 bool sni = TRUE; /* default is SNI enabled */
408 void *transport_ptr = NULL;
409 gnutls_push_func gnutls_transport_push = NULL;
410 gnutls_pull_func gnutls_transport_pull = NULL;
412 struct in6_addr addr;
416 const char *prioritylist;
417 const char *err = NULL;
418 const char * const hostname = SSL_HOST_NAME();
419 long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
420 const char *tls13support;
423 DEBUGASSERT(backend);
425 if(connssl->state == ssl_connection_complete)
426 /* to make us tolerant against being called more than once for the
433 /* Initialize certverifyresult to OK */
434 *certverifyresult = 0;
436 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
437 failf(data, "GnuTLS does not support SSLv2");
438 return CURLE_SSL_CONNECT_ERROR;
440 else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
441 sni = FALSE; /* SSLv3 has no SNI */
443 /* allocate a cred struct */
444 rc = gnutls_certificate_allocate_credentials(&backend->cred);
445 if(rc != GNUTLS_E_SUCCESS) {
446 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
447 return CURLE_SSL_CONNECT_ERROR;
450 #ifdef USE_GNUTLS_SRP
451 if((SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) &&
452 Curl_auth_allowed_to_host(data)) {
453 infof(data, "Using TLS-SRP username: %s",
454 SSL_SET_OPTION(primary.username));
456 rc = gnutls_srp_allocate_client_credentials(&backend->srp_client_cred);
457 if(rc != GNUTLS_E_SUCCESS) {
458 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
459 gnutls_strerror(rc));
460 return CURLE_OUT_OF_MEMORY;
463 rc = gnutls_srp_set_client_credentials(backend->srp_client_cred,
464 SSL_SET_OPTION(primary.username),
465 SSL_SET_OPTION(primary.password));
466 if(rc != GNUTLS_E_SUCCESS) {
467 failf(data, "gnutls_srp_set_client_cred() failed: %s",
468 gnutls_strerror(rc));
469 return CURLE_BAD_FUNCTION_ARGUMENT;
474 if(SSL_CONN_CONFIG(CAfile)) {
475 /* set the trusted CA cert bundle file */
476 gnutls_certificate_set_verify_flags(backend->cred,
477 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
479 rc = gnutls_certificate_set_x509_trust_file(backend->cred,
480 SSL_CONN_CONFIG(CAfile),
481 GNUTLS_X509_FMT_PEM);
483 infof(data, "error reading ca cert file %s (%s)",
484 SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
485 if(SSL_CONN_CONFIG(verifypeer)) {
486 *certverifyresult = rc;
487 return CURLE_SSL_CACERT_BADFILE;
491 infof(data, "found %d certificates in %s", rc,
492 SSL_CONN_CONFIG(CAfile));
495 if(SSL_CONN_CONFIG(CApath)) {
496 /* set the trusted CA cert directory */
497 rc = gnutls_certificate_set_x509_trust_dir(backend->cred,
498 SSL_CONN_CONFIG(CApath),
499 GNUTLS_X509_FMT_PEM);
501 infof(data, "error reading ca cert file %s (%s)",
502 SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
503 if(SSL_CONN_CONFIG(verifypeer)) {
504 *certverifyresult = rc;
505 return CURLE_SSL_CACERT_BADFILE;
509 infof(data, "found %d certificates in %s",
510 rc, SSL_CONN_CONFIG(CApath));
513 #ifdef CURL_CA_FALLBACK
514 /* use system ca certificate store as fallback */
515 if(SSL_CONN_CONFIG(verifypeer) &&
516 !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
517 /* this ignores errors on purpose */
518 gnutls_certificate_set_x509_system_trust(backend->cred);
522 if(SSL_SET_OPTION(primary.CRLfile)) {
523 /* set the CRL list file */
524 rc = gnutls_certificate_set_x509_crl_file(backend->cred,
525 SSL_SET_OPTION(primary.CRLfile),
526 GNUTLS_X509_FMT_PEM);
528 failf(data, "error reading crl file %s (%s)",
529 SSL_SET_OPTION(primary.CRLfile), gnutls_strerror(rc));
530 return CURLE_SSL_CRL_BADFILE;
533 infof(data, "found %d CRL in %s",
534 rc, SSL_SET_OPTION(primary.CRLfile));
537 /* Initialize TLS session as a client */
538 init_flags = GNUTLS_CLIENT;
540 #if defined(GNUTLS_FORCE_CLIENT_CERT)
541 init_flags |= GNUTLS_FORCE_CLIENT_CERT;
544 #if defined(GNUTLS_NO_TICKETS)
545 /* Disable TLS session tickets */
546 init_flags |= GNUTLS_NO_TICKETS;
549 rc = gnutls_init(&backend->session, init_flags);
550 if(rc != GNUTLS_E_SUCCESS) {
551 failf(data, "gnutls_init() failed: %d", rc);
552 return CURLE_SSL_CONNECT_ERROR;
555 /* convenient assign */
556 session = backend->session;
558 if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
560 (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
564 char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
565 if(!snihost || gnutls_server_name_set(session, GNUTLS_NAME_DNS, snihost,
567 failf(data, "Failed to set SNI");
568 return CURLE_SSL_CONNECT_ERROR;
572 /* Use default priorities */
573 rc = gnutls_set_default_priority(session);
574 if(rc != GNUTLS_E_SUCCESS)
575 return CURLE_SSL_CONNECT_ERROR;
577 /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
578 tls13support = gnutls_check_version("3.6.5");
580 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
581 * removed if a run-time error indicates that SRP is not supported by this
584 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2 ||
585 SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) {
586 failf(data, "GnuTLS does not support SSLv2 or SSLv3");
587 return CURLE_SSL_CONNECT_ERROR;
590 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_TLSv1_3) {
592 failf(data, "This GnuTLS installation does not support TLS 1.3");
593 return CURLE_SSL_CONNECT_ERROR;
597 /* At this point we know we have a supported TLS version, so set it */
598 result = set_ssl_version_min_max(data, &prioritylist, tls13support);
602 #ifdef USE_GNUTLS_SRP
603 /* Only add SRP to the cipher list if SRP is requested. Otherwise
604 * GnuTLS will disable TLS 1.3 support. */
605 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
606 size_t len = strlen(prioritylist);
608 char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
610 return CURLE_OUT_OF_MEMORY;
611 strcpy(prioritysrp, prioritylist);
612 strcpy(prioritysrp + len, ":" GNUTLS_SRP);
613 rc = gnutls_priority_set_direct(session, prioritysrp, &err);
616 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
617 infof(data, "This GnuTLS does not support SRP");
622 infof(data, "GnuTLS ciphers: %s", prioritylist);
623 rc = gnutls_priority_set_direct(session, prioritylist, &err);
624 #ifdef USE_GNUTLS_SRP
628 if(rc != GNUTLS_E_SUCCESS) {
629 failf(data, "Error %d setting GnuTLS cipher list starting with %s",
631 return CURLE_SSL_CONNECT_ERROR;
634 if(conn->bits.tls_enable_alpn) {
636 gnutls_datum_t protocols[2];
639 if(data->state.httpwant >= CURL_HTTP_VERSION_2
640 #ifndef CURL_DISABLE_PROXY
641 && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
644 protocols[cur].data = (unsigned char *)ALPN_H2;
645 protocols[cur].size = ALPN_H2_LENGTH;
647 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
651 protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
652 protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
654 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
656 if(gnutls_alpn_set_protocols(session, protocols, cur, 0)) {
657 failf(data, "failed setting ALPN");
658 return CURLE_SSL_CONNECT_ERROR;
662 if(SSL_SET_OPTION(primary.clientcert)) {
663 if(SSL_SET_OPTION(key_passwd)) {
664 const unsigned int supported_key_encryption_algorithms =
665 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
666 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
667 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
668 GNUTLS_PKCS_USE_PBES2_AES_256;
669 rc = gnutls_certificate_set_x509_key_file2(
671 SSL_SET_OPTION(primary.clientcert),
672 SSL_SET_OPTION(key) ?
673 SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
674 do_file_type(SSL_SET_OPTION(cert_type)),
675 SSL_SET_OPTION(key_passwd),
676 supported_key_encryption_algorithms);
677 if(rc != GNUTLS_E_SUCCESS) {
679 "error reading X.509 potentially-encrypted key file: %s",
680 gnutls_strerror(rc));
681 return CURLE_SSL_CONNECT_ERROR;
685 if(gnutls_certificate_set_x509_key_file(
687 SSL_SET_OPTION(primary.clientcert),
688 SSL_SET_OPTION(key) ?
689 SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
690 do_file_type(SSL_SET_OPTION(cert_type)) ) !=
692 failf(data, "error reading X.509 key or certificate file");
693 return CURLE_SSL_CONNECT_ERROR;
698 #ifdef USE_GNUTLS_SRP
699 /* put the credentials to the current session */
700 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
701 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
702 backend->srp_client_cred);
703 if(rc != GNUTLS_E_SUCCESS) {
704 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
705 return CURLE_SSL_CONNECT_ERROR;
711 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
713 if(rc != GNUTLS_E_SUCCESS) {
714 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
715 return CURLE_SSL_CONNECT_ERROR;
719 #ifndef CURL_DISABLE_PROXY
720 if(conn->proxy_ssl[sockindex].use) {
721 struct ssl_backend_data *proxy_backend;
722 proxy_backend = conn->proxy_ssl[sockindex].backend;
723 DEBUGASSERT(proxy_backend);
724 transport_ptr = proxy_backend->session;
725 gnutls_transport_push = gtls_push_ssl;
726 gnutls_transport_pull = gtls_pull_ssl;
731 /* file descriptor for the socket */
732 transport_ptr = &conn->sock[sockindex];
733 gnutls_transport_push = gtls_push;
734 gnutls_transport_pull = gtls_pull;
737 /* set the connection handle */
738 gnutls_transport_set_ptr(session, transport_ptr);
740 /* register callback functions to send and receive data. */
741 gnutls_transport_set_push_function(session, gnutls_transport_push);
742 gnutls_transport_set_pull_function(session, gnutls_transport_pull);
744 if(SSL_CONN_CONFIG(verifystatus)) {
745 rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
746 if(rc != GNUTLS_E_SUCCESS) {
747 failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
748 return CURLE_SSL_CONNECT_ERROR;
752 /* This might be a reconnect, so we check for a session ID in the cache
753 to speed up things */
754 if(SSL_SET_OPTION(primary.sessionid)) {
758 Curl_ssl_sessionid_lock(data);
759 if(!Curl_ssl_getsessionid(data, conn,
760 SSL_IS_PROXY() ? TRUE : FALSE,
761 &ssl_sessionid, &ssl_idsize, sockindex)) {
762 /* we got a session id, use it! */
763 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
765 /* Informational message */
766 infof(data, "SSL re-using session ID");
768 Curl_ssl_sessionid_unlock(data);
774 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
775 gnutls_x509_crt_t cert,
776 const char *pinnedpubkey)
779 size_t len1 = 0, len2 = 0;
780 unsigned char *buff1 = NULL;
782 gnutls_pubkey_t key = NULL;
784 /* Result is returned to caller */
785 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
787 /* if a path wasn't specified, don't pin */
797 /* Begin Gyrations to get the public key */
798 gnutls_pubkey_init(&key);
800 ret = gnutls_pubkey_import_x509(key, cert, 0);
804 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
805 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
808 buff1 = malloc(len1);
814 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
815 if(ret < 0 || len1 != len2)
820 /* The one good exit point */
821 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
825 gnutls_pubkey_deinit(key);
827 Curl_safefree(buff1);
832 static Curl_recv gtls_recv;
833 static Curl_send gtls_send;
836 Curl_gtls_verifyserver(struct Curl_easy *data,
837 struct connectdata *conn,
838 gnutls_session_t session,
841 unsigned int cert_list_size;
842 const gnutls_datum_t *chainp;
843 unsigned int verify_status = 0;
844 gnutls_x509_crt_t x509_cert, x509_issuer;
845 gnutls_datum_t issuerp;
846 gnutls_datum_t certfields;
847 char certname[65] = ""; /* limited to 64 chars by ASN.1 */
852 gnutls_datum_t proto;
853 CURLcode result = CURLE_OK;
854 #ifndef CURL_DISABLE_VERBOSE_STRINGS
857 gnutls_protocol_t version = gnutls_protocol_get_version(session);
859 const char * const hostname = SSL_HOST_NAME();
860 long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
862 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
863 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
864 gnutls_cipher_get(session),
865 gnutls_mac_get(session));
867 infof(data, "SSL connection using %s / %s",
868 gnutls_protocol_get_name(version), ptr);
870 /* This function will return the peer's raw certificate (chain) as sent by
871 the peer. These certificates are in raw format (DER encoded for
872 X.509). In case of a X.509 then a certificate list may be present. The
873 first certificate in the list is the peer's certificate, following the
874 issuer's certificate, then the issuer's issuer etc. */
876 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
878 if(SSL_CONN_CONFIG(verifypeer) ||
879 SSL_CONN_CONFIG(verifyhost) ||
880 SSL_CONN_CONFIG(issuercert)) {
881 #ifdef USE_GNUTLS_SRP
882 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
883 && SSL_SET_OPTION(primary.username)
884 && !SSL_CONN_CONFIG(verifypeer)
885 && gnutls_cipher_get(session)) {
886 /* no peer cert, but auth is ok if we have SRP user and cipher and no
891 failf(data, "failed to get server cert");
892 *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
893 return CURLE_PEER_FAILED_VERIFICATION;
894 #ifdef USE_GNUTLS_SRP
898 infof(data, " common name: WARNING couldn't obtain");
901 if(data->set.ssl.certinfo && chainp) {
904 result = Curl_ssl_init_certinfo(data, cert_list_size);
908 for(i = 0; i < cert_list_size; i++) {
909 const char *beg = (const char *) chainp[i].data;
910 const char *end = beg + chainp[i].size;
912 result = Curl_extract_certinfo(data, i, beg, end);
918 if(SSL_CONN_CONFIG(verifypeer)) {
919 /* This function will try to verify the peer's certificate and return its
920 status (trusted, invalid etc.). The value of status should be one or
921 more of the gnutls_certificate_status_t enumerated elements bitwise
922 or'd. To avoid denial of service attacks some default upper limits
923 regarding the certificate key size and chain size are set. To override
924 them use gnutls_certificate_set_verify_limits(). */
926 rc = gnutls_certificate_verify_peers2(session, &verify_status);
928 failf(data, "server cert verify failed: %d", rc);
929 *certverifyresult = rc;
930 return CURLE_SSL_CONNECT_ERROR;
933 *certverifyresult = verify_status;
935 /* verify_status is a bitmask of gnutls_certificate_status bits */
936 if(verify_status & GNUTLS_CERT_INVALID) {
937 if(SSL_CONN_CONFIG(verifypeer)) {
938 failf(data, "server certificate verification failed. CAfile: %s "
939 "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
941 SSL_SET_OPTION(primary.CRLfile) ?
942 SSL_SET_OPTION(primary.CRLfile) : "none");
943 return CURLE_PEER_FAILED_VERIFICATION;
946 infof(data, " server certificate verification FAILED");
949 infof(data, " server certificate verification OK");
952 infof(data, " server certificate verification SKIPPED");
954 if(SSL_CONN_CONFIG(verifystatus)) {
955 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
956 gnutls_datum_t status_request;
957 gnutls_ocsp_resp_t ocsp_resp;
959 gnutls_ocsp_cert_status_t status;
960 gnutls_x509_crl_reason_t reason;
962 rc = gnutls_ocsp_status_request_get(session, &status_request);
964 infof(data, " server certificate status verification FAILED");
966 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
967 failf(data, "No OCSP response received");
968 return CURLE_SSL_INVALIDCERTSTATUS;
972 failf(data, "Invalid OCSP response received");
973 return CURLE_SSL_INVALIDCERTSTATUS;
976 gnutls_ocsp_resp_init(&ocsp_resp);
978 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
980 failf(data, "Invalid OCSP response received");
981 return CURLE_SSL_INVALIDCERTSTATUS;
984 (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
985 &status, NULL, NULL, NULL, &reason);
988 case GNUTLS_OCSP_CERT_GOOD:
991 case GNUTLS_OCSP_CERT_REVOKED: {
992 const char *crl_reason;
996 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
997 crl_reason = "unspecified reason";
1000 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1001 crl_reason = "private key compromised";
1004 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1005 crl_reason = "CA compromised";
1008 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1009 crl_reason = "affiliation has changed";
1012 case GNUTLS_X509_CRLREASON_SUPERSEDED:
1013 crl_reason = "certificate superseded";
1016 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1017 crl_reason = "operation has ceased";
1020 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1021 crl_reason = "certificate is on hold";
1024 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1025 crl_reason = "will be removed from delta CRL";
1028 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1029 crl_reason = "privilege withdrawn";
1032 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1033 crl_reason = "AA compromised";
1037 failf(data, "Server certificate was revoked: %s", crl_reason);
1042 case GNUTLS_OCSP_CERT_UNKNOWN:
1043 failf(data, "Server certificate status is unknown");
1047 gnutls_ocsp_resp_deinit(ocsp_resp);
1049 return CURLE_SSL_INVALIDCERTSTATUS;
1052 infof(data, " server certificate status verification OK");
1055 infof(data, " server certificate status verification SKIPPED");
1057 /* initialize an X.509 certificate structure. */
1058 gnutls_x509_crt_init(&x509_cert);
1061 /* convert the given DER or PEM encoded Certificate to the native
1062 gnutls_x509_crt_t format */
1063 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1065 if(SSL_CONN_CONFIG(issuercert)) {
1066 gnutls_x509_crt_init(&x509_issuer);
1067 issuerp = load_file(SSL_CONN_CONFIG(issuercert));
1068 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1069 rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1070 gnutls_x509_crt_deinit(x509_issuer);
1071 unload_file(issuerp);
1073 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1074 SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
1075 gnutls_x509_crt_deinit(x509_cert);
1076 return CURLE_SSL_ISSUER_ERROR;
1078 infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
1079 SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
1082 size = sizeof(certname);
1083 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1084 0, /* the first and only one */
1089 infof(data, "error fetching CN from cert:%s",
1090 gnutls_strerror(rc));
1093 /* This function will check if the given certificate's subject matches the
1094 given hostname. This is a basic implementation of the matching described
1095 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1096 alternative name PKIX extension. Returns non zero on success, and zero on
1098 rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
1099 #if GNUTLS_VERSION_NUMBER < 0x030306
1100 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1104 #define use_addr in6_addr
1106 #define use_addr in_addr
1108 unsigned char addrbuf[sizeof(struct use_addr)];
1111 if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
1114 else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
1119 unsigned char certaddr[sizeof(struct use_addr)];
1123 size_t certaddrlen = sizeof(certaddr);
1124 int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1125 &certaddrlen, NULL);
1126 /* If this happens, it wasn't an IP address. */
1127 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1131 if(ret != GNUTLS_SAN_IPADDRESS)
1133 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1142 if(SSL_CONN_CONFIG(verifyhost)) {
1143 failf(data, "SSL: certificate subject name (%s) does not match "
1144 "target host name '%s'", certname, SSL_HOST_DISPNAME());
1145 gnutls_x509_crt_deinit(x509_cert);
1146 return CURLE_PEER_FAILED_VERIFICATION;
1149 infof(data, " common name: %s (does not match '%s')",
1150 certname, SSL_HOST_DISPNAME());
1153 infof(data, " common name: %s (matched)", certname);
1155 /* Check for time-based validity */
1156 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1158 if(certclock == (time_t)-1) {
1159 if(SSL_CONN_CONFIG(verifypeer)) {
1160 failf(data, "server cert expiration date verify failed");
1161 *certverifyresult = GNUTLS_CERT_EXPIRED;
1162 gnutls_x509_crt_deinit(x509_cert);
1163 return CURLE_SSL_CONNECT_ERROR;
1166 infof(data, " server certificate expiration date verify FAILED");
1169 if(certclock < time(NULL)) {
1170 if(SSL_CONN_CONFIG(verifypeer)) {
1171 failf(data, "server certificate expiration date has passed.");
1172 *certverifyresult = GNUTLS_CERT_EXPIRED;
1173 gnutls_x509_crt_deinit(x509_cert);
1174 return CURLE_PEER_FAILED_VERIFICATION;
1177 infof(data, " server certificate expiration date FAILED");
1180 infof(data, " server certificate expiration date OK");
1183 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1185 if(certclock == (time_t)-1) {
1186 if(SSL_CONN_CONFIG(verifypeer)) {
1187 failf(data, "server cert activation date verify failed");
1188 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1189 gnutls_x509_crt_deinit(x509_cert);
1190 return CURLE_SSL_CONNECT_ERROR;
1193 infof(data, " server certificate activation date verify FAILED");
1196 if(certclock > time(NULL)) {
1197 if(SSL_CONN_CONFIG(verifypeer)) {
1198 failf(data, "server certificate not activated yet.");
1199 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1200 gnutls_x509_crt_deinit(x509_cert);
1201 return CURLE_PEER_FAILED_VERIFICATION;
1204 infof(data, " server certificate activation date FAILED");
1207 infof(data, " server certificate activation date OK");
1210 ptr = SSL_PINNED_PUB_KEY();
1212 result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
1213 if(result != CURLE_OK) {
1214 failf(data, "SSL: public key does not match pinned public key");
1215 gnutls_x509_crt_deinit(x509_cert);
1230 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1231 /* public key algorithm's parameters */
1232 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1233 infof(data, " certificate public key: %s",
1234 gnutls_pk_algorithm_get_name(algo));
1236 /* version of the X.509 certificate. */
1237 infof(data, " certificate version: #%d",
1238 gnutls_x509_crt_get_version(x509_cert));
1241 rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1243 infof(data, "Failed to get certificate name");
1245 infof(data, " subject: %s", certfields.data);
1247 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1248 showtime(data, "start date", certclock);
1250 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1251 showtime(data, "expire date", certclock);
1253 gnutls_free(certfields.data);
1256 rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1258 infof(data, "Failed to get certificate issuer");
1260 infof(data, " issuer: %s", certfields.data);
1262 gnutls_free(certfields.data);
1266 gnutls_x509_crt_deinit(x509_cert);
1268 if(conn->bits.tls_enable_alpn) {
1269 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1271 infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, proto.size,
1275 if(proto.size == ALPN_H2_LENGTH &&
1276 !memcmp(ALPN_H2, proto.data,
1278 conn->alpn = CURL_HTTP_VERSION_2;
1282 if(proto.size == ALPN_HTTP_1_1_LENGTH &&
1283 !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
1284 conn->alpn = CURL_HTTP_VERSION_1_1;
1288 infof(data, VTLS_INFOF_NO_ALPN);
1290 Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
1291 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
1294 conn->ssl[sockindex].state = ssl_connection_complete;
1296 if(SSL_SET_OPTION(primary.sessionid)) {
1297 /* we always unconditionally get the session id here, as even if we
1298 already got it from the cache and asked to use it in the connection, it
1299 might've been rejected and then a new one is in use now and we need to
1301 void *connect_sessionid;
1302 size_t connect_idsize = 0;
1304 /* get the session ID data size */
1305 gnutls_session_get_data(session, NULL, &connect_idsize);
1306 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1308 if(connect_sessionid) {
1311 void *ssl_sessionid;
1313 /* extract session ID to the allocated buffer */
1314 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1316 Curl_ssl_sessionid_lock(data);
1317 incache = !(Curl_ssl_getsessionid(data, conn,
1318 SSL_IS_PROXY() ? TRUE : FALSE,
1319 &ssl_sessionid, NULL, sockindex));
1321 /* there was one before in the cache, so instead of risking that the
1322 previous one was rejected, we just kill that and store the new */
1323 Curl_ssl_delsessionid(data, ssl_sessionid);
1326 /* store this session id */
1327 result = Curl_ssl_addsessionid(data, conn,
1328 SSL_IS_PROXY() ? TRUE : FALSE,
1329 connect_sessionid, connect_idsize,
1331 Curl_ssl_sessionid_unlock(data);
1333 free(connect_sessionid);
1335 result = CURLE_OUT_OF_MEMORY;
1339 result = CURLE_OUT_OF_MEMORY;
1347 * This function is called after the TCP connect has completed. Setup the TLS
1348 * layer and do all necessary magic.
1350 /* We use connssl->connecting_state to keep track of the connection status;
1351 there are three states: 'ssl_connect_1' (not started yet or complete),
1352 'ssl_connect_2_reading' (waiting for data from server), and
1353 'ssl_connect_2_writing' (waiting to be able to write).
1356 gtls_connect_common(struct Curl_easy *data,
1357 struct connectdata *conn,
1363 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1365 /* Initiate the connection, if not already done */
1366 if(ssl_connect_1 == connssl->connecting_state) {
1367 rc = gtls_connect_step1(data, conn, sockindex);
1372 rc = handshake(data, conn, sockindex, TRUE, nonblocking);
1374 /* handshake() sets its own error message with failf() */
1377 /* Finish connecting once the handshake is done */
1378 if(ssl_connect_1 == connssl->connecting_state) {
1379 struct ssl_backend_data *backend = connssl->backend;
1380 gnutls_session_t session;
1381 DEBUGASSERT(backend);
1382 session = backend->session;
1383 rc = Curl_gtls_verifyserver(data, conn, session, sockindex);
1386 conn->recv[sockindex] = gtls_recv;
1387 conn->send[sockindex] = gtls_send;
1390 *done = ssl_connect_1 == connssl->connecting_state;
1395 static CURLcode gtls_connect_nonblocking(struct Curl_easy *data,
1396 struct connectdata *conn,
1397 int sockindex, bool *done)
1399 return gtls_connect_common(data, conn, sockindex, TRUE, done);
1402 static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn,
1408 result = gtls_connect_common(data, conn, sockindex, FALSE, &done);
1417 static bool gtls_data_pending(const struct connectdata *conn,
1420 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
1422 struct ssl_backend_data *backend = connssl->backend;
1424 DEBUGASSERT(backend);
1426 if(backend->session &&
1427 0 != gnutls_record_check_pending(backend->session))
1430 #ifndef CURL_DISABLE_PROXY
1431 connssl = &conn->proxy_ssl[connindex];
1432 backend = connssl->backend;
1433 DEBUGASSERT(backend);
1434 if(backend->session &&
1435 0 != gnutls_record_check_pending(backend->session))
1442 static ssize_t gtls_send(struct Curl_easy *data,
1448 struct connectdata *conn = data->conn;
1449 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1450 struct ssl_backend_data *backend = connssl->backend;
1453 DEBUGASSERT(backend);
1454 rc = gnutls_record_send(backend->session, mem, len);
1457 *curlcode = (rc == GNUTLS_E_AGAIN)
1467 static void close_one(struct ssl_connect_data *connssl)
1469 struct ssl_backend_data *backend = connssl->backend;
1470 DEBUGASSERT(backend);
1472 if(backend->session) {
1474 /* Maybe the server has already sent a close notify alert.
1475 Read it to avoid an RST on the TCP connection. */
1476 (void)gnutls_record_recv(backend->session, buf, sizeof(buf));
1477 gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1478 gnutls_deinit(backend->session);
1479 backend->session = NULL;
1482 gnutls_certificate_free_credentials(backend->cred);
1483 backend->cred = NULL;
1485 #ifdef USE_GNUTLS_SRP
1486 if(backend->srp_client_cred) {
1487 gnutls_srp_free_client_credentials(backend->srp_client_cred);
1488 backend->srp_client_cred = NULL;
1493 static void gtls_close(struct Curl_easy *data, struct connectdata *conn,
1497 close_one(&conn->ssl[sockindex]);
1498 #ifndef CURL_DISABLE_PROXY
1499 close_one(&conn->proxy_ssl[sockindex]);
1504 * This function is called to shut down the SSL layer but keep the
1505 * socket open (CCC - Clear Command Channel)
1507 static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
1510 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1511 struct ssl_backend_data *backend = connssl->backend;
1514 DEBUGASSERT(backend);
1516 #ifndef CURL_DISABLE_FTP
1517 /* This has only been tested on the proftpd server, and the mod_tls code
1518 sends a close notify alert without waiting for a close notify alert in
1519 response. Thus we wait for a close notify alert from the server, but
1520 we do not send one. Let's hope other servers do the same... */
1522 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1523 gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1526 if(backend->session) {
1532 int what = SOCKET_READABLE(conn->sock[sockindex],
1533 SSL_SHUTDOWN_TIMEOUT);
1535 /* Something to read, let's do it and hope that it is the close
1536 notify alert from the server */
1537 result = gnutls_record_recv(backend->session,
1541 /* This is the expected response. There was no data but only
1542 the close notify alert */
1545 case GNUTLS_E_AGAIN:
1546 case GNUTLS_E_INTERRUPTED:
1547 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED");
1555 else if(0 == what) {
1557 failf(data, "SSL shutdown timeout");
1561 /* anything that gets here is fatally bad */
1562 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1567 gnutls_deinit(backend->session);
1569 gnutls_certificate_free_credentials(backend->cred);
1571 #ifdef USE_GNUTLS_SRP
1572 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
1573 && SSL_SET_OPTION(primary.username) != NULL)
1574 gnutls_srp_free_client_credentials(backend->srp_client_cred);
1577 backend->cred = NULL;
1578 backend->session = NULL;
1583 static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
1584 int num, /* socketindex */
1585 char *buf, /* store read data here */
1586 size_t buffersize, /* max amount to read */
1589 struct connectdata *conn = data->conn;
1590 struct ssl_connect_data *connssl = &conn->ssl[num];
1591 struct ssl_backend_data *backend = connssl->backend;
1594 DEBUGASSERT(backend);
1596 ret = gnutls_record_recv(backend->session, buf, buffersize);
1597 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1598 *curlcode = CURLE_AGAIN;
1602 if(ret == GNUTLS_E_REHANDSHAKE) {
1603 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1604 proper way" takes a whole lot of work. */
1605 CURLcode result = handshake(data, conn, num, FALSE, FALSE);
1607 /* handshake() writes error message on its own */
1610 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1615 failf(data, "GnuTLS recv error (%d): %s",
1617 (int)ret, gnutls_strerror((int)ret));
1618 *curlcode = CURLE_RECV_ERROR;
1625 static void gtls_session_free(void *ptr)
1630 static size_t gtls_version(char *buffer, size_t size)
1632 return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1635 /* data might be NULL! */
1636 static CURLcode gtls_random(struct Curl_easy *data,
1637 unsigned char *entropy, size_t length)
1641 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1642 return rc?CURLE_FAILED_INIT:CURLE_OK;
1645 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1647 unsigned char *sha256sum, /* output */
1650 struct sha256_ctx SHA256pw;
1651 sha256_init(&SHA256pw);
1652 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1653 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1657 static bool gtls_cert_status_request(void)
1662 static void *gtls_get_internals(struct ssl_connect_data *connssl,
1663 CURLINFO info UNUSED_PARAM)
1665 struct ssl_backend_data *backend = connssl->backend;
1667 DEBUGASSERT(backend);
1668 return backend->session;
1671 const struct Curl_ssl Curl_ssl_gnutls = {
1672 { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
1676 SSLSUPP_PINNEDPUBKEY |
1677 SSLSUPP_HTTPS_PROXY,
1679 sizeof(struct ssl_backend_data),
1681 gtls_init, /* init */
1682 gtls_cleanup, /* cleanup */
1683 gtls_version, /* version */
1684 Curl_none_check_cxn, /* check_cxn */
1685 gtls_shutdown, /* shutdown */
1686 gtls_data_pending, /* data_pending */
1687 gtls_random, /* random */
1688 gtls_cert_status_request, /* cert_status_request */
1689 gtls_connect, /* connect */
1690 gtls_connect_nonblocking, /* connect_nonblocking */
1691 Curl_ssl_getsock, /* getsock */
1692 gtls_get_internals, /* get_internals */
1693 gtls_close, /* close_one */
1694 Curl_none_close_all, /* close_all */
1695 gtls_session_free, /* session_free */
1696 Curl_none_set_engine, /* set_engine */
1697 Curl_none_set_engine_default, /* set_engine_default */
1698 Curl_none_engines_list, /* engines_list */
1699 Curl_none_false_start, /* false_start */
1700 gtls_sha256sum, /* sha256sum */
1701 NULL, /* associate_connection */
1702 NULL /* disassociate_connection */
1705 #endif /* USE_GNUTLS */