1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, 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.haxx.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>
39 #ifdef USE_GNUTLS_NETTLE
40 #include <gnutls/crypto.h>
41 #include <nettle/md5.h>
42 #include <nettle/sha2.h>
49 #include "inet_pton.h"
52 #include "parsedate.h"
53 #include "connect.h" /* for the connect timeout */
58 #include "curl_printf.h"
59 #include "curl_memory.h"
60 /* The last #include file should be: */
64 Some hackish cast macros based on:
65 https://developer.gnome.org/glib/unstable/glib-Type-Conversion-Macros.html
67 #ifndef GNUTLS_POINTER_TO_INT_CAST
68 #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
70 #ifndef GNUTLS_INT_TO_POINTER_CAST
71 #define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
74 /* Enable GnuTLS debugging by defining GTLSDEBUG */
75 /*#define GTLSDEBUG */
78 static void tls_log_func(int level
, const char *str
)
80 fprintf(stderr
, "|<%d>| %s", level
, str
);
83 static bool gtls_inited
= FALSE
;
85 #if defined(GNUTLS_VERSION_NUMBER)
86 # if (GNUTLS_VERSION_NUMBER >= 0x020c00)
87 # undef gnutls_transport_set_lowat
88 # define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
89 # define USE_GNUTLS_PRIORITY_SET_DIRECT 1
91 # if (GNUTLS_VERSION_NUMBER >= 0x020c03)
92 # define GNUTLS_MAPS_WINSOCK_ERRORS 1
95 # if (GNUTLS_VERSION_NUMBER >= 0x030200)
99 # if (GNUTLS_VERSION_NUMBER >= 0x03020d)
103 # if (GNUTLS_VERSION_NUMBER >= 0x030306)
109 # include <gnutls/ocsp.h>
113 * Custom push and pull callback functions used by GNU TLS to read and write
114 * to the socket. These functions are simple wrappers to send() and recv()
115 * (although here using the sread/swrite macros as defined by
116 * curl_setup_once.h).
117 * We use custom functions rather than the GNU TLS defaults because it allows
118 * us to get specific about the fourth "flags" argument, and to use arbitrary
119 * private data with gnutls_transport_set_ptr if we wish.
121 * When these custom push and pull callbacks fail, GNU TLS checks its own
122 * session-specific error variable, and when not set also its own global
123 * errno variable, in order to take appropriate action. GNU TLS does not
124 * require that the transport is actually a socket. This implies that for
125 * Windows builds these callbacks should ideally set the session-specific
126 * error variable using function gnutls_transport_set_errno or as a last
127 * resort global errno variable using gnutls_transport_set_global_errno,
128 * with a transport agnostic error value. This implies that some winsock
129 * error translation must take place in these callbacks.
131 * Paragraph above applies to GNU TLS versions older than 2.12.3, since
132 * this version GNU TLS does its own internal winsock error translation
133 * using system_errno() function.
136 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
137 # define gtls_EINTR 4
139 # define gtls_EAGAIN 11
140 static int gtls_mapped_sockerrno(void)
154 static ssize_t
Curl_gtls_push(void *s
, const void *buf
, size_t len
)
156 ssize_t ret
= swrite(GNUTLS_POINTER_TO_INT_CAST(s
), buf
, len
);
157 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
159 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
164 static ssize_t
Curl_gtls_pull(void *s
, void *buf
, size_t len
)
166 ssize_t ret
= sread(GNUTLS_POINTER_TO_INT_CAST(s
), buf
, len
);
167 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
169 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
176 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
177 * are not thread-safe and thus this function itself is not thread-safe and
178 * must only be called from within curl_global_init() to keep the thread
179 * situation under control!
181 int Curl_gtls_init(void)
185 ret
= gnutls_global_init()?0:1;
187 gnutls_global_set_log_function(tls_log_func
);
188 gnutls_global_set_log_level(2);
195 int Curl_gtls_cleanup(void)
198 gnutls_global_deinit();
204 static void showtime(struct SessionHandle
*data
,
209 const struct tm
*tm
= &buffer
;
210 CURLcode result
= Curl_gmtime(stamp
, &buffer
);
214 snprintf(data
->state
.buffer
,
216 "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
218 Curl_wkday
[tm
->tm_wday
?tm
->tm_wday
-1:6],
220 Curl_month
[tm
->tm_mon
],
225 infof(data
, "%s\n", data
->state
.buffer
);
228 static gnutls_datum_t
load_file (const char *file
)
231 gnutls_datum_t loaded_file
= { NULL
, 0 };
235 if(!(f
= fopen(file
, "rb")))
237 if(fseek(f
, 0, SEEK_END
) != 0
238 || (filelen
= ftell(f
)) < 0
239 || fseek(f
, 0, SEEK_SET
) != 0
240 || !(ptr
= malloc((size_t)filelen
)))
242 if(fread(ptr
, 1, (size_t)filelen
, f
) < (size_t)filelen
) {
247 loaded_file
.data
= ptr
;
248 loaded_file
.size
= (unsigned int)filelen
;
254 static void unload_file(gnutls_datum_t data
) {
259 /* this function does a SSL/TLS (re-)handshake */
260 static CURLcode
handshake(struct connectdata
*conn
,
265 struct SessionHandle
*data
= conn
->data
;
266 struct ssl_connect_data
*connssl
= &conn
->ssl
[sockindex
];
267 gnutls_session_t session
= conn
->ssl
[sockindex
].session
;
268 curl_socket_t sockfd
= conn
->sock
[sockindex
];
274 /* check allowed time left */
275 timeout_ms
= Curl_timeleft(data
, NULL
, duringconnect
);
278 /* no need to continue if time already is up */
279 failf(data
, "SSL connection timeout");
280 return CURLE_OPERATION_TIMEDOUT
;
283 /* if ssl is expecting something, check if it's available. */
284 if(connssl
->connecting_state
== ssl_connect_2_reading
285 || connssl
->connecting_state
== ssl_connect_2_writing
) {
287 curl_socket_t writefd
= ssl_connect_2_writing
==
288 connssl
->connecting_state
?sockfd
:CURL_SOCKET_BAD
;
289 curl_socket_t readfd
= ssl_connect_2_reading
==
290 connssl
->connecting_state
?sockfd
:CURL_SOCKET_BAD
;
292 what
= Curl_socket_ready(readfd
, writefd
,
294 timeout_ms
?timeout_ms
:1000);
297 failf(data
, "select/poll on SSL socket, errno: %d", SOCKERRNO
);
298 return CURLE_SSL_CONNECT_ERROR
;
303 else if(timeout_ms
) {
305 failf(data
, "SSL connection timeout at %ld", timeout_ms
);
306 return CURLE_OPERATION_TIMEDOUT
;
309 /* socket is readable or writable */
312 rc
= gnutls_handshake(session
);
314 if((rc
== GNUTLS_E_AGAIN
) || (rc
== GNUTLS_E_INTERRUPTED
)) {
315 connssl
->connecting_state
=
316 gnutls_record_get_direction(session
)?
317 ssl_connect_2_writing
:ssl_connect_2_reading
;
320 else if((rc
< 0) && !gnutls_error_is_fatal(rc
)) {
321 const char *strerr
= NULL
;
323 if(rc
== GNUTLS_E_WARNING_ALERT_RECEIVED
) {
324 int alert
= gnutls_alert_get(session
);
325 strerr
= gnutls_alert_get_name(alert
);
329 strerr
= gnutls_strerror(rc
);
331 infof(data
, "gnutls_handshake() warning: %s\n", strerr
);
335 const char *strerr
= NULL
;
337 if(rc
== GNUTLS_E_FATAL_ALERT_RECEIVED
) {
338 int alert
= gnutls_alert_get(session
);
339 strerr
= gnutls_alert_get_name(alert
);
343 strerr
= gnutls_strerror(rc
);
345 failf(data
, "gnutls_handshake() failed: %s", strerr
);
346 return CURLE_SSL_CONNECT_ERROR
;
349 /* Reset our connect state machine */
350 connssl
->connecting_state
= ssl_connect_1
;
355 static gnutls_x509_crt_fmt_t
do_file_type(const char *type
)
357 if(!type
|| !type
[0])
358 return GNUTLS_X509_FMT_PEM
;
359 if(Curl_raw_equal(type
, "PEM"))
360 return GNUTLS_X509_FMT_PEM
;
361 if(Curl_raw_equal(type
, "DER"))
362 return GNUTLS_X509_FMT_DER
;
367 gtls_connect_step1(struct connectdata
*conn
,
370 struct SessionHandle
*data
= conn
->data
;
371 gnutls_session_t session
;
375 bool sni
= TRUE
; /* default is SNI enabled */
377 struct in6_addr addr
;
381 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
382 static const int cipher_priority
[] = {
383 /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
384 but this code path is only ever used for ver. < 2.12.0.
385 GNUTLS_CIPHER_AES_128_GCM,
386 GNUTLS_CIPHER_AES_256_GCM,
388 GNUTLS_CIPHER_AES_128_CBC
,
389 GNUTLS_CIPHER_AES_256_CBC
,
390 GNUTLS_CIPHER_CAMELLIA_128_CBC
,
391 GNUTLS_CIPHER_CAMELLIA_256_CBC
,
392 GNUTLS_CIPHER_3DES_CBC
,
394 static const int cert_type_priority
[] = { GNUTLS_CRT_X509
, 0 };
395 static int protocol_priority
[] = { 0, 0, 0, 0 };
397 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
398 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
399 requested in the priority string, so treat it specially
401 #define GNUTLS_SRP "+SRP"
402 const char* prioritylist
;
403 const char *err
= NULL
;
406 if(conn
->ssl
[sockindex
].state
== ssl_connection_complete
)
407 /* to make us tolerant against being called more than once for the
414 /* GnuTLS only supports SSLv3 and TLSv1 */
415 if(data
->set
.ssl
.version
== CURL_SSLVERSION_SSLv2
) {
416 failf(data
, "GnuTLS does not support SSLv2");
417 return CURLE_SSL_CONNECT_ERROR
;
419 else if(data
->set
.ssl
.version
== CURL_SSLVERSION_SSLv3
)
420 sni
= FALSE
; /* SSLv3 has no SNI */
422 /* allocate a cred struct */
423 rc
= gnutls_certificate_allocate_credentials(&conn
->ssl
[sockindex
].cred
);
424 if(rc
!= GNUTLS_E_SUCCESS
) {
425 failf(data
, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc
));
426 return CURLE_SSL_CONNECT_ERROR
;
430 if(data
->set
.ssl
.authtype
== CURL_TLSAUTH_SRP
) {
431 infof(data
, "Using TLS-SRP username: %s\n", data
->set
.ssl
.username
);
433 rc
= gnutls_srp_allocate_client_credentials(
434 &conn
->ssl
[sockindex
].srp_client_cred
);
435 if(rc
!= GNUTLS_E_SUCCESS
) {
436 failf(data
, "gnutls_srp_allocate_client_cred() failed: %s",
437 gnutls_strerror(rc
));
438 return CURLE_OUT_OF_MEMORY
;
441 rc
= gnutls_srp_set_client_credentials(conn
->ssl
[sockindex
].
443 data
->set
.ssl
.username
,
444 data
->set
.ssl
.password
);
445 if(rc
!= GNUTLS_E_SUCCESS
) {
446 failf(data
, "gnutls_srp_set_client_cred() failed: %s",
447 gnutls_strerror(rc
));
448 return CURLE_BAD_FUNCTION_ARGUMENT
;
453 if(data
->set
.ssl
.CAfile
) {
454 /* set the trusted CA cert bundle file */
455 gnutls_certificate_set_verify_flags(conn
->ssl
[sockindex
].cred
,
456 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT
);
458 rc
= gnutls_certificate_set_x509_trust_file(conn
->ssl
[sockindex
].cred
,
459 data
->set
.ssl
.CAfile
,
460 GNUTLS_X509_FMT_PEM
);
462 infof(data
, "error reading ca cert file %s (%s)\n",
463 data
->set
.ssl
.CAfile
, gnutls_strerror(rc
));
464 if(data
->set
.ssl
.verifypeer
)
465 return CURLE_SSL_CACERT_BADFILE
;
468 infof(data
, "found %d certificates in %s\n",
469 rc
, data
->set
.ssl
.CAfile
);
473 if(data
->set
.ssl
.CApath
) {
474 /* set the trusted CA cert directory */
475 rc
= gnutls_certificate_set_x509_trust_dir(conn
->ssl
[sockindex
].cred
,
476 data
->set
.ssl
.CApath
,
477 GNUTLS_X509_FMT_PEM
);
479 infof(data
, "error reading ca cert file %s (%s)\n",
480 data
->set
.ssl
.CAfile
, gnutls_strerror(rc
));
481 if(data
->set
.ssl
.verifypeer
)
482 return CURLE_SSL_CACERT_BADFILE
;
485 infof(data
, "found %d certificates in %s\n",
486 rc
, data
->set
.ssl
.CApath
);
490 #ifdef CURL_CA_FALLBACK
491 /* use system ca certificate store as fallback */
492 if(data
->set
.ssl
.verifypeer
&&
493 !(data
->set
.ssl
.CAfile
|| data
->set
.ssl
.CApath
)) {
494 gnutls_certificate_set_x509_system_trust(conn
->ssl
[sockindex
].cred
);
498 if(data
->set
.ssl
.CRLfile
) {
499 /* set the CRL list file */
500 rc
= gnutls_certificate_set_x509_crl_file(conn
->ssl
[sockindex
].cred
,
501 data
->set
.ssl
.CRLfile
,
502 GNUTLS_X509_FMT_PEM
);
504 failf(data
, "error reading crl file %s (%s)",
505 data
->set
.ssl
.CRLfile
, gnutls_strerror(rc
));
506 return CURLE_SSL_CRL_BADFILE
;
509 infof(data
, "found %d CRL in %s\n",
510 rc
, data
->set
.ssl
.CRLfile
);
513 /* Initialize TLS session as a client */
514 rc
= gnutls_init(&conn
->ssl
[sockindex
].session
, GNUTLS_CLIENT
);
515 if(rc
!= GNUTLS_E_SUCCESS
) {
516 failf(data
, "gnutls_init() failed: %d", rc
);
517 return CURLE_SSL_CONNECT_ERROR
;
520 /* convenient assign */
521 session
= conn
->ssl
[sockindex
].session
;
523 if((0 == Curl_inet_pton(AF_INET
, conn
->host
.name
, &addr
)) &&
525 (0 == Curl_inet_pton(AF_INET6
, conn
->host
.name
, &addr
)) &&
528 (gnutls_server_name_set(session
, GNUTLS_NAME_DNS
, conn
->host
.name
,
529 strlen(conn
->host
.name
)) < 0))
530 infof(data
, "WARNING: failed to configure server name indication (SNI) "
533 /* Use default priorities */
534 rc
= gnutls_set_default_priority(session
);
535 if(rc
!= GNUTLS_E_SUCCESS
)
536 return CURLE_SSL_CONNECT_ERROR
;
538 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
539 rc
= gnutls_cipher_set_priority(session
, cipher_priority
);
540 if(rc
!= GNUTLS_E_SUCCESS
)
541 return CURLE_SSL_CONNECT_ERROR
;
543 /* Sets the priority on the certificate types supported by gnutls. Priority
544 is higher for types specified before others. After specifying the types
545 you want, you must append a 0. */
546 rc
= gnutls_certificate_type_set_priority(session
, cert_type_priority
);
547 if(rc
!= GNUTLS_E_SUCCESS
)
548 return CURLE_SSL_CONNECT_ERROR
;
550 if(data
->set
.ssl
.cipher_list
!= NULL
) {
551 failf(data
, "can't pass a custom cipher list to older GnuTLS"
553 return CURLE_SSL_CONNECT_ERROR
;
556 switch (data
->set
.ssl
.version
) {
557 case CURL_SSLVERSION_SSLv3
:
558 protocol_priority
[0] = GNUTLS_SSL3
;
560 case CURL_SSLVERSION_DEFAULT
:
561 case CURL_SSLVERSION_TLSv1
:
562 protocol_priority
[0] = GNUTLS_TLS1_0
;
563 protocol_priority
[1] = GNUTLS_TLS1_1
;
564 protocol_priority
[2] = GNUTLS_TLS1_2
;
566 case CURL_SSLVERSION_TLSv1_0
:
567 protocol_priority
[0] = GNUTLS_TLS1_0
;
569 case CURL_SSLVERSION_TLSv1_1
:
570 protocol_priority
[0] = GNUTLS_TLS1_1
;
572 case CURL_SSLVERSION_TLSv1_2
:
573 protocol_priority
[0] = GNUTLS_TLS1_2
;
575 case CURL_SSLVERSION_SSLv2
:
577 failf(data
, "GnuTLS does not support SSLv2");
578 return CURLE_SSL_CONNECT_ERROR
;
581 rc
= gnutls_protocol_set_priority(session
, protocol_priority
);
582 if(rc
!= GNUTLS_E_SUCCESS
) {
583 failf(data
, "Did you pass a valid GnuTLS cipher list?");
584 return CURLE_SSL_CONNECT_ERROR
;
588 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
589 * removed if a run-time error indicates that SRP is not supported by this
591 switch (data
->set
.ssl
.version
) {
592 case CURL_SSLVERSION_SSLv3
:
593 prioritylist
= GNUTLS_CIPHERS
":-VERS-TLS-ALL:+VERS-SSL3.0";
596 case CURL_SSLVERSION_DEFAULT
:
597 case CURL_SSLVERSION_TLSv1
:
598 prioritylist
= GNUTLS_CIPHERS
":-VERS-SSL3.0:" GNUTLS_SRP
;
600 case CURL_SSLVERSION_TLSv1_0
:
601 prioritylist
= GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:"
602 "+VERS-TLS1.0:" GNUTLS_SRP
;
604 case CURL_SSLVERSION_TLSv1_1
:
605 prioritylist
= GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:"
606 "+VERS-TLS1.1:" GNUTLS_SRP
;
608 case CURL_SSLVERSION_TLSv1_2
:
609 prioritylist
= GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:"
610 "+VERS-TLS1.2:" GNUTLS_SRP
;
612 case CURL_SSLVERSION_SSLv2
:
614 failf(data
, "GnuTLS does not support SSLv2");
615 return CURLE_SSL_CONNECT_ERROR
;
618 rc
= gnutls_priority_set_direct(session
, prioritylist
, &err
);
619 if((rc
== GNUTLS_E_INVALID_REQUEST
) && err
) {
620 if(!strcmp(err
, GNUTLS_SRP
)) {
621 /* This GnuTLS was probably compiled without support for SRP.
622 * Note that fact and try again without it. */
623 int validprioritylen
= curlx_uztosi(err
- prioritylist
);
624 char *prioritycopy
= strdup(prioritylist
);
626 return CURLE_OUT_OF_MEMORY
;
628 infof(data
, "This GnuTLS does not support SRP\n");
630 /* Remove the :+SRP */
631 prioritycopy
[validprioritylen
- 1] = 0;
632 rc
= gnutls_priority_set_direct(session
, prioritycopy
, &err
);
636 if(rc
!= GNUTLS_E_SUCCESS
) {
637 failf(data
, "Error %d setting GnuTLS cipher list starting with %s",
639 return CURLE_SSL_CONNECT_ERROR
;
644 if(conn
->bits
.tls_enable_alpn
) {
646 gnutls_datum_t protocols
[2];
649 if(data
->set
.httpversion
>= CURL_HTTP_VERSION_2
) {
650 protocols
[cur
].data
= (unsigned char *)NGHTTP2_PROTO_VERSION_ID
;
651 protocols
[cur
].size
= NGHTTP2_PROTO_VERSION_ID_LEN
;
653 infof(data
, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID
);
657 protocols
[cur
].data
= (unsigned char *)ALPN_HTTP_1_1
;
658 protocols
[cur
].size
= ALPN_HTTP_1_1_LENGTH
;
660 infof(data
, "ALPN, offering %s\n", ALPN_HTTP_1_1
);
662 gnutls_alpn_set_protocols(session
, protocols
, cur
, 0);
666 if(data
->set
.str
[STRING_CERT
]) {
667 if(data
->set
.str
[STRING_KEY_PASSWD
]) {
668 #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
669 const unsigned int supported_key_encryption_algorithms
=
670 GNUTLS_PKCS_USE_PKCS12_3DES
| GNUTLS_PKCS_USE_PKCS12_ARCFOUR
|
671 GNUTLS_PKCS_USE_PKCS12_RC2_40
| GNUTLS_PKCS_USE_PBES2_3DES
|
672 GNUTLS_PKCS_USE_PBES2_AES_128
| GNUTLS_PKCS_USE_PBES2_AES_192
|
673 GNUTLS_PKCS_USE_PBES2_AES_256
;
674 rc
= gnutls_certificate_set_x509_key_file2(
675 conn
->ssl
[sockindex
].cred
,
676 data
->set
.str
[STRING_CERT
],
677 data
->set
.str
[STRING_KEY
] ?
678 data
->set
.str
[STRING_KEY
] : data
->set
.str
[STRING_CERT
],
679 do_file_type(data
->set
.str
[STRING_CERT_TYPE
]),
680 data
->set
.str
[STRING_KEY_PASSWD
],
681 supported_key_encryption_algorithms
);
682 if(rc
!= GNUTLS_E_SUCCESS
) {
684 "error reading X.509 potentially-encrypted key file: %s",
685 gnutls_strerror(rc
));
686 return CURLE_SSL_CONNECT_ERROR
;
689 failf(data
, "gnutls lacks support for encrypted key files");
690 return CURLE_SSL_CONNECT_ERROR
;
694 rc
= gnutls_certificate_set_x509_key_file(
695 conn
->ssl
[sockindex
].cred
,
696 data
->set
.str
[STRING_CERT
],
697 data
->set
.str
[STRING_KEY
] ?
698 data
->set
.str
[STRING_KEY
] : data
->set
.str
[STRING_CERT
],
699 do_file_type(data
->set
.str
[STRING_CERT_TYPE
]) );
700 if(rc
!= GNUTLS_E_SUCCESS
) {
701 failf(data
, "error reading X.509 key or certificate file: %s",
702 gnutls_strerror(rc
));
703 return CURLE_SSL_CONNECT_ERROR
;
709 /* put the credentials to the current session */
710 if(data
->set
.ssl
.authtype
== CURL_TLSAUTH_SRP
) {
711 rc
= gnutls_credentials_set(session
, GNUTLS_CRD_SRP
,
712 conn
->ssl
[sockindex
].srp_client_cred
);
713 if(rc
!= GNUTLS_E_SUCCESS
) {
714 failf(data
, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc
));
715 return CURLE_SSL_CONNECT_ERROR
;
721 rc
= gnutls_credentials_set(session
, GNUTLS_CRD_CERTIFICATE
,
722 conn
->ssl
[sockindex
].cred
);
723 if(rc
!= GNUTLS_E_SUCCESS
) {
724 failf(data
, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc
));
725 return CURLE_SSL_CONNECT_ERROR
;
729 /* set the connection handle (file descriptor for the socket) */
730 gnutls_transport_set_ptr(session
,
731 GNUTLS_INT_TO_POINTER_CAST(conn
->sock
[sockindex
]));
733 /* register callback functions to send and receive data. */
734 gnutls_transport_set_push_function(session
, Curl_gtls_push
);
735 gnutls_transport_set_pull_function(session
, Curl_gtls_pull
);
737 /* lowat must be set to zero when using custom push and pull functions. */
738 gnutls_transport_set_lowat(session
, 0);
741 if(data
->set
.ssl
.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
;
750 /* This might be a reconnect, so we check for a session ID in the cache
751 to speed up things */
753 if(!Curl_ssl_getsessionid(conn
, &ssl_sessionid
, &ssl_idsize
)) {
754 /* we got a session id, use it! */
755 gnutls_session_set_data(session
, ssl_sessionid
, ssl_idsize
);
757 /* Informational message */
758 infof (data
, "SSL re-using session ID\n");
764 static CURLcode
pkp_pin_peer_pubkey(struct SessionHandle
*data
,
765 gnutls_x509_crt_t cert
,
766 const char *pinnedpubkey
)
769 size_t len1
= 0, len2
= 0;
770 unsigned char *buff1
= NULL
;
772 gnutls_pubkey_t key
= NULL
;
774 /* Result is returned to caller */
776 CURLcode result
= CURLE_SSL_PINNEDPUBKEYNOTMATCH
;
778 /* if a path wasn't specified, don't pin */
779 if(NULL
== pinnedpubkey
)
786 /* Begin Gyrations to get the public key */
787 gnutls_pubkey_init(&key
);
789 ret
= gnutls_pubkey_import_x509(key
, cert
, 0);
793 ret
= gnutls_pubkey_export(key
, GNUTLS_X509_FMT_DER
, NULL
, &len1
);
794 if(ret
!= GNUTLS_E_SHORT_MEMORY_BUFFER
|| len1
== 0)
797 buff1
= malloc(len1
);
803 ret
= gnutls_pubkey_export(key
, GNUTLS_X509_FMT_DER
, buff1
, &len2
);
804 if(ret
< 0 || len1
!= len2
)
809 /* The one good exit point */
810 result
= Curl_pin_peer_pubkey(data
, pinnedpubkey
, buff1
, len1
);
814 gnutls_pubkey_deinit(key
);
816 Curl_safefree(buff1
);
821 static Curl_recv gtls_recv
;
822 static Curl_send gtls_send
;
825 gtls_connect_step3(struct connectdata
*conn
,
828 unsigned int cert_list_size
;
829 const gnutls_datum_t
*chainp
;
830 unsigned int verify_status
= 0;
831 gnutls_x509_crt_t x509_cert
, x509_issuer
;
832 gnutls_datum_t issuerp
;
833 char certbuf
[256] = ""; /* big enough? */
839 struct SessionHandle
*data
= conn
->data
;
840 gnutls_session_t session
= conn
->ssl
[sockindex
].session
;
845 gnutls_datum_t proto
;
847 CURLcode result
= CURLE_OK
;
849 gnutls_protocol_t version
= gnutls_protocol_get_version(session
);
851 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
852 ptr
= gnutls_cipher_suite_get_name(gnutls_kx_get(session
),
853 gnutls_cipher_get(session
),
854 gnutls_mac_get(session
));
856 infof(data
, "SSL connection using %s / %s\n",
857 gnutls_protocol_get_name(version
), ptr
);
859 /* This function will return the peer's raw certificate (chain) as sent by
860 the peer. These certificates are in raw format (DER encoded for
861 X.509). In case of a X.509 then a certificate list may be present. The
862 first certificate in the list is the peer's certificate, following the
863 issuer's certificate, then the issuer's issuer etc. */
865 chainp
= gnutls_certificate_get_peers(session
, &cert_list_size
);
867 if(data
->set
.ssl
.verifypeer
||
868 data
->set
.ssl
.verifyhost
||
869 data
->set
.ssl
.issuercert
) {
871 if(data
->set
.ssl
.authtype
== CURL_TLSAUTH_SRP
872 && data
->set
.ssl
.username
!= NULL
873 && !data
->set
.ssl
.verifypeer
874 && gnutls_cipher_get(session
)) {
875 /* no peer cert, but auth is ok if we have SRP user and cipher and no
880 failf(data
, "failed to get server cert");
881 return CURLE_PEER_FAILED_VERIFICATION
;
886 infof(data
, "\t common name: WARNING couldn't obtain\n");
889 if(data
->set
.ssl
.certinfo
&& chainp
) {
892 result
= Curl_ssl_init_certinfo(data
, cert_list_size
);
896 for(i
= 0; i
< cert_list_size
; i
++) {
897 const char *beg
= (const char *) chainp
[i
].data
;
898 const char *end
= beg
+ chainp
[i
].size
;
900 result
= Curl_extract_certinfo(conn
, i
, beg
, end
);
906 if(data
->set
.ssl
.verifypeer
) {
907 /* This function will try to verify the peer's certificate and return its
908 status (trusted, invalid etc.). The value of status should be one or
909 more of the gnutls_certificate_status_t enumerated elements bitwise
910 or'd. To avoid denial of service attacks some default upper limits
911 regarding the certificate key size and chain size are set. To override
912 them use gnutls_certificate_set_verify_limits(). */
914 rc
= gnutls_certificate_verify_peers2(session
, &verify_status
);
916 failf(data
, "server cert verify failed: %d", rc
);
917 return CURLE_SSL_CONNECT_ERROR
;
920 /* verify_status is a bitmask of gnutls_certificate_status bits */
921 if(verify_status
& GNUTLS_CERT_INVALID
) {
922 if(data
->set
.ssl
.verifypeer
) {
923 failf(data
, "server certificate verification failed. CAfile: %s "
924 "CRLfile: %s", data
->set
.ssl
.CAfile
?data
->set
.ssl
.CAfile
:"none",
925 data
->set
.ssl
.CRLfile
?data
->set
.ssl
.CRLfile
:"none");
926 return CURLE_SSL_CACERT
;
929 infof(data
, "\t server certificate verification FAILED\n");
932 infof(data
, "\t server certificate verification OK\n");
935 infof(data
, "\t server certificate verification SKIPPED\n");
938 if(data
->set
.ssl
.verifystatus
) {
939 if(gnutls_ocsp_status_request_is_checked(session
, 0) == 0) {
940 gnutls_datum_t status_request
;
941 gnutls_ocsp_resp_t ocsp_resp
;
943 gnutls_ocsp_cert_status_t status
;
944 gnutls_x509_crl_reason_t reason
;
946 rc
= gnutls_ocsp_status_request_get(session
, &status_request
);
948 infof(data
, "\t server certificate status verification FAILED\n");
950 if(rc
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
) {
951 failf(data
, "No OCSP response received");
952 return CURLE_SSL_INVALIDCERTSTATUS
;
956 failf(data
, "Invalid OCSP response received");
957 return CURLE_SSL_INVALIDCERTSTATUS
;
960 gnutls_ocsp_resp_init(&ocsp_resp
);
962 rc
= gnutls_ocsp_resp_import(ocsp_resp
, &status_request
);
964 failf(data
, "Invalid OCSP response received");
965 return CURLE_SSL_INVALIDCERTSTATUS
;
968 rc
= gnutls_ocsp_resp_get_single(ocsp_resp
, 0, NULL
, NULL
, NULL
, NULL
,
969 &status
, NULL
, NULL
, NULL
, &reason
);
972 case GNUTLS_OCSP_CERT_GOOD
:
975 case GNUTLS_OCSP_CERT_REVOKED
: {
976 const char *crl_reason
;
980 case GNUTLS_X509_CRLREASON_UNSPECIFIED
:
981 crl_reason
= "unspecified reason";
984 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE
:
985 crl_reason
= "private key compromised";
988 case GNUTLS_X509_CRLREASON_CACOMPROMISE
:
989 crl_reason
= "CA compromised";
992 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED
:
993 crl_reason
= "affiliation has changed";
996 case GNUTLS_X509_CRLREASON_SUPERSEDED
:
997 crl_reason
= "certificate superseded";
1000 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION
:
1001 crl_reason
= "operation has ceased";
1004 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD
:
1005 crl_reason
= "certificate is on hold";
1008 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL
:
1009 crl_reason
= "will be removed from delta CRL";
1012 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN
:
1013 crl_reason
= "privilege withdrawn";
1016 case GNUTLS_X509_CRLREASON_AACOMPROMISE
:
1017 crl_reason
= "AA compromised";
1021 failf(data
, "Server certificate was revoked: %s", crl_reason
);
1026 case GNUTLS_OCSP_CERT_UNKNOWN
:
1027 failf(data
, "Server certificate status is unknown");
1031 gnutls_ocsp_resp_deinit(ocsp_resp
);
1033 return CURLE_SSL_INVALIDCERTSTATUS
;
1036 infof(data
, "\t server certificate status verification OK\n");
1039 infof(data
, "\t server certificate status verification SKIPPED\n");
1042 /* initialize an X.509 certificate structure. */
1043 gnutls_x509_crt_init(&x509_cert
);
1046 /* convert the given DER or PEM encoded Certificate to the native
1047 gnutls_x509_crt_t format */
1048 gnutls_x509_crt_import(x509_cert
, chainp
, GNUTLS_X509_FMT_DER
);
1050 if(data
->set
.ssl
.issuercert
) {
1051 gnutls_x509_crt_init(&x509_issuer
);
1052 issuerp
= load_file(data
->set
.ssl
.issuercert
);
1053 gnutls_x509_crt_import(x509_issuer
, &issuerp
, GNUTLS_X509_FMT_PEM
);
1054 rc
= gnutls_x509_crt_check_issuer(x509_cert
, x509_issuer
);
1055 gnutls_x509_crt_deinit(x509_issuer
);
1056 unload_file(issuerp
);
1058 failf(data
, "server certificate issuer check failed (IssuerCert: %s)",
1059 data
->set
.ssl
.issuercert
?data
->set
.ssl
.issuercert
:"none");
1060 gnutls_x509_crt_deinit(x509_cert
);
1061 return CURLE_SSL_ISSUER_ERROR
;
1063 infof(data
, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
1064 data
->set
.ssl
.issuercert
?data
->set
.ssl
.issuercert
:"none");
1067 size
=sizeof(certbuf
);
1068 rc
= gnutls_x509_crt_get_dn_by_oid(x509_cert
, GNUTLS_OID_X520_COMMON_NAME
,
1069 0, /* the first and only one */
1074 infof(data
, "error fetching CN from cert:%s\n",
1075 gnutls_strerror(rc
));
1078 /* This function will check if the given certificate's subject matches the
1079 given hostname. This is a basic implementation of the matching described
1080 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1081 alternative name PKIX extension. Returns non zero on success, and zero on
1083 rc
= gnutls_x509_crt_check_hostname(x509_cert
, conn
->host
.name
);
1084 #if GNUTLS_VERSION_NUMBER < 0x030306
1085 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1089 #define use_addr in6_addr
1091 #define use_addr in_addr
1093 unsigned char addrbuf
[sizeof(struct use_addr
)];
1094 unsigned char certaddr
[sizeof(struct use_addr
)];
1095 size_t addrlen
= 0, certaddrlen
;
1099 if(Curl_inet_pton(AF_INET
, conn
->host
.name
, addrbuf
) > 0)
1102 else if(Curl_inet_pton(AF_INET6
, conn
->host
.name
, addrbuf
) > 0)
1108 certaddrlen
= sizeof(certaddr
);
1109 ret
= gnutls_x509_crt_get_subject_alt_name(x509_cert
, i
, certaddr
,
1110 &certaddrlen
, NULL
);
1111 /* If this happens, it wasn't an IP address. */
1112 if(ret
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
1116 if(ret
!= GNUTLS_SAN_IPADDRESS
)
1118 if(certaddrlen
== addrlen
&& !memcmp(addrbuf
, certaddr
, addrlen
)) {
1127 if(data
->set
.ssl
.verifyhost
) {
1128 failf(data
, "SSL: certificate subject name (%s) does not match "
1129 "target host name '%s'", certbuf
, conn
->host
.dispname
);
1130 gnutls_x509_crt_deinit(x509_cert
);
1131 return CURLE_PEER_FAILED_VERIFICATION
;
1134 infof(data
, "\t common name: %s (does not match '%s')\n",
1135 certbuf
, conn
->host
.dispname
);
1138 infof(data
, "\t common name: %s (matched)\n", certbuf
);
1140 /* Check for time-based validity */
1141 certclock
= gnutls_x509_crt_get_expiration_time(x509_cert
);
1143 if(certclock
== (time_t)-1) {
1144 if(data
->set
.ssl
.verifypeer
) {
1145 failf(data
, "server cert expiration date verify failed");
1146 gnutls_x509_crt_deinit(x509_cert
);
1147 return CURLE_SSL_CONNECT_ERROR
;
1150 infof(data
, "\t server certificate expiration date verify FAILED\n");
1153 if(certclock
< time(NULL
)) {
1154 if(data
->set
.ssl
.verifypeer
) {
1155 failf(data
, "server certificate expiration date has passed.");
1156 gnutls_x509_crt_deinit(x509_cert
);
1157 return CURLE_PEER_FAILED_VERIFICATION
;
1160 infof(data
, "\t server certificate expiration date FAILED\n");
1163 infof(data
, "\t server certificate expiration date OK\n");
1166 certclock
= gnutls_x509_crt_get_activation_time(x509_cert
);
1168 if(certclock
== (time_t)-1) {
1169 if(data
->set
.ssl
.verifypeer
) {
1170 failf(data
, "server cert activation date verify failed");
1171 gnutls_x509_crt_deinit(x509_cert
);
1172 return CURLE_SSL_CONNECT_ERROR
;
1175 infof(data
, "\t server certificate activation date verify FAILED\n");
1178 if(certclock
> time(NULL
)) {
1179 if(data
->set
.ssl
.verifypeer
) {
1180 failf(data
, "server certificate not activated yet.");
1181 gnutls_x509_crt_deinit(x509_cert
);
1182 return CURLE_PEER_FAILED_VERIFICATION
;
1185 infof(data
, "\t server certificate activation date FAILED\n");
1188 infof(data
, "\t server certificate activation date OK\n");
1191 ptr
= data
->set
.str
[STRING_SSL_PINNEDPUBLICKEY
];
1193 result
= pkp_pin_peer_pubkey(data
, x509_cert
, ptr
);
1194 if(result
!= CURLE_OK
) {
1195 failf(data
, "SSL: public key does not match pinned public key!");
1196 gnutls_x509_crt_deinit(x509_cert
);
1211 /* public key algorithm's parameters */
1212 algo
= gnutls_x509_crt_get_pk_algorithm(x509_cert
, &bits
);
1213 infof(data
, "\t certificate public key: %s\n",
1214 gnutls_pk_algorithm_get_name(algo
));
1216 /* version of the X.509 certificate. */
1217 infof(data
, "\t certificate version: #%d\n",
1218 gnutls_x509_crt_get_version(x509_cert
));
1221 size
= sizeof(certbuf
);
1222 gnutls_x509_crt_get_dn(x509_cert
, certbuf
, &size
);
1223 infof(data
, "\t subject: %s\n", certbuf
);
1225 certclock
= gnutls_x509_crt_get_activation_time(x509_cert
);
1226 showtime(data
, "start date", certclock
);
1228 certclock
= gnutls_x509_crt_get_expiration_time(x509_cert
);
1229 showtime(data
, "expire date", certclock
);
1231 size
= sizeof(certbuf
);
1232 gnutls_x509_crt_get_issuer_dn(x509_cert
, certbuf
, &size
);
1233 infof(data
, "\t issuer: %s\n", certbuf
);
1235 gnutls_x509_crt_deinit(x509_cert
);
1237 /* compression algorithm (if any) */
1238 ptr
= gnutls_compression_get_name(gnutls_compression_get(session
));
1239 /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
1240 infof(data
, "\t compression: %s\n", ptr
);
1243 if(conn
->bits
.tls_enable_alpn
) {
1244 rc
= gnutls_alpn_get_selected_protocol(session
, &proto
);
1246 infof(data
, "ALPN, server accepted to use %.*s\n", proto
.size
,
1250 if(proto
.size
== NGHTTP2_PROTO_VERSION_ID_LEN
&&
1251 !memcmp(NGHTTP2_PROTO_VERSION_ID
, proto
.data
,
1252 NGHTTP2_PROTO_VERSION_ID_LEN
)) {
1253 conn
->negnpn
= CURL_HTTP_VERSION_2
;
1257 if(proto
.size
== ALPN_HTTP_1_1_LENGTH
&&
1258 !memcmp(ALPN_HTTP_1_1
, proto
.data
, ALPN_HTTP_1_1_LENGTH
)) {
1259 conn
->negnpn
= CURL_HTTP_VERSION_1_1
;
1263 infof(data
, "ALPN, server did not agree to a protocol\n");
1267 conn
->ssl
[sockindex
].state
= ssl_connection_complete
;
1268 conn
->recv
[sockindex
] = gtls_recv
;
1269 conn
->send
[sockindex
] = gtls_send
;
1272 /* we always unconditionally get the session id here, as even if we
1273 already got it from the cache and asked to use it in the connection, it
1274 might've been rejected and then a new one is in use now and we need to
1276 void *connect_sessionid
;
1277 size_t connect_idsize
= 0;
1279 /* get the session ID data size */
1280 gnutls_session_get_data(session
, NULL
, &connect_idsize
);
1281 connect_sessionid
= malloc(connect_idsize
); /* get a buffer for it */
1283 if(connect_sessionid
) {
1284 /* extract session ID to the allocated buffer */
1285 gnutls_session_get_data(session
, connect_sessionid
, &connect_idsize
);
1287 incache
= !(Curl_ssl_getsessionid(conn
, &ssl_sessionid
, NULL
));
1289 /* there was one before in the cache, so instead of risking that the
1290 previous one was rejected, we just kill that and store the new */
1291 Curl_ssl_delsessionid(conn
, ssl_sessionid
);
1294 /* store this session id */
1295 result
= Curl_ssl_addsessionid(conn
, connect_sessionid
, connect_idsize
);
1297 free(connect_sessionid
);
1298 result
= CURLE_OUT_OF_MEMORY
;
1302 result
= CURLE_OUT_OF_MEMORY
;
1310 * This function is called after the TCP connect has completed. Setup the TLS
1311 * layer and do all necessary magic.
1313 /* We use connssl->connecting_state to keep track of the connection status;
1314 there are three states: 'ssl_connect_1' (not started yet or complete),
1315 'ssl_connect_2_reading' (waiting for data from server), and
1316 'ssl_connect_2_writing' (waiting to be able to write).
1319 gtls_connect_common(struct connectdata
*conn
,
1325 struct ssl_connect_data
*connssl
= &conn
->ssl
[sockindex
];
1327 /* Initiate the connection, if not already done */
1328 if(ssl_connect_1
==connssl
->connecting_state
) {
1329 rc
= gtls_connect_step1 (conn
, sockindex
);
1334 rc
= handshake(conn
, sockindex
, TRUE
, nonblocking
);
1336 /* handshake() sets its own error message with failf() */
1339 /* Finish connecting once the handshake is done */
1340 if(ssl_connect_1
==connssl
->connecting_state
) {
1341 rc
= gtls_connect_step3(conn
, sockindex
);
1346 *done
= ssl_connect_1
==connssl
->connecting_state
;
1352 Curl_gtls_connect_nonblocking(struct connectdata
*conn
,
1356 return gtls_connect_common(conn
, sockindex
, TRUE
, done
);
1360 Curl_gtls_connect(struct connectdata
*conn
,
1367 result
= gtls_connect_common(conn
, sockindex
, FALSE
, &done
);
1376 static ssize_t
gtls_send(struct connectdata
*conn
,
1382 ssize_t rc
= gnutls_record_send(conn
->ssl
[sockindex
].session
, mem
, len
);
1385 *curlcode
= (rc
== GNUTLS_E_AGAIN
)
1395 static void close_one(struct connectdata
*conn
,
1398 if(conn
->ssl
[idx
].session
) {
1399 gnutls_bye(conn
->ssl
[idx
].session
, GNUTLS_SHUT_RDWR
);
1400 gnutls_deinit(conn
->ssl
[idx
].session
);
1401 conn
->ssl
[idx
].session
= NULL
;
1403 if(conn
->ssl
[idx
].cred
) {
1404 gnutls_certificate_free_credentials(conn
->ssl
[idx
].cred
);
1405 conn
->ssl
[idx
].cred
= NULL
;
1408 if(conn
->ssl
[idx
].srp_client_cred
) {
1409 gnutls_srp_free_client_credentials(conn
->ssl
[idx
].srp_client_cred
);
1410 conn
->ssl
[idx
].srp_client_cred
= NULL
;
1415 void Curl_gtls_close(struct connectdata
*conn
, int sockindex
)
1417 close_one(conn
, sockindex
);
1421 * This function is called to shut down the SSL layer but keep the
1422 * socket open (CCC - Clear Command Channel)
1424 int Curl_gtls_shutdown(struct connectdata
*conn
, int sockindex
)
1428 struct SessionHandle
*data
= conn
->data
;
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... */
1437 if(data
->set
.ftp_ccc
== CURLFTPSSL_CCC_ACTIVE
)
1438 gnutls_bye(conn
->ssl
[sockindex
].session
, GNUTLS_SHUT_WR
);
1440 if(conn
->ssl
[sockindex
].session
) {
1442 int what
= Curl_socket_ready(conn
->sock
[sockindex
],
1443 CURL_SOCKET_BAD
, SSL_SHUTDOWN_TIMEOUT
);
1445 /* Something to read, let's do it and hope that it is the close
1446 notify alert from the server */
1447 result
= gnutls_record_recv(conn
->ssl
[sockindex
].session
,
1451 /* This is the expected response. There was no data but only
1452 the close notify alert */
1455 case GNUTLS_E_AGAIN
:
1456 case GNUTLS_E_INTERRUPTED
:
1457 infof(data
, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1465 else if(0 == what
) {
1467 failf(data
, "SSL shutdown timeout");
1472 /* anything that gets here is fatally bad */
1473 failf(data
, "select/poll on SSL socket, errno: %d", SOCKERRNO
);
1478 gnutls_deinit(conn
->ssl
[sockindex
].session
);
1480 gnutls_certificate_free_credentials(conn
->ssl
[sockindex
].cred
);
1483 if(data
->set
.ssl
.authtype
== CURL_TLSAUTH_SRP
1484 && data
->set
.ssl
.username
!= NULL
)
1485 gnutls_srp_free_client_credentials(conn
->ssl
[sockindex
].srp_client_cred
);
1488 conn
->ssl
[sockindex
].cred
= NULL
;
1489 conn
->ssl
[sockindex
].session
= NULL
;
1494 static ssize_t
gtls_recv(struct connectdata
*conn
, /* connection data */
1495 int num
, /* socketindex */
1496 char *buf
, /* store read data here */
1497 size_t buffersize
, /* max amount to read */
1502 ret
= gnutls_record_recv(conn
->ssl
[num
].session
, buf
, buffersize
);
1503 if((ret
== GNUTLS_E_AGAIN
) || (ret
== GNUTLS_E_INTERRUPTED
)) {
1504 *curlcode
= CURLE_AGAIN
;
1508 if(ret
== GNUTLS_E_REHANDSHAKE
) {
1509 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1510 proper way" takes a whole lot of work. */
1511 CURLcode result
= handshake(conn
, num
, FALSE
, FALSE
);
1513 /* handshake() writes error message on its own */
1516 *curlcode
= CURLE_AGAIN
; /* then return as if this was a wouldblock */
1521 failf(conn
->data
, "GnuTLS recv error (%d): %s",
1522 (int)ret
, gnutls_strerror((int)ret
));
1523 *curlcode
= CURLE_RECV_ERROR
;
1530 void Curl_gtls_session_free(void *ptr
)
1535 size_t Curl_gtls_version(char *buffer
, size_t size
)
1537 return snprintf(buffer
, size
, "GnuTLS/%s", gnutls_check_version(NULL
));
1540 #ifndef USE_GNUTLS_NETTLE
1541 static int Curl_gtls_seed(struct SessionHandle
*data
)
1543 /* we have the "SSL is seeded" boolean static to prevent multiple
1544 time-consuming seedings in vain */
1545 static bool ssl_seeded
= FALSE
;
1547 /* Quickly add a bit of entropy */
1548 gcry_fast_random_poll();
1550 if(!ssl_seeded
|| data
->set
.str
[STRING_SSL_RANDOM_FILE
] ||
1551 data
->set
.str
[STRING_SSL_EGDSOCKET
]) {
1553 /* TODO: to a good job seeding the RNG
1554 This may involve the gcry_control function and these options:
1555 GCRYCTL_SET_RANDOM_SEED_FILE
1556 GCRYCTL_SET_RNDEGD_SOCKET
1564 /* data might be NULL! */
1565 int Curl_gtls_random(struct SessionHandle
*data
,
1566 unsigned char *entropy
,
1569 #if defined(USE_GNUTLS_NETTLE)
1571 gnutls_rnd(GNUTLS_RND_RANDOM
, entropy
, length
);
1572 #elif defined(USE_GNUTLS)
1574 Curl_gtls_seed(data
); /* Initiate the seed if not already done */
1575 gcry_randomize(entropy
, length
, GCRY_STRONG_RANDOM
);
1580 void Curl_gtls_md5sum(unsigned char *tmp
, /* input */
1582 unsigned char *md5sum
, /* output */
1585 #if defined(USE_GNUTLS_NETTLE)
1586 struct md5_ctx MD5pw
;
1588 md5_update(&MD5pw
, (unsigned int)tmplen
, tmp
);
1589 md5_digest(&MD5pw
, (unsigned int)md5len
, md5sum
);
1590 #elif defined(USE_GNUTLS)
1592 gcry_md_open(&MD5pw
, GCRY_MD_MD5
, 0);
1593 gcry_md_write(MD5pw
, tmp
, tmplen
);
1594 memcpy(md5sum
, gcry_md_read (MD5pw
, 0), md5len
);
1595 gcry_md_close(MD5pw
);
1599 void Curl_gtls_sha256sum(const unsigned char *tmp
, /* input */
1601 unsigned char *sha256sum
, /* output */
1604 #if defined(USE_GNUTLS_NETTLE)
1605 struct sha256_ctx SHA256pw
;
1606 sha256_init(&SHA256pw
);
1607 sha256_update(&SHA256pw
, (unsigned int)tmplen
, tmp
);
1608 sha256_digest(&SHA256pw
, (unsigned int)sha256len
, sha256sum
);
1609 #elif defined(USE_GNUTLS)
1610 gcry_md_hd_t SHA256pw
;
1611 gcry_md_open(&SHA256pw
, GCRY_MD_SHA256
, 0);
1612 gcry_md_write(SHA256pw
, tmp
, tmplen
);
1613 memcpy(sha256sum
, gcry_md_read (SHA256pw
, 0), sha256len
);
1614 gcry_md_close(SHA256pw
);
1618 bool Curl_gtls_cert_status_request(void)
1627 #endif /* USE_GNUTLS */