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 ***************************************************************************/
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.
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.
31 #include "curl_setup.h"
35 #include <gnutls/abstract.h>
36 #include <gnutls/gnutls.h>
37 #include <gnutls/x509.h>
38 #include <gnutls/crypto.h>
39 #include <nettle/sha2.h>
43 #include "inet_pton.h"
46 #include "parsedate.h"
47 #include "connect.h" /* for the connect timeout */
53 #include "curl_printf.h"
54 #include "curl_memory.h"
55 /* The last #include file should be: */
58 #ifdef HAVE_GNUTLS_SRP
59 /* the function exists */
61 /* the functionality is not disabled */
62 #define USE_GNUTLS_SRP
66 /* Enable GnuTLS debugging by defining GTLSDEBUG */
67 /*#define GTLSDEBUG */
70 static void tls_log_func(int level, const char *str)
72 fprintf(stderr, "|<%d>| %s", level, str);
75 static bool gtls_inited = FALSE;
77 #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
78 #error "too old GnuTLS version"
81 # include <gnutls/ocsp.h>
83 struct ssl_backend_data {
84 gnutls_session_t session;
85 gnutls_certificate_credentials_t cred;
87 gnutls_srp_client_credentials_t srp_client_cred;
91 static ssize_t gtls_push(void *s, const void *buf, size_t len)
93 curl_socket_t sock = *(curl_socket_t *)s;
94 ssize_t ret = swrite(sock, buf, len);
98 static ssize_t gtls_pull(void *s, void *buf, size_t len)
100 curl_socket_t sock = *(curl_socket_t *)s;
101 ssize_t ret = sread(sock, buf, len);
105 static ssize_t gtls_push_ssl(void *s, const void *buf, size_t len)
107 return gnutls_record_send((gnutls_session_t) s, buf, len);
110 static ssize_t gtls_pull_ssl(void *s, void *buf, size_t len)
112 return gnutls_record_recv((gnutls_session_t) s, buf, len);
117 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
118 * are not thread-safe and thus this function itself is not thread-safe and
119 * must only be called from within curl_global_init() to keep the thread
120 * situation under control!
122 static int gtls_init(void)
126 ret = gnutls_global_init()?0:1;
128 gnutls_global_set_log_function(tls_log_func);
129 gnutls_global_set_log_level(2);
136 static void gtls_cleanup(void)
139 gnutls_global_deinit();
144 #ifndef CURL_DISABLE_VERBOSE_STRINGS
145 static void showtime(struct Curl_easy *data,
150 const struct tm *tm = &buffer;
152 CURLcode result = Curl_gmtime(stamp, &buffer);
158 " %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
160 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
162 Curl_month[tm->tm_mon],
167 infof(data, "%s", str);
171 static gnutls_datum_t load_file(const char *file)
174 gnutls_datum_t loaded_file = { NULL, 0 };
178 f = fopen(file, "rb");
181 if(fseek(f, 0, SEEK_END) != 0
182 || (filelen = ftell(f)) < 0
183 || fseek(f, 0, SEEK_SET) != 0
184 || !(ptr = malloc((size_t)filelen)))
186 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
191 loaded_file.data = ptr;
192 loaded_file.size = (unsigned int)filelen;
198 static void unload_file(gnutls_datum_t data)
204 /* this function does a SSL/TLS (re-)handshake */
205 static CURLcode handshake(struct Curl_easy *data,
206 struct connectdata *conn,
211 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
212 struct ssl_backend_data *backend = connssl->backend;
213 gnutls_session_t session;
214 curl_socket_t sockfd = conn->sock[sockindex];
216 DEBUGASSERT(backend);
217 session = backend->session;
220 timediff_t timeout_ms;
223 /* check allowed time left */
224 timeout_ms = Curl_timeleft(data, NULL, duringconnect);
227 /* no need to continue if time already is up */
228 failf(data, "SSL connection timeout");
229 return CURLE_OPERATION_TIMEDOUT;
232 /* if ssl is expecting something, check if it's available. */
233 if(connssl->connecting_state == ssl_connect_2_reading
234 || connssl->connecting_state == ssl_connect_2_writing) {
236 curl_socket_t writefd = ssl_connect_2_writing ==
237 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
238 curl_socket_t readfd = ssl_connect_2_reading ==
239 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
241 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
243 timeout_ms?timeout_ms:1000);
246 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
247 return CURLE_SSL_CONNECT_ERROR;
252 else if(timeout_ms) {
254 failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
255 return CURLE_OPERATION_TIMEDOUT;
258 /* socket is readable or writable */
261 rc = gnutls_handshake(session);
263 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
264 connssl->connecting_state =
265 gnutls_record_get_direction(session)?
266 ssl_connect_2_writing:ssl_connect_2_reading;
269 else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
270 const char *strerr = NULL;
272 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
273 int alert = gnutls_alert_get(session);
274 strerr = gnutls_alert_get_name(alert);
278 strerr = gnutls_strerror(rc);
280 infof(data, "gnutls_handshake() warning: %s", strerr);
284 const char *strerr = NULL;
286 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
287 int alert = gnutls_alert_get(session);
288 strerr = gnutls_alert_get_name(alert);
292 strerr = gnutls_strerror(rc);
294 failf(data, "gnutls_handshake() failed: %s", strerr);
295 return CURLE_SSL_CONNECT_ERROR;
298 /* Reset our connect state machine */
299 connssl->connecting_state = ssl_connect_1;
304 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
306 if(!type || !type[0])
307 return GNUTLS_X509_FMT_PEM;
308 if(strcasecompare(type, "PEM"))
309 return GNUTLS_X509_FMT_PEM;
310 if(strcasecompare(type, "DER"))
311 return GNUTLS_X509_FMT_DER;
312 return GNUTLS_X509_FMT_PEM; /* default to PEM */
315 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
316 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
317 requested in the priority string, so treat it specially
319 #define GNUTLS_SRP "+SRP"
322 set_ssl_version_min_max(struct Curl_easy *data,
323 const char **prioritylist,
324 const char *tls13support)
326 struct connectdata *conn = data->conn;
327 long ssl_version = SSL_CONN_CONFIG(version);
328 long ssl_version_max = SSL_CONN_CONFIG(version_max);
330 if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
331 (ssl_version == CURL_SSLVERSION_TLSv1))
332 ssl_version = CURL_SSLVERSION_TLSv1_0;
333 if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
334 ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
336 /* If the running GnuTLS doesn't support TLS 1.3, we must not specify a
337 prioritylist involving that since it will make GnuTLS return an en
339 if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
340 (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
341 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
344 else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
345 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
348 switch(ssl_version | ssl_version_max) {
349 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
350 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
353 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
354 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
355 "+VERS-TLS1.1:+VERS-TLS1.0";
357 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
358 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
359 "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
361 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
362 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
365 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
366 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
367 "+VERS-TLS1.2:+VERS-TLS1.1";
369 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
370 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
373 case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
374 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
377 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
378 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
380 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
381 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
382 "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
384 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
385 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
386 "+VERS-TLS1.3:+VERS-TLS1.2";
390 failf(data, "GnuTLS: cannot set ssl protocol");
391 return CURLE_SSL_CONNECT_ERROR;
395 gtls_connect_step1(struct Curl_easy *data,
396 struct connectdata *conn,
399 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
400 struct ssl_backend_data *backend = connssl->backend;
401 unsigned int init_flags;
402 gnutls_session_t session;
404 bool sni = TRUE; /* default is SNI enabled */
405 void *transport_ptr = NULL;
406 gnutls_push_func gnutls_transport_push = NULL;
407 gnutls_pull_func gnutls_transport_pull = NULL;
409 struct in6_addr addr;
413 const char *prioritylist;
414 const char *err = NULL;
415 const char * const hostname = SSL_HOST_NAME();
416 long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
417 const char *tls13support;
420 DEBUGASSERT(backend);
422 if(connssl->state == ssl_connection_complete)
423 /* to make us tolerant against being called more than once for the
430 /* Initialize certverifyresult to OK */
431 *certverifyresult = 0;
433 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
434 failf(data, "GnuTLS does not support SSLv2");
435 return CURLE_SSL_CONNECT_ERROR;
437 else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
438 sni = FALSE; /* SSLv3 has no SNI */
440 /* allocate a cred struct */
441 rc = gnutls_certificate_allocate_credentials(&backend->cred);
442 if(rc != GNUTLS_E_SUCCESS) {
443 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
444 return CURLE_SSL_CONNECT_ERROR;
447 #ifdef USE_GNUTLS_SRP
448 if((SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) &&
449 Curl_allow_auth_to_host(data)) {
450 infof(data, "Using TLS-SRP username: %s",
451 SSL_SET_OPTION(primary.username));
453 rc = gnutls_srp_allocate_client_credentials(&backend->srp_client_cred);
454 if(rc != GNUTLS_E_SUCCESS) {
455 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
456 gnutls_strerror(rc));
457 return CURLE_OUT_OF_MEMORY;
460 rc = gnutls_srp_set_client_credentials(backend->srp_client_cred,
461 SSL_SET_OPTION(primary.username),
462 SSL_SET_OPTION(primary.password));
463 if(rc != GNUTLS_E_SUCCESS) {
464 failf(data, "gnutls_srp_set_client_cred() failed: %s",
465 gnutls_strerror(rc));
466 return CURLE_BAD_FUNCTION_ARGUMENT;
471 if(SSL_CONN_CONFIG(CAfile)) {
472 /* set the trusted CA cert bundle file */
473 gnutls_certificate_set_verify_flags(backend->cred,
474 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
476 rc = gnutls_certificate_set_x509_trust_file(backend->cred,
477 SSL_CONN_CONFIG(CAfile),
478 GNUTLS_X509_FMT_PEM);
480 infof(data, "error reading ca cert file %s (%s)",
481 SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
482 if(SSL_CONN_CONFIG(verifypeer)) {
483 *certverifyresult = rc;
484 return CURLE_SSL_CACERT_BADFILE;
488 infof(data, "found %d certificates in %s", rc,
489 SSL_CONN_CONFIG(CAfile));
492 if(SSL_CONN_CONFIG(CApath)) {
493 /* set the trusted CA cert directory */
494 rc = gnutls_certificate_set_x509_trust_dir(backend->cred,
495 SSL_CONN_CONFIG(CApath),
496 GNUTLS_X509_FMT_PEM);
498 infof(data, "error reading ca cert file %s (%s)",
499 SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
500 if(SSL_CONN_CONFIG(verifypeer)) {
501 *certverifyresult = rc;
502 return CURLE_SSL_CACERT_BADFILE;
506 infof(data, "found %d certificates in %s",
507 rc, SSL_CONN_CONFIG(CApath));
510 #ifdef CURL_CA_FALLBACK
511 /* use system ca certificate store as fallback */
512 if(SSL_CONN_CONFIG(verifypeer) &&
513 !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
514 /* this ignores errors on purpose */
515 gnutls_certificate_set_x509_system_trust(backend->cred);
519 if(SSL_SET_OPTION(primary.CRLfile)) {
520 /* set the CRL list file */
521 rc = gnutls_certificate_set_x509_crl_file(backend->cred,
522 SSL_SET_OPTION(primary.CRLfile),
523 GNUTLS_X509_FMT_PEM);
525 failf(data, "error reading crl file %s (%s)",
526 SSL_SET_OPTION(primary.CRLfile), gnutls_strerror(rc));
527 return CURLE_SSL_CRL_BADFILE;
530 infof(data, "found %d CRL in %s",
531 rc, SSL_SET_OPTION(primary.CRLfile));
534 /* Initialize TLS session as a client */
535 init_flags = GNUTLS_CLIENT;
537 #if defined(GNUTLS_FORCE_CLIENT_CERT)
538 init_flags |= GNUTLS_FORCE_CLIENT_CERT;
541 #if defined(GNUTLS_NO_TICKETS)
542 /* Disable TLS session tickets */
543 init_flags |= GNUTLS_NO_TICKETS;
546 rc = gnutls_init(&backend->session, init_flags);
547 if(rc != GNUTLS_E_SUCCESS) {
548 failf(data, "gnutls_init() failed: %d", rc);
549 return CURLE_SSL_CONNECT_ERROR;
552 /* convenient assign */
553 session = backend->session;
555 if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
557 (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
561 char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
562 if(!snihost || gnutls_server_name_set(session, GNUTLS_NAME_DNS, snihost,
564 failf(data, "Failed to set SNI");
565 return CURLE_SSL_CONNECT_ERROR;
569 /* Use default priorities */
570 rc = gnutls_set_default_priority(session);
571 if(rc != GNUTLS_E_SUCCESS)
572 return CURLE_SSL_CONNECT_ERROR;
574 /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
575 tls13support = gnutls_check_version("3.6.5");
577 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
578 * removed if a run-time error indicates that SRP is not supported by this
581 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2 ||
582 SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) {
583 failf(data, "GnuTLS does not support SSLv2 or SSLv3");
584 return CURLE_SSL_CONNECT_ERROR;
587 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_TLSv1_3) {
589 failf(data, "This GnuTLS installation does not support TLS 1.3");
590 return CURLE_SSL_CONNECT_ERROR;
594 /* At this point we know we have a supported TLS version, so set it */
595 result = set_ssl_version_min_max(data, &prioritylist, tls13support);
599 #ifdef USE_GNUTLS_SRP
600 /* Only add SRP to the cipher list if SRP is requested. Otherwise
601 * GnuTLS will disable TLS 1.3 support. */
602 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
603 size_t len = strlen(prioritylist);
605 char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
607 return CURLE_OUT_OF_MEMORY;
608 strcpy(prioritysrp, prioritylist);
609 strcpy(prioritysrp + len, ":" GNUTLS_SRP);
610 rc = gnutls_priority_set_direct(session, prioritysrp, &err);
613 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
614 infof(data, "This GnuTLS does not support SRP");
619 infof(data, "GnuTLS ciphers: %s", prioritylist);
620 rc = gnutls_priority_set_direct(session, prioritylist, &err);
621 #ifdef USE_GNUTLS_SRP
625 if(rc != GNUTLS_E_SUCCESS) {
626 failf(data, "Error %d setting GnuTLS cipher list starting with %s",
628 return CURLE_SSL_CONNECT_ERROR;
631 if(conn->bits.tls_enable_alpn) {
633 gnutls_datum_t protocols[2];
636 if(data->state.httpwant >= CURL_HTTP_VERSION_2
637 #ifndef CURL_DISABLE_PROXY
638 && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
641 protocols[cur].data = (unsigned char *)ALPN_H2;
642 protocols[cur].size = ALPN_H2_LENGTH;
644 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
648 protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
649 protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
651 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
653 if(gnutls_alpn_set_protocols(session, protocols, cur, 0)) {
654 failf(data, "failed setting ALPN");
655 return CURLE_SSL_CONNECT_ERROR;
659 if(SSL_SET_OPTION(primary.clientcert)) {
660 if(SSL_SET_OPTION(key_passwd)) {
661 const unsigned int supported_key_encryption_algorithms =
662 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
663 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
664 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
665 GNUTLS_PKCS_USE_PBES2_AES_256;
666 rc = gnutls_certificate_set_x509_key_file2(
668 SSL_SET_OPTION(primary.clientcert),
669 SSL_SET_OPTION(key) ?
670 SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
671 do_file_type(SSL_SET_OPTION(cert_type)),
672 SSL_SET_OPTION(key_passwd),
673 supported_key_encryption_algorithms);
674 if(rc != GNUTLS_E_SUCCESS) {
676 "error reading X.509 potentially-encrypted key file: %s",
677 gnutls_strerror(rc));
678 return CURLE_SSL_CONNECT_ERROR;
682 if(gnutls_certificate_set_x509_key_file(
684 SSL_SET_OPTION(primary.clientcert),
685 SSL_SET_OPTION(key) ?
686 SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
687 do_file_type(SSL_SET_OPTION(cert_type)) ) !=
689 failf(data, "error reading X.509 key or certificate file");
690 return CURLE_SSL_CONNECT_ERROR;
695 #ifdef USE_GNUTLS_SRP
696 /* put the credentials to the current session */
697 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
698 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
699 backend->srp_client_cred);
700 if(rc != GNUTLS_E_SUCCESS) {
701 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
702 return CURLE_SSL_CONNECT_ERROR;
708 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
710 if(rc != GNUTLS_E_SUCCESS) {
711 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
712 return CURLE_SSL_CONNECT_ERROR;
716 #ifndef CURL_DISABLE_PROXY
717 if(conn->proxy_ssl[sockindex].use) {
718 struct ssl_backend_data *proxy_backend;
719 proxy_backend = conn->proxy_ssl[sockindex].backend;
720 DEBUGASSERT(proxy_backend);
721 transport_ptr = proxy_backend->session;
722 gnutls_transport_push = gtls_push_ssl;
723 gnutls_transport_pull = gtls_pull_ssl;
728 /* file descriptor for the socket */
729 transport_ptr = &conn->sock[sockindex];
730 gnutls_transport_push = gtls_push;
731 gnutls_transport_pull = gtls_pull;
734 /* set the connection handle */
735 gnutls_transport_set_ptr(session, transport_ptr);
737 /* register callback functions to send and receive data. */
738 gnutls_transport_set_push_function(session, gnutls_transport_push);
739 gnutls_transport_set_pull_function(session, gnutls_transport_pull);
741 if(SSL_CONN_CONFIG(verifystatus)) {
742 rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
743 if(rc != GNUTLS_E_SUCCESS) {
744 failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
745 return CURLE_SSL_CONNECT_ERROR;
749 /* This might be a reconnect, so we check for a session ID in the cache
750 to speed up things */
751 if(SSL_SET_OPTION(primary.sessionid)) {
755 Curl_ssl_sessionid_lock(data);
756 if(!Curl_ssl_getsessionid(data, conn,
757 SSL_IS_PROXY() ? TRUE : FALSE,
758 &ssl_sessionid, &ssl_idsize, sockindex)) {
759 /* we got a session id, use it! */
760 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
762 /* Informational message */
763 infof(data, "SSL re-using session ID");
765 Curl_ssl_sessionid_unlock(data);
771 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
772 gnutls_x509_crt_t cert,
773 const char *pinnedpubkey)
776 size_t len1 = 0, len2 = 0;
777 unsigned char *buff1 = NULL;
779 gnutls_pubkey_t key = NULL;
781 /* Result is returned to caller */
782 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
784 /* if a path wasn't specified, don't pin */
794 /* Begin Gyrations to get the public key */
795 gnutls_pubkey_init(&key);
797 ret = gnutls_pubkey_import_x509(key, cert, 0);
801 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
802 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
805 buff1 = malloc(len1);
811 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
812 if(ret < 0 || len1 != len2)
817 /* The one good exit point */
818 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
822 gnutls_pubkey_deinit(key);
824 Curl_safefree(buff1);
829 static Curl_recv gtls_recv;
830 static Curl_send gtls_send;
833 Curl_gtls_verifyserver(struct Curl_easy *data,
834 struct connectdata *conn,
835 gnutls_session_t session,
838 unsigned int cert_list_size;
839 const gnutls_datum_t *chainp;
840 unsigned int verify_status = 0;
841 gnutls_x509_crt_t x509_cert, x509_issuer;
842 gnutls_datum_t issuerp;
843 gnutls_datum_t certfields;
844 char certname[65] = ""; /* limited to 64 chars by ASN.1 */
849 gnutls_datum_t proto;
850 CURLcode result = CURLE_OK;
851 #ifndef CURL_DISABLE_VERBOSE_STRINGS
854 gnutls_protocol_t version = gnutls_protocol_get_version(session);
856 const char * const hostname = SSL_HOST_NAME();
857 long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
859 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
860 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
861 gnutls_cipher_get(session),
862 gnutls_mac_get(session));
864 infof(data, "SSL connection using %s / %s",
865 gnutls_protocol_get_name(version), ptr);
867 /* This function will return the peer's raw certificate (chain) as sent by
868 the peer. These certificates are in raw format (DER encoded for
869 X.509). In case of a X.509 then a certificate list may be present. The
870 first certificate in the list is the peer's certificate, following the
871 issuer's certificate, then the issuer's issuer etc. */
873 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
875 if(SSL_CONN_CONFIG(verifypeer) ||
876 SSL_CONN_CONFIG(verifyhost) ||
877 SSL_CONN_CONFIG(issuercert)) {
878 #ifdef USE_GNUTLS_SRP
879 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
880 && SSL_SET_OPTION(primary.username)
881 && !SSL_CONN_CONFIG(verifypeer)
882 && gnutls_cipher_get(session)) {
883 /* no peer cert, but auth is ok if we have SRP user and cipher and no
888 failf(data, "failed to get server cert");
889 *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
890 return CURLE_PEER_FAILED_VERIFICATION;
891 #ifdef USE_GNUTLS_SRP
895 infof(data, " common name: WARNING couldn't obtain");
898 if(data->set.ssl.certinfo && chainp) {
901 result = Curl_ssl_init_certinfo(data, cert_list_size);
905 for(i = 0; i < cert_list_size; i++) {
906 const char *beg = (const char *) chainp[i].data;
907 const char *end = beg + chainp[i].size;
909 result = Curl_extract_certinfo(data, i, beg, end);
915 if(SSL_CONN_CONFIG(verifypeer)) {
916 /* This function will try to verify the peer's certificate and return its
917 status (trusted, invalid etc.). The value of status should be one or
918 more of the gnutls_certificate_status_t enumerated elements bitwise
919 or'd. To avoid denial of service attacks some default upper limits
920 regarding the certificate key size and chain size are set. To override
921 them use gnutls_certificate_set_verify_limits(). */
923 rc = gnutls_certificate_verify_peers2(session, &verify_status);
925 failf(data, "server cert verify failed: %d", rc);
926 *certverifyresult = rc;
927 return CURLE_SSL_CONNECT_ERROR;
930 *certverifyresult = verify_status;
932 /* verify_status is a bitmask of gnutls_certificate_status bits */
933 if(verify_status & GNUTLS_CERT_INVALID) {
934 if(SSL_CONN_CONFIG(verifypeer)) {
935 failf(data, "server certificate verification failed. CAfile: %s "
936 "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
938 SSL_SET_OPTION(primary.CRLfile) ?
939 SSL_SET_OPTION(primary.CRLfile) : "none");
940 return CURLE_PEER_FAILED_VERIFICATION;
943 infof(data, " server certificate verification FAILED");
946 infof(data, " server certificate verification OK");
949 infof(data, " server certificate verification SKIPPED");
951 if(SSL_CONN_CONFIG(verifystatus)) {
952 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
953 gnutls_datum_t status_request;
954 gnutls_ocsp_resp_t ocsp_resp;
956 gnutls_ocsp_cert_status_t status;
957 gnutls_x509_crl_reason_t reason;
959 rc = gnutls_ocsp_status_request_get(session, &status_request);
961 infof(data, " server certificate status verification FAILED");
963 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
964 failf(data, "No OCSP response received");
965 return CURLE_SSL_INVALIDCERTSTATUS;
969 failf(data, "Invalid OCSP response received");
970 return CURLE_SSL_INVALIDCERTSTATUS;
973 gnutls_ocsp_resp_init(&ocsp_resp);
975 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
977 failf(data, "Invalid OCSP response received");
978 return CURLE_SSL_INVALIDCERTSTATUS;
981 (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
982 &status, NULL, NULL, NULL, &reason);
985 case GNUTLS_OCSP_CERT_GOOD:
988 case GNUTLS_OCSP_CERT_REVOKED: {
989 const char *crl_reason;
993 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
994 crl_reason = "unspecified reason";
997 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
998 crl_reason = "private key compromised";
1001 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1002 crl_reason = "CA compromised";
1005 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1006 crl_reason = "affiliation has changed";
1009 case GNUTLS_X509_CRLREASON_SUPERSEDED:
1010 crl_reason = "certificate superseded";
1013 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1014 crl_reason = "operation has ceased";
1017 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1018 crl_reason = "certificate is on hold";
1021 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1022 crl_reason = "will be removed from delta CRL";
1025 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1026 crl_reason = "privilege withdrawn";
1029 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1030 crl_reason = "AA compromised";
1034 failf(data, "Server certificate was revoked: %s", crl_reason);
1039 case GNUTLS_OCSP_CERT_UNKNOWN:
1040 failf(data, "Server certificate status is unknown");
1044 gnutls_ocsp_resp_deinit(ocsp_resp);
1046 return CURLE_SSL_INVALIDCERTSTATUS;
1049 infof(data, " server certificate status verification OK");
1052 infof(data, " server certificate status verification SKIPPED");
1054 /* initialize an X.509 certificate structure. */
1055 gnutls_x509_crt_init(&x509_cert);
1058 /* convert the given DER or PEM encoded Certificate to the native
1059 gnutls_x509_crt_t format */
1060 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1062 if(SSL_CONN_CONFIG(issuercert)) {
1063 gnutls_x509_crt_init(&x509_issuer);
1064 issuerp = load_file(SSL_CONN_CONFIG(issuercert));
1065 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1066 rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1067 gnutls_x509_crt_deinit(x509_issuer);
1068 unload_file(issuerp);
1070 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1071 SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
1072 gnutls_x509_crt_deinit(x509_cert);
1073 return CURLE_SSL_ISSUER_ERROR;
1075 infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
1076 SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
1079 size = sizeof(certname);
1080 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1081 0, /* the first and only one */
1086 infof(data, "error fetching CN from cert:%s",
1087 gnutls_strerror(rc));
1090 /* This function will check if the given certificate's subject matches the
1091 given hostname. This is a basic implementation of the matching described
1092 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1093 alternative name PKIX extension. Returns non zero on success, and zero on
1095 rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
1096 #if GNUTLS_VERSION_NUMBER < 0x030306
1097 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1101 #define use_addr in6_addr
1103 #define use_addr in_addr
1105 unsigned char addrbuf[sizeof(struct use_addr)];
1108 if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
1111 else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
1116 unsigned char certaddr[sizeof(struct use_addr)];
1120 size_t certaddrlen = sizeof(certaddr);
1121 int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1122 &certaddrlen, NULL);
1123 /* If this happens, it wasn't an IP address. */
1124 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1128 if(ret != GNUTLS_SAN_IPADDRESS)
1130 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1139 if(SSL_CONN_CONFIG(verifyhost)) {
1140 failf(data, "SSL: certificate subject name (%s) does not match "
1141 "target host name '%s'", certname, SSL_HOST_DISPNAME());
1142 gnutls_x509_crt_deinit(x509_cert);
1143 return CURLE_PEER_FAILED_VERIFICATION;
1146 infof(data, " common name: %s (does not match '%s')",
1147 certname, SSL_HOST_DISPNAME());
1150 infof(data, " common name: %s (matched)", certname);
1152 /* Check for time-based validity */
1153 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1155 if(certclock == (time_t)-1) {
1156 if(SSL_CONN_CONFIG(verifypeer)) {
1157 failf(data, "server cert expiration date verify failed");
1158 *certverifyresult = GNUTLS_CERT_EXPIRED;
1159 gnutls_x509_crt_deinit(x509_cert);
1160 return CURLE_SSL_CONNECT_ERROR;
1163 infof(data, " server certificate expiration date verify FAILED");
1166 if(certclock < time(NULL)) {
1167 if(SSL_CONN_CONFIG(verifypeer)) {
1168 failf(data, "server certificate expiration date has passed.");
1169 *certverifyresult = GNUTLS_CERT_EXPIRED;
1170 gnutls_x509_crt_deinit(x509_cert);
1171 return CURLE_PEER_FAILED_VERIFICATION;
1174 infof(data, " server certificate expiration date FAILED");
1177 infof(data, " server certificate expiration date OK");
1180 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1182 if(certclock == (time_t)-1) {
1183 if(SSL_CONN_CONFIG(verifypeer)) {
1184 failf(data, "server cert activation date verify failed");
1185 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1186 gnutls_x509_crt_deinit(x509_cert);
1187 return CURLE_SSL_CONNECT_ERROR;
1190 infof(data, " server certificate activation date verify FAILED");
1193 if(certclock > time(NULL)) {
1194 if(SSL_CONN_CONFIG(verifypeer)) {
1195 failf(data, "server certificate not activated yet.");
1196 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1197 gnutls_x509_crt_deinit(x509_cert);
1198 return CURLE_PEER_FAILED_VERIFICATION;
1201 infof(data, " server certificate activation date FAILED");
1204 infof(data, " server certificate activation date OK");
1207 ptr = SSL_PINNED_PUB_KEY();
1209 result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
1210 if(result != CURLE_OK) {
1211 failf(data, "SSL: public key does not match pinned public key");
1212 gnutls_x509_crt_deinit(x509_cert);
1227 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1228 /* public key algorithm's parameters */
1229 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1230 infof(data, " certificate public key: %s",
1231 gnutls_pk_algorithm_get_name(algo));
1233 /* version of the X.509 certificate. */
1234 infof(data, " certificate version: #%d",
1235 gnutls_x509_crt_get_version(x509_cert));
1238 rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1240 infof(data, "Failed to get certificate name");
1242 infof(data, " subject: %s", certfields.data);
1244 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1245 showtime(data, "start date", certclock);
1247 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1248 showtime(data, "expire date", certclock);
1250 gnutls_free(certfields.data);
1253 rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1255 infof(data, "Failed to get certificate issuer");
1257 infof(data, " issuer: %s", certfields.data);
1259 gnutls_free(certfields.data);
1263 gnutls_x509_crt_deinit(x509_cert);
1265 if(conn->bits.tls_enable_alpn) {
1266 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1268 infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, proto.size,
1272 if(proto.size == ALPN_H2_LENGTH &&
1273 !memcmp(ALPN_H2, proto.data,
1275 conn->negnpn = CURL_HTTP_VERSION_2;
1279 if(proto.size == ALPN_HTTP_1_1_LENGTH &&
1280 !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
1281 conn->negnpn = CURL_HTTP_VERSION_1_1;
1285 infof(data, VTLS_INFOF_NO_ALPN);
1287 Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
1288 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
1291 conn->ssl[sockindex].state = ssl_connection_complete;
1293 if(SSL_SET_OPTION(primary.sessionid)) {
1294 /* we always unconditionally get the session id here, as even if we
1295 already got it from the cache and asked to use it in the connection, it
1296 might've been rejected and then a new one is in use now and we need to
1298 void *connect_sessionid;
1299 size_t connect_idsize = 0;
1301 /* get the session ID data size */
1302 gnutls_session_get_data(session, NULL, &connect_idsize);
1303 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1305 if(connect_sessionid) {
1308 void *ssl_sessionid;
1310 /* extract session ID to the allocated buffer */
1311 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1313 Curl_ssl_sessionid_lock(data);
1314 incache = !(Curl_ssl_getsessionid(data, conn,
1315 SSL_IS_PROXY() ? TRUE : FALSE,
1316 &ssl_sessionid, NULL, sockindex));
1318 /* there was one before in the cache, so instead of risking that the
1319 previous one was rejected, we just kill that and store the new */
1320 Curl_ssl_delsessionid(data, ssl_sessionid);
1323 /* store this session id */
1324 result = Curl_ssl_addsessionid(data, conn,
1325 SSL_IS_PROXY() ? TRUE : FALSE,
1326 connect_sessionid, connect_idsize,
1328 Curl_ssl_sessionid_unlock(data);
1330 free(connect_sessionid);
1332 result = CURLE_OUT_OF_MEMORY;
1336 result = CURLE_OUT_OF_MEMORY;
1344 * This function is called after the TCP connect has completed. Setup the TLS
1345 * layer and do all necessary magic.
1347 /* We use connssl->connecting_state to keep track of the connection status;
1348 there are three states: 'ssl_connect_1' (not started yet or complete),
1349 'ssl_connect_2_reading' (waiting for data from server), and
1350 'ssl_connect_2_writing' (waiting to be able to write).
1353 gtls_connect_common(struct Curl_easy *data,
1354 struct connectdata *conn,
1360 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1362 /* Initiate the connection, if not already done */
1363 if(ssl_connect_1 == connssl->connecting_state) {
1364 rc = gtls_connect_step1(data, conn, sockindex);
1369 rc = handshake(data, conn, sockindex, TRUE, nonblocking);
1371 /* handshake() sets its own error message with failf() */
1374 /* Finish connecting once the handshake is done */
1375 if(ssl_connect_1 == connssl->connecting_state) {
1376 struct ssl_backend_data *backend = connssl->backend;
1377 gnutls_session_t session;
1378 DEBUGASSERT(backend);
1379 session = backend->session;
1380 rc = Curl_gtls_verifyserver(data, conn, session, sockindex);
1383 conn->recv[sockindex] = gtls_recv;
1384 conn->send[sockindex] = gtls_send;
1387 *done = ssl_connect_1 == connssl->connecting_state;
1392 static CURLcode gtls_connect_nonblocking(struct Curl_easy *data,
1393 struct connectdata *conn,
1394 int sockindex, bool *done)
1396 return gtls_connect_common(data, conn, sockindex, TRUE, done);
1399 static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn,
1405 result = gtls_connect_common(data, conn, sockindex, FALSE, &done);
1414 static bool gtls_data_pending(const struct connectdata *conn,
1417 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
1419 struct ssl_backend_data *backend = connssl->backend;
1421 DEBUGASSERT(backend);
1423 if(backend->session &&
1424 0 != gnutls_record_check_pending(backend->session))
1427 #ifndef CURL_DISABLE_PROXY
1428 connssl = &conn->proxy_ssl[connindex];
1429 backend = connssl->backend;
1430 DEBUGASSERT(backend);
1431 if(backend->session &&
1432 0 != gnutls_record_check_pending(backend->session))
1439 static ssize_t gtls_send(struct Curl_easy *data,
1445 struct connectdata *conn = data->conn;
1446 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1447 struct ssl_backend_data *backend = connssl->backend;
1450 DEBUGASSERT(backend);
1451 rc = gnutls_record_send(backend->session, mem, len);
1454 *curlcode = (rc == GNUTLS_E_AGAIN)
1464 static void close_one(struct ssl_connect_data *connssl)
1466 struct ssl_backend_data *backend = connssl->backend;
1467 DEBUGASSERT(backend);
1469 if(backend->session) {
1471 /* Maybe the server has already sent a close notify alert.
1472 Read it to avoid an RST on the TCP connection. */
1473 (void)gnutls_record_recv(backend->session, buf, sizeof(buf));
1474 gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1475 gnutls_deinit(backend->session);
1476 backend->session = NULL;
1479 gnutls_certificate_free_credentials(backend->cred);
1480 backend->cred = NULL;
1482 #ifdef USE_GNUTLS_SRP
1483 if(backend->srp_client_cred) {
1484 gnutls_srp_free_client_credentials(backend->srp_client_cred);
1485 backend->srp_client_cred = NULL;
1490 static void gtls_close(struct Curl_easy *data, struct connectdata *conn,
1494 close_one(&conn->ssl[sockindex]);
1495 #ifndef CURL_DISABLE_PROXY
1496 close_one(&conn->proxy_ssl[sockindex]);
1501 * This function is called to shut down the SSL layer but keep the
1502 * socket open (CCC - Clear Command Channel)
1504 static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
1507 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1508 struct ssl_backend_data *backend = connssl->backend;
1511 DEBUGASSERT(backend);
1513 #ifndef CURL_DISABLE_FTP
1514 /* This has only been tested on the proftpd server, and the mod_tls code
1515 sends a close notify alert without waiting for a close notify alert in
1516 response. Thus we wait for a close notify alert from the server, but
1517 we do not send one. Let's hope other servers do the same... */
1519 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1520 gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1523 if(backend->session) {
1529 int what = SOCKET_READABLE(conn->sock[sockindex],
1530 SSL_SHUTDOWN_TIMEOUT);
1532 /* Something to read, let's do it and hope that it is the close
1533 notify alert from the server */
1534 result = gnutls_record_recv(backend->session,
1538 /* This is the expected response. There was no data but only
1539 the close notify alert */
1542 case GNUTLS_E_AGAIN:
1543 case GNUTLS_E_INTERRUPTED:
1544 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED");
1552 else if(0 == what) {
1554 failf(data, "SSL shutdown timeout");
1558 /* anything that gets here is fatally bad */
1559 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1564 gnutls_deinit(backend->session);
1566 gnutls_certificate_free_credentials(backend->cred);
1568 #ifdef USE_GNUTLS_SRP
1569 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
1570 && SSL_SET_OPTION(primary.username) != NULL)
1571 gnutls_srp_free_client_credentials(backend->srp_client_cred);
1574 backend->cred = NULL;
1575 backend->session = NULL;
1580 static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
1581 int num, /* socketindex */
1582 char *buf, /* store read data here */
1583 size_t buffersize, /* max amount to read */
1586 struct connectdata *conn = data->conn;
1587 struct ssl_connect_data *connssl = &conn->ssl[num];
1588 struct ssl_backend_data *backend = connssl->backend;
1591 DEBUGASSERT(backend);
1593 ret = gnutls_record_recv(backend->session, buf, buffersize);
1594 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1595 *curlcode = CURLE_AGAIN;
1599 if(ret == GNUTLS_E_REHANDSHAKE) {
1600 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1601 proper way" takes a whole lot of work. */
1602 CURLcode result = handshake(data, conn, num, FALSE, FALSE);
1604 /* handshake() writes error message on its own */
1607 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1612 failf(data, "GnuTLS recv error (%d): %s",
1614 (int)ret, gnutls_strerror((int)ret));
1615 *curlcode = CURLE_RECV_ERROR;
1622 static void gtls_session_free(void *ptr)
1627 static size_t gtls_version(char *buffer, size_t size)
1629 return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1632 /* data might be NULL! */
1633 static CURLcode gtls_random(struct Curl_easy *data,
1634 unsigned char *entropy, size_t length)
1638 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1639 return rc?CURLE_FAILED_INIT:CURLE_OK;
1642 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1644 unsigned char *sha256sum, /* output */
1647 struct sha256_ctx SHA256pw;
1648 sha256_init(&SHA256pw);
1649 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1650 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1654 static bool gtls_cert_status_request(void)
1659 static void *gtls_get_internals(struct ssl_connect_data *connssl,
1660 CURLINFO info UNUSED_PARAM)
1662 struct ssl_backend_data *backend = connssl->backend;
1664 DEBUGASSERT(backend);
1665 return backend->session;
1668 const struct Curl_ssl Curl_ssl_gnutls = {
1669 { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
1673 SSLSUPP_PINNEDPUBKEY |
1674 SSLSUPP_HTTPS_PROXY,
1676 sizeof(struct ssl_backend_data),
1678 gtls_init, /* init */
1679 gtls_cleanup, /* cleanup */
1680 gtls_version, /* version */
1681 Curl_none_check_cxn, /* check_cxn */
1682 gtls_shutdown, /* shutdown */
1683 gtls_data_pending, /* data_pending */
1684 gtls_random, /* random */
1685 gtls_cert_status_request, /* cert_status_request */
1686 gtls_connect, /* connect */
1687 gtls_connect_nonblocking, /* connect_nonblocking */
1688 Curl_ssl_getsock, /* getsock */
1689 gtls_get_internals, /* get_internals */
1690 gtls_close, /* close_one */
1691 Curl_none_close_all, /* close_all */
1692 gtls_session_free, /* session_free */
1693 Curl_none_set_engine, /* set_engine */
1694 Curl_none_set_engine_default, /* set_engine_default */
1695 Curl_none_engines_list, /* engines_list */
1696 Curl_none_false_start, /* false_start */
1697 gtls_sha256sum, /* sha256sum */
1698 NULL, /* associate_connection */
1699 NULL /* disassociate_connection */
1702 #endif /* USE_GNUTLS */