1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25 /*
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.
28 *
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.
31 */
32
33 #include "curl_setup.h"
34
35 #ifdef USE_GNUTLS
36
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>
42
43 #include "urldata.h"
44 #include "sendf.h"
45 #include "inet_pton.h"
46 #include "keylog.h"
47 #include "gtls.h"
48 #include "vtls.h"
49 #include "vtls_int.h"
50 #include "vauth/vauth.h"
51 #include "parsedate.h"
52 #include "connect.h" /* for the connect timeout */
53 #include "select.h"
54 #include "strcase.h"
55 #include "warnless.h"
56 #include "x509asn1.h"
57 #include "multiif.h"
58 #include "curl_printf.h"
59 #include "curl_memory.h"
60 /* The last #include file should be: */
61 #include "memdebug.h"
62
63 #ifndef ARRAYSIZE
64 #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
65 #endif
66
67 #define QUIC_PRIORITY \
68 "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
69 "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
70 "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
71 "%DISABLE_TLS13_COMPAT_MODE"
72
73 /* Enable GnuTLS debugging by defining GTLSDEBUG */
74 /*#define GTLSDEBUG */
75
76 #ifdef GTLSDEBUG
tls_log_func(int level,const char * str)77 static void tls_log_func(int level, const char *str)
78 {
79 fprintf(stderr, "|<%d>| %s", level, str);
80 }
81 #endif
82 static bool gtls_inited = FALSE;
83
84 #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
85 #error "too old GnuTLS version"
86 #endif
87
88 # include <gnutls/ocsp.h>
89
90 struct gtls_ssl_backend_data {
91 struct gtls_ctx gtls;
92 };
93
gtls_push(void * s,const void * buf,size_t blen)94 static ssize_t gtls_push(void *s, const void *buf, size_t blen)
95 {
96 struct Curl_cfilter *cf = s;
97 struct ssl_connect_data *connssl = cf->ctx;
98 struct gtls_ssl_backend_data *backend =
99 (struct gtls_ssl_backend_data *)connssl->backend;
100 struct Curl_easy *data = CF_DATA_CURRENT(cf);
101 ssize_t nwritten;
102 CURLcode result;
103
104 DEBUGASSERT(data);
105 nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
106 CURL_TRC_CF(data, cf, "gtls_push(len=%zu) -> %zd, err=%d",
107 blen, nwritten, result);
108 backend->gtls.io_result = result;
109 if(nwritten < 0) {
110 gnutls_transport_set_errno(backend->gtls.session,
111 (CURLE_AGAIN == result)? EAGAIN : EINVAL);
112 nwritten = -1;
113 }
114 return nwritten;
115 }
116
gtls_pull(void * s,void * buf,size_t blen)117 static ssize_t gtls_pull(void *s, void *buf, size_t blen)
118 {
119 struct Curl_cfilter *cf = s;
120 struct ssl_connect_data *connssl = cf->ctx;
121 struct gtls_ssl_backend_data *backend =
122 (struct gtls_ssl_backend_data *)connssl->backend;
123 struct Curl_easy *data = CF_DATA_CURRENT(cf);
124 ssize_t nread;
125 CURLcode result;
126
127 DEBUGASSERT(data);
128 if(!backend->gtls.shared_creds->trust_setup) {
129 result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
130 if(result) {
131 gnutls_transport_set_errno(backend->gtls.session, EINVAL);
132 backend->gtls.io_result = result;
133 return -1;
134 }
135 }
136
137 nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
138 CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %zd, err=%d",
139 blen, nread, result);
140 backend->gtls.io_result = result;
141 if(nread < 0) {
142 gnutls_transport_set_errno(backend->gtls.session,
143 (CURLE_AGAIN == result)? EAGAIN : EINVAL);
144 nread = -1;
145 }
146 else if(nread == 0)
147 connssl->peer_closed = TRUE;
148 return nread;
149 }
150
151 /* gtls_init()
152 *
153 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
154 * are not thread-safe and thus this function itself is not thread-safe and
155 * must only be called from within curl_global_init() to keep the thread
156 * situation under control!
157 */
gtls_init(void)158 static int gtls_init(void)
159 {
160 int ret = 1;
161 if(!gtls_inited) {
162 ret = gnutls_global_init()?0:1;
163 #ifdef GTLSDEBUG
164 gnutls_global_set_log_function(tls_log_func);
165 gnutls_global_set_log_level(2);
166 #endif
167 gtls_inited = TRUE;
168 }
169 return ret;
170 }
171
gtls_cleanup(void)172 static void gtls_cleanup(void)
173 {
174 if(gtls_inited) {
175 gnutls_global_deinit();
176 gtls_inited = FALSE;
177 }
178 }
179
180 #ifndef CURL_DISABLE_VERBOSE_STRINGS
showtime(struct Curl_easy * data,const char * text,time_t stamp)181 static void showtime(struct Curl_easy *data,
182 const char *text,
183 time_t stamp)
184 {
185 struct tm buffer;
186 const struct tm *tm = &buffer;
187 char str[96];
188 CURLcode result = Curl_gmtime(stamp, &buffer);
189 if(result)
190 return;
191
192 msnprintf(str,
193 sizeof(str),
194 " %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
195 text,
196 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
197 tm->tm_mday,
198 Curl_month[tm->tm_mon],
199 tm->tm_year + 1900,
200 tm->tm_hour,
201 tm->tm_min,
202 tm->tm_sec);
203 infof(data, "%s", str);
204 }
205 #endif
206
load_file(const char * file)207 static gnutls_datum_t load_file(const char *file)
208 {
209 FILE *f;
210 gnutls_datum_t loaded_file = { NULL, 0 };
211 long filelen;
212 void *ptr;
213
214 f = fopen(file, "rb");
215 if(!f)
216 return loaded_file;
217 if(fseek(f, 0, SEEK_END) != 0
218 || (filelen = ftell(f)) < 0
219 || fseek(f, 0, SEEK_SET) != 0
220 || !(ptr = malloc((size_t)filelen)))
221 goto out;
222 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
223 free(ptr);
224 goto out;
225 }
226
227 loaded_file.data = ptr;
228 loaded_file.size = (unsigned int)filelen;
229 out:
230 fclose(f);
231 return loaded_file;
232 }
233
unload_file(gnutls_datum_t data)234 static void unload_file(gnutls_datum_t data)
235 {
236 free(data.data);
237 }
238
239
240 /* this function does a SSL/TLS (re-)handshake */
handshake(struct Curl_cfilter * cf,struct Curl_easy * data,bool duringconnect,bool nonblocking)241 static CURLcode handshake(struct Curl_cfilter *cf,
242 struct Curl_easy *data,
243 bool duringconnect,
244 bool nonblocking)
245 {
246 struct ssl_connect_data *connssl = cf->ctx;
247 struct gtls_ssl_backend_data *backend =
248 (struct gtls_ssl_backend_data *)connssl->backend;
249 gnutls_session_t session;
250 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
251
252 DEBUGASSERT(backend);
253 session = backend->gtls.session;
254 connssl->connecting_state = ssl_connect_2;
255
256 for(;;) {
257 timediff_t timeout_ms;
258 int rc;
259
260 /* check allowed time left */
261 timeout_ms = Curl_timeleft(data, NULL, duringconnect);
262
263 if(timeout_ms < 0) {
264 /* no need to continue if time already is up */
265 failf(data, "SSL connection timeout");
266 return CURLE_OPERATION_TIMEDOUT;
267 }
268
269 /* if ssl is expecting something, check if it's available. */
270 if(connssl->io_need) {
271 int what;
272 curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND)?
273 sockfd:CURL_SOCKET_BAD;
274 curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV)?
275 sockfd:CURL_SOCKET_BAD;
276
277 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
278 nonblocking?0:
279 timeout_ms?timeout_ms:1000);
280 if(what < 0) {
281 /* fatal error */
282 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
283 return CURLE_SSL_CONNECT_ERROR;
284 }
285 else if(0 == what) {
286 if(nonblocking)
287 return CURLE_OK;
288 else if(timeout_ms) {
289 /* timeout */
290 failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
291 return CURLE_OPERATION_TIMEDOUT;
292 }
293 }
294 /* socket is readable or writable */
295 }
296
297 connssl->io_need = CURL_SSL_IO_NEED_NONE;
298 backend->gtls.io_result = CURLE_OK;
299 rc = gnutls_handshake(session);
300
301 if(!backend->gtls.shared_creds->trust_setup) {
302 /* After having send off the ClientHello, we prepare the trust
303 * store to verify the coming certificate from the server */
304 CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
305 if(result)
306 return result;
307 }
308
309 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
310 connssl->io_need =
311 gnutls_record_get_direction(session)?
312 CURL_SSL_IO_NEED_SEND:CURL_SSL_IO_NEED_RECV;
313 continue;
314 }
315 else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
316 const char *strerr = NULL;
317
318 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
319 gnutls_alert_description_t alert = gnutls_alert_get(session);
320 strerr = gnutls_alert_get_name(alert);
321 }
322
323 if(!strerr)
324 strerr = gnutls_strerror(rc);
325
326 infof(data, "gnutls_handshake() warning: %s", strerr);
327 continue;
328 }
329 else if((rc < 0) && backend->gtls.io_result) {
330 return backend->gtls.io_result;
331 }
332 else if(rc < 0) {
333 const char *strerr = NULL;
334
335 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
336 gnutls_alert_description_t alert = gnutls_alert_get(session);
337 strerr = gnutls_alert_get_name(alert);
338 }
339
340 if(!strerr)
341 strerr = gnutls_strerror(rc);
342
343 failf(data, "gnutls_handshake() failed: %s", strerr);
344 return CURLE_SSL_CONNECT_ERROR;
345 }
346
347 /* Reset our connect state machine */
348 connssl->connecting_state = ssl_connect_1;
349 return CURLE_OK;
350 }
351 }
352
do_file_type(const char * type)353 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
354 {
355 if(!type || !type[0])
356 return GNUTLS_X509_FMT_PEM;
357 if(strcasecompare(type, "PEM"))
358 return GNUTLS_X509_FMT_PEM;
359 if(strcasecompare(type, "DER"))
360 return GNUTLS_X509_FMT_DER;
361 return GNUTLS_X509_FMT_PEM; /* default to PEM */
362 }
363
364 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
365 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
366 requested in the priority string, so treat it specially
367 */
368 #define GNUTLS_SRP "+SRP"
369
370 static CURLcode
set_ssl_version_min_max(struct Curl_easy * data,struct ssl_peer * peer,struct ssl_primary_config * conn_config,const char ** prioritylist,const char * tls13support)371 set_ssl_version_min_max(struct Curl_easy *data,
372 struct ssl_peer *peer,
373 struct ssl_primary_config *conn_config,
374 const char **prioritylist,
375 const char *tls13support)
376 {
377 long ssl_version = conn_config->version;
378 long ssl_version_max = conn_config->version_max;
379
380 if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
381 (ssl_version == CURL_SSLVERSION_TLSv1))
382 ssl_version = CURL_SSLVERSION_TLSv1_0;
383 if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
384 ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
385
386 if(peer->transport == TRNSPRT_QUIC) {
387 if((ssl_version_max != CURL_SSLVERSION_MAX_DEFAULT) &&
388 (ssl_version_max < CURL_SSLVERSION_MAX_TLSv1_3)) {
389 failf(data, "QUIC needs at least TLS version 1.3");
390 return CURLE_SSL_CONNECT_ERROR;
391 }
392 *prioritylist = QUIC_PRIORITY;
393 return CURLE_OK;
394 }
395
396 if(!tls13support) {
397 /* If the running GnuTLS doesn't support TLS 1.3, we must not specify a
398 prioritylist involving that since it will make GnuTLS return an en
399 error back at us */
400 if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
401 (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
402 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
403 }
404 }
405 else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
406 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
407 }
408
409 switch(ssl_version | ssl_version_max) {
410 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
411 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
412 "+VERS-TLS1.0";
413 return CURLE_OK;
414 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
415 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
416 "+VERS-TLS1.1:+VERS-TLS1.0";
417 return CURLE_OK;
418 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
419 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
420 "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
421 return CURLE_OK;
422 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
423 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
424 "+VERS-TLS1.1";
425 return CURLE_OK;
426 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
427 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
428 "+VERS-TLS1.2:+VERS-TLS1.1";
429 return CURLE_OK;
430 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
431 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
432 "+VERS-TLS1.2";
433 return CURLE_OK;
434 case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
435 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
436 "+VERS-TLS1.3";
437 return CURLE_OK;
438 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
439 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
440 return CURLE_OK;
441 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
442 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
443 "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
444 return CURLE_OK;
445 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
446 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
447 "+VERS-TLS1.3:+VERS-TLS1.2";
448 return CURLE_OK;
449 }
450
451 failf(data, "GnuTLS: cannot set ssl protocol");
452 return CURLE_SSL_CONNECT_ERROR;
453 }
454
Curl_gtls_shared_creds_create(struct Curl_easy * data,struct gtls_shared_creds ** pcreds)455 CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data,
456 struct gtls_shared_creds **pcreds)
457 {
458 struct gtls_shared_creds *shared;
459 int rc;
460
461 *pcreds = NULL;
462 shared = calloc(1, sizeof(*shared));
463 if(!shared)
464 return CURLE_OUT_OF_MEMORY;
465
466 rc = gnutls_certificate_allocate_credentials(&shared->creds);
467 if(rc != GNUTLS_E_SUCCESS) {
468 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
469 free(shared);
470 return CURLE_SSL_CONNECT_ERROR;
471 }
472
473 shared->refcount = 1;
474 shared->time = Curl_now();
475 *pcreds = shared;
476 return CURLE_OK;
477 }
478
Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds * creds)479 CURLcode Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds *creds)
480 {
481 DEBUGASSERT(creds);
482 if(creds->refcount < SIZE_T_MAX) {
483 ++creds->refcount;
484 return CURLE_OK;
485 }
486 return CURLE_BAD_FUNCTION_ARGUMENT;
487 }
488
Curl_gtls_shared_creds_free(struct gtls_shared_creds ** pcreds)489 void Curl_gtls_shared_creds_free(struct gtls_shared_creds **pcreds)
490 {
491 struct gtls_shared_creds *shared = *pcreds;
492 *pcreds = NULL;
493 if(shared) {
494 --shared->refcount;
495 if(!shared->refcount) {
496 gnutls_certificate_free_credentials(shared->creds);
497 free(shared->CAfile);
498 free(shared);
499 }
500 }
501 }
502
gtls_populate_creds(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_certificate_credentials_t creds)503 static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
504 struct Curl_easy *data,
505 gnutls_certificate_credentials_t creds)
506 {
507 struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
508 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
509 int rc;
510
511 if(config->verifypeer) {
512 bool imported_native_ca = false;
513
514 if(ssl_config->native_ca_store) {
515 rc = gnutls_certificate_set_x509_system_trust(creds);
516 if(rc < 0)
517 infof(data, "error reading native ca store (%s), continuing anyway",
518 gnutls_strerror(rc));
519 else {
520 infof(data, "found %d certificates in native ca store", rc);
521 if(rc > 0)
522 imported_native_ca = true;
523 }
524 }
525
526 if(config->CAfile) {
527 /* set the trusted CA cert bundle file */
528 gnutls_certificate_set_verify_flags(creds,
529 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
530
531 rc = gnutls_certificate_set_x509_trust_file(creds,
532 config->CAfile,
533 GNUTLS_X509_FMT_PEM);
534 if(rc < 0) {
535 infof(data, "error reading ca cert file %s (%s)%s",
536 config->CAfile, gnutls_strerror(rc),
537 (imported_native_ca ? ", continuing anyway" : ""));
538 if(!imported_native_ca) {
539 ssl_config->certverifyresult = rc;
540 return CURLE_SSL_CACERT_BADFILE;
541 }
542 }
543 else
544 infof(data, "found %d certificates in %s", rc, config->CAfile);
545 }
546
547 if(config->CApath) {
548 /* set the trusted CA cert directory */
549 rc = gnutls_certificate_set_x509_trust_dir(creds, config->CApath,
550 GNUTLS_X509_FMT_PEM);
551 if(rc < 0) {
552 infof(data, "error reading ca cert file %s (%s)%s",
553 config->CApath, gnutls_strerror(rc),
554 (imported_native_ca ? ", continuing anyway" : ""));
555 if(!imported_native_ca) {
556 ssl_config->certverifyresult = rc;
557 return CURLE_SSL_CACERT_BADFILE;
558 }
559 }
560 else
561 infof(data, "found %d certificates in %s", rc, config->CApath);
562 }
563 }
564
565 if(config->CRLfile) {
566 /* set the CRL list file */
567 rc = gnutls_certificate_set_x509_crl_file(creds, config->CRLfile,
568 GNUTLS_X509_FMT_PEM);
569 if(rc < 0) {
570 failf(data, "error reading crl file %s (%s)",
571 config->CRLfile, gnutls_strerror(rc));
572 return CURLE_SSL_CRL_BADFILE;
573 }
574 else
575 infof(data, "found %d CRL in %s", rc, config->CRLfile);
576 }
577
578 return CURLE_OK;
579 }
580
581 /* key to use at `multi->proto_hash` */
582 #define MPROTO_GTLS_X509_KEY "tls:gtls:x509:share"
583
gtls_shared_creds_expired(const struct Curl_easy * data,const struct gtls_shared_creds * sc)584 static bool gtls_shared_creds_expired(const struct Curl_easy *data,
585 const struct gtls_shared_creds *sc)
586 {
587 const struct ssl_general_config *cfg = &data->set.general_ssl;
588 struct curltime now = Curl_now();
589 timediff_t elapsed_ms = Curl_timediff(now, sc->time);
590 timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
591
592 if(timeout_ms < 0)
593 return false;
594
595 return elapsed_ms >= timeout_ms;
596 }
597
gtls_shared_creds_different(struct Curl_cfilter * cf,const struct gtls_shared_creds * sc)598 static bool gtls_shared_creds_different(struct Curl_cfilter *cf,
599 const struct gtls_shared_creds *sc)
600 {
601 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
602 if(!sc->CAfile || !conn_config->CAfile)
603 return sc->CAfile != conn_config->CAfile;
604
605 return strcmp(sc->CAfile, conn_config->CAfile);
606 }
607
608 static struct gtls_shared_creds*
gtls_get_cached_creds(struct Curl_cfilter * cf,struct Curl_easy * data)609 gtls_get_cached_creds(struct Curl_cfilter *cf, struct Curl_easy *data)
610 {
611 struct gtls_shared_creds *shared_creds;
612
613 if(data->multi) {
614 shared_creds = Curl_hash_pick(&data->multi->proto_hash,
615 (void *)MPROTO_GTLS_X509_KEY,
616 sizeof(MPROTO_GTLS_X509_KEY)-1);
617 if(shared_creds && shared_creds->creds &&
618 !gtls_shared_creds_expired(data, shared_creds) &&
619 !gtls_shared_creds_different(cf, shared_creds)) {
620 return shared_creds;
621 }
622 }
623 return NULL;
624 }
625
gtls_shared_creds_hash_free(void * key,size_t key_len,void * p)626 static void gtls_shared_creds_hash_free(void *key, size_t key_len, void *p)
627 {
628 struct gtls_shared_creds *sc = p;
629 DEBUGASSERT(key_len == (sizeof(MPROTO_GTLS_X509_KEY)-1));
630 DEBUGASSERT(!memcmp(MPROTO_GTLS_X509_KEY, key, key_len));
631 (void)key;
632 (void)key_len;
633 Curl_gtls_shared_creds_free(&sc); /* down reference */
634 }
635
gtls_set_cached_creds(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_shared_creds * sc)636 static void gtls_set_cached_creds(struct Curl_cfilter *cf,
637 struct Curl_easy *data,
638 struct gtls_shared_creds *sc)
639 {
640 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
641
642 DEBUGASSERT(sc);
643 DEBUGASSERT(sc->creds);
644 DEBUGASSERT(!sc->CAfile);
645 DEBUGASSERT(sc->refcount == 1);
646 if(!data->multi)
647 return;
648
649 if(conn_config->CAfile) {
650 sc->CAfile = strdup(conn_config->CAfile);
651 if(!sc->CAfile)
652 return;
653 }
654
655 if(Curl_gtls_shared_creds_up_ref(sc))
656 return;
657
658 if(!Curl_hash_add2(&data->multi->proto_hash,
659 (void *)MPROTO_GTLS_X509_KEY,
660 sizeof(MPROTO_GTLS_X509_KEY)-1,
661 sc, gtls_shared_creds_hash_free)) {
662 Curl_gtls_shared_creds_free(&sc); /* down reference again */
663 return;
664 }
665 }
666
Curl_gtls_client_trust_setup(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_ctx * gtls)667 CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
668 struct Curl_easy *data,
669 struct gtls_ctx *gtls)
670 {
671 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
672 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
673 struct gtls_shared_creds *cached_creds = NULL;
674 bool cache_criteria_met;
675 CURLcode result;
676 int rc;
677
678
679 /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
680 or no source is provided and we are falling back to openssl's built-in
681 default. */
682 cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
683 conn_config->verifypeer &&
684 !conn_config->CApath &&
685 !conn_config->ca_info_blob &&
686 !ssl_config->primary.CRLfile &&
687 !ssl_config->native_ca_store &&
688 !conn_config->clientcert; /* GNUTls adds client cert to its credentials! */
689
690 if(cache_criteria_met)
691 cached_creds = gtls_get_cached_creds(cf, data);
692
693 if(cached_creds && !Curl_gtls_shared_creds_up_ref(cached_creds)) {
694 CURL_TRC_CF(data, cf, "using shared trust anchors and CRLs");
695 Curl_gtls_shared_creds_free(>ls->shared_creds);
696 gtls->shared_creds = cached_creds;
697 rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
698 gtls->shared_creds->creds);
699 if(rc != GNUTLS_E_SUCCESS) {
700 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
701 return CURLE_SSL_CONNECT_ERROR;
702 }
703 }
704 else {
705 CURL_TRC_CF(data, cf, "loading trust anchors and CRLs");
706 result = gtls_populate_creds(cf, data, gtls->shared_creds->creds);
707 if(result)
708 return result;
709 gtls->shared_creds->trust_setup = TRUE;
710 if(cache_criteria_met)
711 gtls_set_cached_creds(cf, data, gtls->shared_creds);
712 }
713 return CURLE_OK;
714 }
715
gtls_sessionid_free(void * sessionid,size_t idsize)716 static void gtls_sessionid_free(void *sessionid, size_t idsize)
717 {
718 (void)idsize;
719 free(sessionid);
720 }
721
gtls_update_session_id(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)722 static CURLcode gtls_update_session_id(struct Curl_cfilter *cf,
723 struct Curl_easy *data,
724 gnutls_session_t session)
725 {
726 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
727 struct ssl_connect_data *connssl = cf->ctx;
728 CURLcode result = CURLE_OK;
729
730 if(ssl_config->primary.sessionid) {
731 /* we always unconditionally get the session id here, as even if we
732 already got it from the cache and asked to use it in the connection, it
733 might've been rejected and then a new one is in use now and we need to
734 detect that. */
735 void *connect_sessionid;
736 size_t connect_idsize = 0;
737
738 /* get the session ID data size */
739 gnutls_session_get_data(session, NULL, &connect_idsize);
740 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
741 if(!connect_sessionid) {
742 return CURLE_OUT_OF_MEMORY;
743 }
744 else {
745 bool incache;
746 void *ssl_sessionid;
747
748 /* extract session ID to the allocated buffer */
749 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
750
751 CURL_TRC_CF(data, cf, "get session id (len=%zu) and store in cache",
752 connect_idsize);
753 Curl_ssl_sessionid_lock(data);
754 incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
755 &ssl_sessionid, NULL));
756 if(incache) {
757 /* there was one before in the cache, so instead of risking that the
758 previous one was rejected, we just kill that and store the new */
759 Curl_ssl_delsessionid(data, ssl_sessionid);
760 }
761
762 /* store this session id, takes ownership */
763 result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
764 connect_sessionid, connect_idsize,
765 gtls_sessionid_free);
766 Curl_ssl_sessionid_unlock(data);
767 }
768 }
769 return result;
770 }
771
gtls_handshake_cb(gnutls_session_t session,unsigned int htype,unsigned when,unsigned int incoming,const gnutls_datum_t * msg)772 static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
773 unsigned when, unsigned int incoming,
774 const gnutls_datum_t *msg)
775 {
776 struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
777
778 (void)msg;
779 (void)incoming;
780 if(when) { /* after message has been processed */
781 struct Curl_easy *data = CF_DATA_CURRENT(cf);
782 if(data) {
783 CURL_TRC_CF(data, cf, "handshake: %s message type %d",
784 incoming? "incoming" : "outgoing", htype);
785 switch(htype) {
786 case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
787 gtls_update_session_id(cf, data, session);
788 break;
789 }
790 default:
791 break;
792 }
793 }
794 }
795 return 0;
796 }
797
gtls_client_init(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,struct gtls_ctx * gtls)798 static CURLcode gtls_client_init(struct Curl_cfilter *cf,
799 struct Curl_easy *data,
800 struct ssl_peer *peer,
801 struct gtls_ctx *gtls)
802 {
803 struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
804 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
805 unsigned int init_flags;
806 int rc;
807 bool sni = TRUE; /* default is SNI enabled */
808 const char *prioritylist;
809 const char *err = NULL;
810 const char *tls13support;
811 CURLcode result;
812
813 if(!gtls_inited)
814 gtls_init();
815
816 if(config->version == CURL_SSLVERSION_SSLv2) {
817 failf(data, "GnuTLS does not support SSLv2");
818 return CURLE_SSL_CONNECT_ERROR;
819 }
820 else if(config->version == CURL_SSLVERSION_SSLv3)
821 sni = FALSE; /* SSLv3 has no SNI */
822
823 /* allocate a shared creds struct */
824 result = Curl_gtls_shared_creds_create(data, >ls->shared_creds);
825 if(result)
826 return result;
827
828 #ifdef USE_GNUTLS_SRP
829 if(config->username && Curl_auth_allowed_to_host(data)) {
830 infof(data, "Using TLS-SRP username: %s", config->username);
831
832 rc = gnutls_srp_allocate_client_credentials(>ls->srp_client_cred);
833 if(rc != GNUTLS_E_SUCCESS) {
834 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
835 gnutls_strerror(rc));
836 return CURLE_OUT_OF_MEMORY;
837 }
838
839 rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
840 config->username,
841 config->password);
842 if(rc != GNUTLS_E_SUCCESS) {
843 failf(data, "gnutls_srp_set_client_cred() failed: %s",
844 gnutls_strerror(rc));
845 return CURLE_BAD_FUNCTION_ARGUMENT;
846 }
847 }
848 #endif
849
850 ssl_config->certverifyresult = 0;
851
852 /* Initialize TLS session as a client */
853 init_flags = GNUTLS_CLIENT;
854
855 #if defined(GNUTLS_FORCE_CLIENT_CERT)
856 init_flags |= GNUTLS_FORCE_CLIENT_CERT;
857 #endif
858
859 #if defined(GNUTLS_NO_TICKETS)
860 /* Disable TLS session tickets */
861 init_flags |= GNUTLS_NO_TICKETS;
862 #endif
863
864 rc = gnutls_init(>ls->session, init_flags);
865 if(rc != GNUTLS_E_SUCCESS) {
866 failf(data, "gnutls_init() failed: %d", rc);
867 return CURLE_SSL_CONNECT_ERROR;
868 }
869
870 if(sni && peer->sni) {
871 if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
872 peer->sni, strlen(peer->sni)) < 0) {
873 failf(data, "Failed to set SNI");
874 return CURLE_SSL_CONNECT_ERROR;
875 }
876 }
877
878 /* Use default priorities */
879 rc = gnutls_set_default_priority(gtls->session);
880 if(rc != GNUTLS_E_SUCCESS)
881 return CURLE_SSL_CONNECT_ERROR;
882
883 /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
884 tls13support = gnutls_check_version("3.6.5");
885
886 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
887 * removed if a run-time error indicates that SRP is not supported by this
888 * GnuTLS version */
889
890 if(config->version == CURL_SSLVERSION_SSLv2 ||
891 config->version == CURL_SSLVERSION_SSLv3) {
892 failf(data, "GnuTLS does not support SSLv2 or SSLv3");
893 return CURLE_SSL_CONNECT_ERROR;
894 }
895
896 if(config->version == CURL_SSLVERSION_TLSv1_3) {
897 if(!tls13support) {
898 failf(data, "This GnuTLS installation does not support TLS 1.3");
899 return CURLE_SSL_CONNECT_ERROR;
900 }
901 }
902
903 /* At this point we know we have a supported TLS version, so set it */
904 result = set_ssl_version_min_max(data, peer,
905 config, &prioritylist, tls13support);
906 if(result)
907 return result;
908
909 #ifdef USE_GNUTLS_SRP
910 /* Only add SRP to the cipher list if SRP is requested. Otherwise
911 * GnuTLS will disable TLS 1.3 support. */
912 if(config->username) {
913 char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
914 if(!prioritysrp)
915 return CURLE_OUT_OF_MEMORY;
916 rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
917 free(prioritysrp);
918
919 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
920 infof(data, "This GnuTLS does not support SRP");
921 }
922 }
923 else {
924 #endif
925 infof(data, "GnuTLS ciphers: %s", prioritylist);
926 rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
927 #ifdef USE_GNUTLS_SRP
928 }
929 #endif
930
931 if(rc != GNUTLS_E_SUCCESS) {
932 failf(data, "Error %d setting GnuTLS cipher list starting with %s",
933 rc, err);
934 return CURLE_SSL_CONNECT_ERROR;
935 }
936
937 if(config->clientcert) {
938 if(!gtls->shared_creds->trust_setup) {
939 result = Curl_gtls_client_trust_setup(cf, data, gtls);
940 if(result)
941 return result;
942 }
943 if(ssl_config->key_passwd) {
944 const unsigned int supported_key_encryption_algorithms =
945 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
946 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
947 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
948 GNUTLS_PKCS_USE_PBES2_AES_256;
949 rc = gnutls_certificate_set_x509_key_file2(
950 gtls->shared_creds->creds,
951 config->clientcert,
952 ssl_config->key ? ssl_config->key : config->clientcert,
953 do_file_type(ssl_config->cert_type),
954 ssl_config->key_passwd,
955 supported_key_encryption_algorithms);
956 if(rc != GNUTLS_E_SUCCESS) {
957 failf(data,
958 "error reading X.509 potentially-encrypted key file: %s",
959 gnutls_strerror(rc));
960 return CURLE_SSL_CONNECT_ERROR;
961 }
962 }
963 else {
964 if(gnutls_certificate_set_x509_key_file(
965 gtls->shared_creds->creds,
966 config->clientcert,
967 ssl_config->key ? ssl_config->key : config->clientcert,
968 do_file_type(ssl_config->cert_type) ) !=
969 GNUTLS_E_SUCCESS) {
970 failf(data, "error reading X.509 key or certificate file");
971 return CURLE_SSL_CONNECT_ERROR;
972 }
973 }
974 }
975
976 #ifdef USE_GNUTLS_SRP
977 /* put the credentials to the current session */
978 if(config->username) {
979 rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
980 gtls->srp_client_cred);
981 if(rc != GNUTLS_E_SUCCESS) {
982 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
983 return CURLE_SSL_CONNECT_ERROR;
984 }
985 }
986 else
987 #endif
988 {
989 rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
990 gtls->shared_creds->creds);
991 if(rc != GNUTLS_E_SUCCESS) {
992 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
993 return CURLE_SSL_CONNECT_ERROR;
994 }
995 }
996
997 if(config->verifystatus) {
998 rc = gnutls_ocsp_status_request_enable_client(gtls->session,
999 NULL, 0, NULL);
1000 if(rc != GNUTLS_E_SUCCESS) {
1001 failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
1002 return CURLE_SSL_CONNECT_ERROR;
1003 }
1004 }
1005
1006 return CURLE_OK;
1007 }
1008
keylog_callback(gnutls_session_t session,const char * label,const gnutls_datum_t * secret)1009 static int keylog_callback(gnutls_session_t session, const char *label,
1010 const gnutls_datum_t *secret)
1011 {
1012 gnutls_datum_t crandom;
1013 gnutls_datum_t srandom;
1014
1015 gnutls_session_get_random(session, &crandom, &srandom);
1016 if(crandom.size != 32) {
1017 return -1;
1018 }
1019
1020 Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
1021 return 0;
1022 }
1023
Curl_gtls_ctx_init(struct gtls_ctx * gctx,struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,const unsigned char * alpn,size_t alpn_len,Curl_gtls_ctx_setup_cb * cb_setup,void * cb_user_data,void * ssl_user_data)1024 CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
1025 struct Curl_cfilter *cf,
1026 struct Curl_easy *data,
1027 struct ssl_peer *peer,
1028 const unsigned char *alpn, size_t alpn_len,
1029 Curl_gtls_ctx_setup_cb *cb_setup,
1030 void *cb_user_data,
1031 void *ssl_user_data)
1032 {
1033 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1034 CURLcode result;
1035
1036 DEBUGASSERT(gctx);
1037
1038 result = gtls_client_init(cf, data, peer, gctx);
1039 if(result)
1040 return result;
1041
1042 gnutls_session_set_ptr(gctx->session, ssl_user_data);
1043
1044 if(cb_setup) {
1045 result = cb_setup(cf, data, cb_user_data);
1046 if(result)
1047 return result;
1048 }
1049
1050 /* Open the file if a TLS or QUIC backend has not done this before. */
1051 Curl_tls_keylog_open();
1052 if(Curl_tls_keylog_enabled()) {
1053 gnutls_session_set_keylog_function(gctx->session, keylog_callback);
1054 }
1055
1056 /* convert the ALPN string from our arguments to a list of strings
1057 * that gnutls wants and will convert internally back to this very
1058 * string for sending to the server. nice. */
1059 if(alpn && alpn_len) {
1060 gnutls_datum_t alpns[5];
1061 size_t i, alen = alpn_len;
1062 unsigned char *s = (unsigned char *)alpn;
1063 unsigned char slen;
1064 for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
1065 slen = s[0];
1066 if(slen >= alen)
1067 return CURLE_FAILED_INIT;
1068 alpns[i].data = s + 1;
1069 alpns[i].size = slen;
1070 s += slen + 1;
1071 alen -= (size_t)slen + 1;
1072 }
1073 if(alen) /* not all alpn chars used, wrong format or too many */
1074 return CURLE_FAILED_INIT;
1075 if(i && gnutls_alpn_set_protocols(gctx->session,
1076 alpns, (unsigned int)i,
1077 GNUTLS_ALPN_MANDATORY)) {
1078 failf(data, "failed setting ALPN");
1079 return CURLE_SSL_CONNECT_ERROR;
1080 }
1081 }
1082
1083 /* This might be a reconnect, so we check for a session ID in the cache
1084 to speed up things */
1085 if(conn_config->sessionid) {
1086 void *ssl_sessionid;
1087 size_t ssl_idsize;
1088
1089 Curl_ssl_sessionid_lock(data);
1090 if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, &ssl_idsize)) {
1091 /* we got a session id, use it! */
1092 int rc;
1093
1094 rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
1095 if(rc < 0)
1096 infof(data, "SSL failed to set session ID");
1097 else
1098 infof(data, "SSL reusing session ID (size=%zu)", ssl_idsize);
1099 }
1100 Curl_ssl_sessionid_unlock(data);
1101 }
1102 return CURLE_OK;
1103 }
1104
1105 static CURLcode
gtls_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)1106 gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
1107 {
1108 struct ssl_connect_data *connssl = cf->ctx;
1109 struct gtls_ssl_backend_data *backend =
1110 (struct gtls_ssl_backend_data *)connssl->backend;
1111 struct alpn_proto_buf proto;
1112 CURLcode result;
1113
1114 DEBUGASSERT(backend);
1115 DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
1116
1117 if(connssl->state == ssl_connection_complete)
1118 /* to make us tolerant against being called more than once for the
1119 same connection */
1120 return CURLE_OK;
1121
1122 memset(&proto, 0, sizeof(proto));
1123 if(connssl->alpn) {
1124 result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
1125 if(result) {
1126 failf(data, "Error determining ALPN");
1127 return CURLE_SSL_CONNECT_ERROR;
1128 }
1129 }
1130
1131 result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
1132 proto.data, proto.len, NULL, NULL, cf);
1133 if(result)
1134 return result;
1135
1136 gnutls_handshake_set_hook_function(backend->gtls.session,
1137 GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
1138 gtls_handshake_cb);
1139
1140 /* register callback functions and handle to send and receive data. */
1141 gnutls_transport_set_ptr(backend->gtls.session, cf);
1142 gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
1143 gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
1144
1145 return CURLE_OK;
1146 }
1147
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)1148 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
1149 gnutls_x509_crt_t cert,
1150 const char *pinnedpubkey)
1151 {
1152 /* Scratch */
1153 size_t len1 = 0, len2 = 0;
1154 unsigned char *buff1 = NULL;
1155
1156 gnutls_pubkey_t key = NULL;
1157
1158 /* Result is returned to caller */
1159 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1160
1161 /* if a path wasn't specified, don't pin */
1162 if(!pinnedpubkey)
1163 return CURLE_OK;
1164
1165 if(!cert)
1166 return result;
1167
1168 do {
1169 int ret;
1170
1171 /* Begin Gyrations to get the public key */
1172 gnutls_pubkey_init(&key);
1173
1174 ret = gnutls_pubkey_import_x509(key, cert, 0);
1175 if(ret < 0)
1176 break; /* failed */
1177
1178 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
1179 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
1180 break; /* failed */
1181
1182 buff1 = malloc(len1);
1183 if(!buff1)
1184 break; /* failed */
1185
1186 len2 = len1;
1187
1188 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
1189 if(ret < 0 || len1 != len2)
1190 break; /* failed */
1191
1192 /* End Gyrations */
1193
1194 /* The one good exit point */
1195 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
1196 } while(0);
1197
1198 if(key)
1199 gnutls_pubkey_deinit(key);
1200
1201 Curl_safefree(buff1);
1202
1203 return result;
1204 }
1205
1206 CURLcode
Curl_gtls_verifyserver(struct Curl_easy * data,gnutls_session_t session,struct ssl_primary_config * config,struct ssl_config_data * ssl_config,struct ssl_peer * peer,const char * pinned_key)1207 Curl_gtls_verifyserver(struct Curl_easy *data,
1208 gnutls_session_t session,
1209 struct ssl_primary_config *config,
1210 struct ssl_config_data *ssl_config,
1211 struct ssl_peer *peer,
1212 const char *pinned_key)
1213 {
1214 unsigned int cert_list_size;
1215 const gnutls_datum_t *chainp;
1216 unsigned int verify_status = 0;
1217 gnutls_x509_crt_t x509_cert, x509_issuer;
1218 gnutls_datum_t issuerp;
1219 gnutls_datum_t certfields;
1220 char certname[65] = ""; /* limited to 64 chars by ASN.1 */
1221 size_t size;
1222 time_t certclock;
1223 int rc;
1224 CURLcode result = CURLE_OK;
1225 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1226 const char *ptr;
1227 int algo;
1228 unsigned int bits;
1229 gnutls_protocol_t version = gnutls_protocol_get_version(session);
1230 #endif
1231 long * const certverifyresult = &ssl_config->certverifyresult;
1232
1233 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1234 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
1235 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
1236 gnutls_cipher_get(session),
1237 gnutls_mac_get(session));
1238
1239 infof(data, "SSL connection using %s / %s",
1240 gnutls_protocol_get_name(version), ptr);
1241 #endif
1242
1243 /* This function will return the peer's raw certificate (chain) as sent by
1244 the peer. These certificates are in raw format (DER encoded for
1245 X.509). In case of a X.509 then a certificate list may be present. The
1246 first certificate in the list is the peer's certificate, following the
1247 issuer's certificate, then the issuer's issuer etc. */
1248
1249 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1250 if(!chainp) {
1251 if(config->verifypeer ||
1252 config->verifyhost ||
1253 config->issuercert) {
1254 #ifdef USE_GNUTLS_SRP
1255 if(ssl_config->primary.username && !config->verifypeer &&
1256 gnutls_cipher_get(session)) {
1257 /* no peer cert, but auth is ok if we have SRP user and cipher and no
1258 peer verify */
1259 }
1260 else {
1261 #endif
1262 failf(data, "failed to get server cert");
1263 *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
1264 return CURLE_PEER_FAILED_VERIFICATION;
1265 #ifdef USE_GNUTLS_SRP
1266 }
1267 #endif
1268 }
1269 infof(data, " common name: WARNING couldn't obtain");
1270 }
1271
1272 if(data->set.ssl.certinfo && chainp) {
1273 unsigned int i;
1274
1275 result = Curl_ssl_init_certinfo(data, (int)cert_list_size);
1276 if(result)
1277 return result;
1278
1279 for(i = 0; i < cert_list_size; i++) {
1280 const char *beg = (const char *) chainp[i].data;
1281 const char *end = beg + chainp[i].size;
1282
1283 result = Curl_extract_certinfo(data, (int)i, beg, end);
1284 if(result)
1285 return result;
1286 }
1287 }
1288
1289 if(config->verifypeer) {
1290 /* This function will try to verify the peer's certificate and return its
1291 status (trusted, invalid etc.). The value of status should be one or
1292 more of the gnutls_certificate_status_t enumerated elements bitwise
1293 or'd. To avoid denial of service attacks some default upper limits
1294 regarding the certificate key size and chain size are set. To override
1295 them use gnutls_certificate_set_verify_limits(). */
1296
1297 rc = gnutls_certificate_verify_peers2(session, &verify_status);
1298 if(rc < 0) {
1299 failf(data, "server cert verify failed: %d", rc);
1300 *certverifyresult = rc;
1301 return CURLE_SSL_CONNECT_ERROR;
1302 }
1303
1304 *certverifyresult = verify_status;
1305
1306 /* verify_status is a bitmask of gnutls_certificate_status bits */
1307 if(verify_status & GNUTLS_CERT_INVALID) {
1308 if(config->verifypeer) {
1309 failf(data, "server certificate verification failed. CAfile: %s "
1310 "CRLfile: %s", config->CAfile ? config->CAfile:
1311 "none",
1312 ssl_config->primary.CRLfile ?
1313 ssl_config->primary.CRLfile : "none");
1314 return CURLE_PEER_FAILED_VERIFICATION;
1315 }
1316 else
1317 infof(data, " server certificate verification FAILED");
1318 }
1319 else
1320 infof(data, " server certificate verification OK");
1321 }
1322 else
1323 infof(data, " server certificate verification SKIPPED");
1324
1325 if(config->verifystatus) {
1326 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
1327 gnutls_datum_t status_request;
1328 gnutls_ocsp_resp_t ocsp_resp;
1329
1330 gnutls_ocsp_cert_status_t status;
1331 gnutls_x509_crl_reason_t reason;
1332
1333 rc = gnutls_ocsp_status_request_get(session, &status_request);
1334
1335 infof(data, " server certificate status verification FAILED");
1336
1337 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1338 failf(data, "No OCSP response received");
1339 return CURLE_SSL_INVALIDCERTSTATUS;
1340 }
1341
1342 if(rc < 0) {
1343 failf(data, "Invalid OCSP response received");
1344 return CURLE_SSL_INVALIDCERTSTATUS;
1345 }
1346
1347 gnutls_ocsp_resp_init(&ocsp_resp);
1348
1349 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1350 if(rc < 0) {
1351 failf(data, "Invalid OCSP response received");
1352 return CURLE_SSL_INVALIDCERTSTATUS;
1353 }
1354
1355 (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1356 &status, NULL, NULL, NULL, &reason);
1357
1358 switch(status) {
1359 case GNUTLS_OCSP_CERT_GOOD:
1360 break;
1361
1362 case GNUTLS_OCSP_CERT_REVOKED: {
1363 const char *crl_reason;
1364
1365 switch(reason) {
1366 default:
1367 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1368 crl_reason = "unspecified reason";
1369 break;
1370
1371 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1372 crl_reason = "private key compromised";
1373 break;
1374
1375 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1376 crl_reason = "CA compromised";
1377 break;
1378
1379 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1380 crl_reason = "affiliation has changed";
1381 break;
1382
1383 case GNUTLS_X509_CRLREASON_SUPERSEDED:
1384 crl_reason = "certificate superseded";
1385 break;
1386
1387 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1388 crl_reason = "operation has ceased";
1389 break;
1390
1391 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1392 crl_reason = "certificate is on hold";
1393 break;
1394
1395 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1396 crl_reason = "will be removed from delta CRL";
1397 break;
1398
1399 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1400 crl_reason = "privilege withdrawn";
1401 break;
1402
1403 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1404 crl_reason = "AA compromised";
1405 break;
1406 }
1407
1408 failf(data, "Server certificate was revoked: %s", crl_reason);
1409 break;
1410 }
1411
1412 default:
1413 case GNUTLS_OCSP_CERT_UNKNOWN:
1414 failf(data, "Server certificate status is unknown");
1415 break;
1416 }
1417
1418 gnutls_ocsp_resp_deinit(ocsp_resp);
1419
1420 return CURLE_SSL_INVALIDCERTSTATUS;
1421 }
1422 else
1423 infof(data, " server certificate status verification OK");
1424 }
1425 else
1426 infof(data, " server certificate status verification SKIPPED");
1427
1428 /* initialize an X.509 certificate structure. */
1429 gnutls_x509_crt_init(&x509_cert);
1430
1431 if(chainp)
1432 /* convert the given DER or PEM encoded Certificate to the native
1433 gnutls_x509_crt_t format */
1434 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1435
1436 if(config->issuercert) {
1437 gnutls_x509_crt_init(&x509_issuer);
1438 issuerp = load_file(config->issuercert);
1439 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1440 rc = (int)gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1441 gnutls_x509_crt_deinit(x509_issuer);
1442 unload_file(issuerp);
1443 if(rc <= 0) {
1444 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1445 config->issuercert?config->issuercert:"none");
1446 gnutls_x509_crt_deinit(x509_cert);
1447 return CURLE_SSL_ISSUER_ERROR;
1448 }
1449 infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
1450 config->issuercert?config->issuercert:"none");
1451 }
1452
1453 size = sizeof(certname);
1454 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1455 0, /* the first and only one */
1456 FALSE,
1457 certname,
1458 &size);
1459 if(rc) {
1460 infof(data, "error fetching CN from cert:%s",
1461 gnutls_strerror(rc));
1462 }
1463
1464 /* This function will check if the given certificate's subject matches the
1465 given hostname. This is a basic implementation of the matching described
1466 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1467 alternative name PKIX extension. Returns non zero on success, and zero on
1468 failure. */
1469 rc = (int)gnutls_x509_crt_check_hostname(x509_cert, peer->hostname);
1470 #if GNUTLS_VERSION_NUMBER < 0x030306
1471 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1472 addresses. */
1473 if(!rc) {
1474 #ifdef USE_IPV6
1475 #define use_addr in6_addr
1476 #else
1477 #define use_addr in_addr
1478 #endif
1479 unsigned char addrbuf[sizeof(struct use_addr)];
1480 size_t addrlen = 0;
1481
1482 if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
1483 addrlen = 4;
1484 #ifdef USE_IPV6
1485 else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
1486 addrlen = 16;
1487 #endif
1488
1489 if(addrlen) {
1490 unsigned char certaddr[sizeof(struct use_addr)];
1491 int i;
1492
1493 for(i = 0; ; i++) {
1494 size_t certaddrlen = sizeof(certaddr);
1495 int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1496 &certaddrlen, NULL);
1497 /* If this happens, it wasn't an IP address. */
1498 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1499 continue;
1500 if(ret < 0)
1501 break;
1502 if(ret != GNUTLS_SAN_IPADDRESS)
1503 continue;
1504 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1505 rc = 1;
1506 break;
1507 }
1508 }
1509 }
1510 }
1511 #endif
1512 if(!rc) {
1513 if(config->verifyhost) {
1514 failf(data, "SSL: certificate subject name (%s) does not match "
1515 "target host name '%s'", certname, peer->dispname);
1516 gnutls_x509_crt_deinit(x509_cert);
1517 return CURLE_PEER_FAILED_VERIFICATION;
1518 }
1519 else
1520 infof(data, " common name: %s (does not match '%s')",
1521 certname, peer->dispname);
1522 }
1523 else
1524 infof(data, " common name: %s (matched)", certname);
1525
1526 /* Check for time-based validity */
1527 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1528
1529 if(certclock == (time_t)-1) {
1530 if(config->verifypeer) {
1531 failf(data, "server cert expiration date verify failed");
1532 *certverifyresult = GNUTLS_CERT_EXPIRED;
1533 gnutls_x509_crt_deinit(x509_cert);
1534 return CURLE_SSL_CONNECT_ERROR;
1535 }
1536 else
1537 infof(data, " server certificate expiration date verify FAILED");
1538 }
1539 else {
1540 if(certclock < time(NULL)) {
1541 if(config->verifypeer) {
1542 failf(data, "server certificate expiration date has passed.");
1543 *certverifyresult = GNUTLS_CERT_EXPIRED;
1544 gnutls_x509_crt_deinit(x509_cert);
1545 return CURLE_PEER_FAILED_VERIFICATION;
1546 }
1547 else
1548 infof(data, " server certificate expiration date FAILED");
1549 }
1550 else
1551 infof(data, " server certificate expiration date OK");
1552 }
1553
1554 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1555
1556 if(certclock == (time_t)-1) {
1557 if(config->verifypeer) {
1558 failf(data, "server cert activation date verify failed");
1559 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1560 gnutls_x509_crt_deinit(x509_cert);
1561 return CURLE_SSL_CONNECT_ERROR;
1562 }
1563 else
1564 infof(data, " server certificate activation date verify FAILED");
1565 }
1566 else {
1567 if(certclock > time(NULL)) {
1568 if(config->verifypeer) {
1569 failf(data, "server certificate not activated yet.");
1570 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1571 gnutls_x509_crt_deinit(x509_cert);
1572 return CURLE_PEER_FAILED_VERIFICATION;
1573 }
1574 else
1575 infof(data, " server certificate activation date FAILED");
1576 }
1577 else
1578 infof(data, " server certificate activation date OK");
1579 }
1580
1581 if(pinned_key) {
1582 result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
1583 if(result != CURLE_OK) {
1584 failf(data, "SSL: public key does not match pinned public key");
1585 gnutls_x509_crt_deinit(x509_cert);
1586 return result;
1587 }
1588 }
1589
1590 /* Show:
1591
1592 - subject
1593 - start date
1594 - expire date
1595 - common name
1596 - issuer
1597
1598 */
1599
1600 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1601 /* public key algorithm's parameters */
1602 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1603 infof(data, " certificate public key: %s",
1604 gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo));
1605
1606 /* version of the X.509 certificate. */
1607 infof(data, " certificate version: #%d",
1608 gnutls_x509_crt_get_version(x509_cert));
1609
1610
1611 rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1612 if(rc)
1613 infof(data, "Failed to get certificate name");
1614 else {
1615 infof(data, " subject: %s", certfields.data);
1616
1617 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1618 showtime(data, "start date", certclock);
1619
1620 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1621 showtime(data, "expire date", certclock);
1622
1623 gnutls_free(certfields.data);
1624 }
1625
1626 rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1627 if(rc)
1628 infof(data, "Failed to get certificate issuer");
1629 else {
1630 infof(data, " issuer: %s", certfields.data);
1631
1632 gnutls_free(certfields.data);
1633 }
1634 #endif
1635
1636 gnutls_x509_crt_deinit(x509_cert);
1637
1638 return result;
1639 }
1640
gtls_verifyserver(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)1641 static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
1642 struct Curl_easy *data,
1643 gnutls_session_t session)
1644 {
1645 struct ssl_connect_data *connssl = cf->ctx;
1646 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1647 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1648 #ifndef CURL_DISABLE_PROXY
1649 const char *pinned_key = Curl_ssl_cf_is_proxy(cf)?
1650 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
1651 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1652 #else
1653 const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1654 #endif
1655 CURLcode result;
1656
1657 result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
1658 &connssl->peer, pinned_key);
1659 if(result)
1660 goto out;
1661
1662 if(connssl->alpn) {
1663 gnutls_datum_t proto;
1664 int rc;
1665
1666 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1667 if(rc == 0)
1668 Curl_alpn_set_negotiated(cf, data, proto.data, proto.size);
1669 else
1670 Curl_alpn_set_negotiated(cf, data, NULL, 0);
1671 }
1672
1673 /* Only on TLSv1.2 or lower do we have the session id now. For
1674 * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
1675 if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
1676 result = gtls_update_session_id(cf, data, session);
1677
1678 out:
1679 return result;
1680 }
1681
1682 /*
1683 * This function is called after the TCP connect has completed. Setup the TLS
1684 * layer and do all necessary magic.
1685 */
1686 /* We use connssl->connecting_state to keep track of the connection status;
1687 there are three states: 'ssl_connect_1' (not started yet or complete),
1688 'ssl_connect_2' (doing handshake with the server), and
1689 'ssl_connect_3' (verifying and getting stats).
1690 */
1691 static CURLcode
gtls_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1692 gtls_connect_common(struct Curl_cfilter *cf,
1693 struct Curl_easy *data,
1694 bool nonblocking,
1695 bool *done)
1696 {
1697 struct ssl_connect_data *connssl = cf->ctx;
1698 CURLcode rc;
1699 CURLcode result = CURLE_OK;
1700
1701 /* Initiate the connection, if not already done */
1702 if(ssl_connect_1 == connssl->connecting_state) {
1703 rc = gtls_connect_step1(cf, data);
1704 if(rc) {
1705 result = rc;
1706 goto out;
1707 }
1708 }
1709
1710 rc = handshake(cf, data, TRUE, nonblocking);
1711 if(rc) {
1712 /* handshake() sets its own error message with failf() */
1713 result = rc;
1714 goto out;
1715 }
1716
1717 /* Finish connecting once the handshake is done */
1718 if(ssl_connect_1 == connssl->connecting_state) {
1719 struct gtls_ssl_backend_data *backend =
1720 (struct gtls_ssl_backend_data *)connssl->backend;
1721 gnutls_session_t session;
1722 DEBUGASSERT(backend);
1723 session = backend->gtls.session;
1724 rc = gtls_verifyserver(cf, data, session);
1725 if(rc) {
1726 result = rc;
1727 goto out;
1728 }
1729 connssl->state = ssl_connection_complete;
1730 }
1731
1732 out:
1733 *done = ssl_connect_1 == connssl->connecting_state;
1734
1735 return result;
1736 }
1737
gtls_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1738 static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
1739 struct Curl_easy *data,
1740 bool *done)
1741 {
1742 return gtls_connect_common(cf, data, TRUE, done);
1743 }
1744
gtls_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1745 static CURLcode gtls_connect(struct Curl_cfilter *cf,
1746 struct Curl_easy *data)
1747 {
1748 CURLcode result;
1749 bool done = FALSE;
1750
1751 result = gtls_connect_common(cf, data, FALSE, &done);
1752 if(result)
1753 return result;
1754
1755 DEBUGASSERT(done);
1756
1757 return CURLE_OK;
1758 }
1759
gtls_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1760 static bool gtls_data_pending(struct Curl_cfilter *cf,
1761 const struct Curl_easy *data)
1762 {
1763 struct ssl_connect_data *ctx = cf->ctx;
1764 struct gtls_ssl_backend_data *backend;
1765
1766 (void)data;
1767 DEBUGASSERT(ctx && ctx->backend);
1768 backend = (struct gtls_ssl_backend_data *)ctx->backend;
1769 if(backend->gtls.session &&
1770 0 != gnutls_record_check_pending(backend->gtls.session))
1771 return TRUE;
1772 return FALSE;
1773 }
1774
gtls_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * mem,size_t len,CURLcode * curlcode)1775 static ssize_t gtls_send(struct Curl_cfilter *cf,
1776 struct Curl_easy *data,
1777 const void *mem,
1778 size_t len,
1779 CURLcode *curlcode)
1780 {
1781 struct ssl_connect_data *connssl = cf->ctx;
1782 struct gtls_ssl_backend_data *backend =
1783 (struct gtls_ssl_backend_data *)connssl->backend;
1784 ssize_t rc;
1785
1786 (void)data;
1787 DEBUGASSERT(backend);
1788 backend->gtls.io_result = CURLE_OK;
1789 rc = gnutls_record_send(backend->gtls.session, mem, len);
1790
1791 if(rc < 0) {
1792 *curlcode = (rc == GNUTLS_E_AGAIN)?
1793 CURLE_AGAIN :
1794 (backend->gtls.io_result? backend->gtls.io_result : CURLE_SEND_ERROR);
1795
1796 rc = -1;
1797 }
1798
1799 return rc;
1800 }
1801
gtls_close(struct Curl_cfilter * cf,struct Curl_easy * data)1802 static void gtls_close(struct Curl_cfilter *cf,
1803 struct Curl_easy *data)
1804 {
1805 struct ssl_connect_data *connssl = cf->ctx;
1806 struct gtls_ssl_backend_data *backend =
1807 (struct gtls_ssl_backend_data *)connssl->backend;
1808
1809 (void) data;
1810 DEBUGASSERT(backend);
1811 CURL_TRC_CF(data, cf, "close");
1812 if(backend->gtls.session) {
1813 char buf[32];
1814 /* Maybe the server has already sent a close notify alert.
1815 Read it to avoid an RST on the TCP connection. */
1816 CURL_TRC_CF(data, cf, "close, try receive before bye");
1817 (void)gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
1818 CURL_TRC_CF(data, cf, "close, send bye");
1819 gnutls_bye(backend->gtls.session, GNUTLS_SHUT_RDWR);
1820 /* try one last receive */
1821 CURL_TRC_CF(data, cf, "close, receive after bye");
1822 (void)gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
1823 gnutls_deinit(backend->gtls.session);
1824 backend->gtls.session = NULL;
1825 }
1826 if(backend->gtls.shared_creds) {
1827 Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
1828 }
1829 #ifdef USE_GNUTLS_SRP
1830 if(backend->gtls.srp_client_cred) {
1831 gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1832 backend->gtls.srp_client_cred = NULL;
1833 }
1834 #endif
1835 }
1836
1837 /*
1838 * This function is called to shut down the SSL layer but keep the
1839 * socket open (CCC - Clear Command Channel)
1840 */
gtls_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data)1841 static int gtls_shutdown(struct Curl_cfilter *cf,
1842 struct Curl_easy *data)
1843 {
1844 struct ssl_connect_data *connssl = cf->ctx;
1845 struct gtls_ssl_backend_data *backend =
1846 (struct gtls_ssl_backend_data *)connssl->backend;
1847 int retval = 0;
1848
1849 DEBUGASSERT(backend);
1850
1851 #ifndef CURL_DISABLE_FTP
1852 /* This has only been tested on the proftpd server, and the mod_tls code
1853 sends a close notify alert without waiting for a close notify alert in
1854 response. Thus we wait for a close notify alert from the server, but
1855 we do not send one. Let's hope other servers do the same... */
1856
1857 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1858 gnutls_bye(backend->gtls.session, GNUTLS_SHUT_WR);
1859 #endif
1860
1861 if(backend->gtls.session) {
1862 ssize_t result;
1863 bool done = FALSE;
1864 char buf[120];
1865
1866 while(!done && !connssl->peer_closed) {
1867 int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
1868 SSL_SHUTDOWN_TIMEOUT);
1869 if(what > 0) {
1870 /* Something to read, let's do it and hope that it is the close
1871 notify alert from the server */
1872 result = gnutls_record_recv(backend->gtls.session,
1873 buf, sizeof(buf));
1874 switch(result) {
1875 case 0:
1876 /* This is the expected response. There was no data but only
1877 the close notify alert */
1878 done = TRUE;
1879 break;
1880 case GNUTLS_E_AGAIN:
1881 case GNUTLS_E_INTERRUPTED:
1882 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED");
1883 break;
1884 default:
1885 retval = -1;
1886 done = TRUE;
1887 break;
1888 }
1889 }
1890 else if(0 == what) {
1891 /* timeout */
1892 failf(data, "SSL shutdown timeout");
1893 done = TRUE;
1894 }
1895 else {
1896 /* anything that gets here is fatally bad */
1897 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1898 retval = -1;
1899 done = TRUE;
1900 }
1901 }
1902 gnutls_deinit(backend->gtls.session);
1903 }
1904
1905 #ifdef USE_GNUTLS_SRP
1906 {
1907 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1908 if(ssl_config->primary.username)
1909 gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1910 }
1911 #endif
1912
1913 backend->gtls.session = NULL;
1914 Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
1915
1916 return retval;
1917 }
1918
gtls_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t buffersize,CURLcode * curlcode)1919 static ssize_t gtls_recv(struct Curl_cfilter *cf,
1920 struct Curl_easy *data,
1921 char *buf,
1922 size_t buffersize,
1923 CURLcode *curlcode)
1924 {
1925 struct ssl_connect_data *connssl = cf->ctx;
1926 struct gtls_ssl_backend_data *backend =
1927 (struct gtls_ssl_backend_data *)connssl->backend;
1928 ssize_t ret;
1929
1930 (void)data;
1931 DEBUGASSERT(backend);
1932
1933 backend->gtls.io_result = CURLE_OK;
1934 ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
1935 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1936 *curlcode = CURLE_AGAIN;
1937 ret = -1;
1938 goto out;
1939 }
1940
1941 if(ret == GNUTLS_E_REHANDSHAKE) {
1942 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1943 proper way" takes a whole lot of work. */
1944 CURLcode result = handshake(cf, data, FALSE, FALSE);
1945 if(result)
1946 /* handshake() writes error message on its own */
1947 *curlcode = result;
1948 else
1949 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1950 ret = -1;
1951 goto out;
1952 }
1953
1954 if(ret < 0) {
1955 failf(data, "GnuTLS recv error (%d): %s",
1956
1957 (int)ret, gnutls_strerror((int)ret));
1958 *curlcode = backend->gtls.io_result?
1959 backend->gtls.io_result : CURLE_RECV_ERROR;
1960 ret = -1;
1961 goto out;
1962 }
1963
1964 out:
1965 return ret;
1966 }
1967
gtls_version(char * buffer,size_t size)1968 static size_t gtls_version(char *buffer, size_t size)
1969 {
1970 return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1971 }
1972
1973 /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1974 static CURLcode gtls_random(struct Curl_easy *data,
1975 unsigned char *entropy, size_t length)
1976 {
1977 int rc;
1978 (void)data;
1979 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1980 return rc?CURLE_FAILED_INIT:CURLE_OK;
1981 }
1982
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)1983 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1984 size_t tmplen,
1985 unsigned char *sha256sum, /* output */
1986 size_t sha256len)
1987 {
1988 struct sha256_ctx SHA256pw;
1989 sha256_init(&SHA256pw);
1990 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1991 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1992 return CURLE_OK;
1993 }
1994
gtls_cert_status_request(void)1995 static bool gtls_cert_status_request(void)
1996 {
1997 return TRUE;
1998 }
1999
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)2000 static void *gtls_get_internals(struct ssl_connect_data *connssl,
2001 CURLINFO info UNUSED_PARAM)
2002 {
2003 struct gtls_ssl_backend_data *backend =
2004 (struct gtls_ssl_backend_data *)connssl->backend;
2005 (void)info;
2006 DEBUGASSERT(backend);
2007 return backend->gtls.session;
2008 }
2009
2010 const struct Curl_ssl Curl_ssl_gnutls = {
2011 { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
2012
2013 SSLSUPP_CA_PATH |
2014 SSLSUPP_CERTINFO |
2015 SSLSUPP_PINNEDPUBKEY |
2016 SSLSUPP_HTTPS_PROXY |
2017 SSLSUPP_CA_CACHE,
2018
2019 sizeof(struct gtls_ssl_backend_data),
2020
2021 gtls_init, /* init */
2022 gtls_cleanup, /* cleanup */
2023 gtls_version, /* version */
2024 Curl_none_check_cxn, /* check_cxn */
2025 gtls_shutdown, /* shutdown */
2026 gtls_data_pending, /* data_pending */
2027 gtls_random, /* random */
2028 gtls_cert_status_request, /* cert_status_request */
2029 gtls_connect, /* connect */
2030 gtls_connect_nonblocking, /* connect_nonblocking */
2031 Curl_ssl_adjust_pollset, /* adjust_pollset */
2032 gtls_get_internals, /* get_internals */
2033 gtls_close, /* close_one */
2034 Curl_none_close_all, /* close_all */
2035 Curl_none_set_engine, /* set_engine */
2036 Curl_none_set_engine_default, /* set_engine_default */
2037 Curl_none_engines_list, /* engines_list */
2038 Curl_none_false_start, /* false_start */
2039 gtls_sha256sum, /* sha256sum */
2040 NULL, /* associate_connection */
2041 NULL, /* disassociate_connection */
2042 gtls_recv, /* recv decrypted data */
2043 gtls_send, /* send data to encrypt */
2044 };
2045
2046 #endif /* USE_GNUTLS */
2047