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: do not 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, FALSE, &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 is 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
gnutls_do_file_type(const char * type)353 static gnutls_x509_crt_fmt_t gnutls_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
gnutls_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 gnutls_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 does not 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.cache_session) {
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 /* extract session ID to the allocated buffer */
746 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
747
748 CURL_TRC_CF(data, cf, "get session id (len=%zu) and store in cache",
749 connect_idsize);
750 Curl_ssl_sessionid_lock(data);
751 /* store this session id, takes ownership */
752 result = Curl_ssl_set_sessionid(cf, data, &connssl->peer,
753 connect_sessionid, connect_idsize,
754 gtls_sessionid_free);
755 Curl_ssl_sessionid_unlock(data);
756 }
757 }
758 return result;
759 }
760
gtls_handshake_cb(gnutls_session_t session,unsigned int htype,unsigned when,unsigned int incoming,const gnutls_datum_t * msg)761 static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
762 unsigned when, unsigned int incoming,
763 const gnutls_datum_t *msg)
764 {
765 struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
766
767 (void)msg;
768 (void)incoming;
769 if(when) { /* after message has been processed */
770 struct Curl_easy *data = CF_DATA_CURRENT(cf);
771 if(data) {
772 CURL_TRC_CF(data, cf, "handshake: %s message type %d",
773 incoming ? "incoming" : "outgoing", htype);
774 switch(htype) {
775 case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
776 gtls_update_session_id(cf, data, session);
777 break;
778 }
779 default:
780 break;
781 }
782 }
783 }
784 return 0;
785 }
786
gtls_client_init(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,struct gtls_ctx * gtls)787 static CURLcode gtls_client_init(struct Curl_cfilter *cf,
788 struct Curl_easy *data,
789 struct ssl_peer *peer,
790 struct gtls_ctx *gtls)
791 {
792 struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
793 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
794 unsigned int init_flags;
795 int rc;
796 bool sni = TRUE; /* default is SNI enabled */
797 const char *prioritylist;
798 const char *err = NULL;
799 const char *tls13support;
800 CURLcode result;
801
802 if(!gtls_inited)
803 gtls_init();
804
805 if(config->version == CURL_SSLVERSION_SSLv2) {
806 failf(data, "GnuTLS does not support SSLv2");
807 return CURLE_SSL_CONNECT_ERROR;
808 }
809 else if(config->version == CURL_SSLVERSION_SSLv3)
810 sni = FALSE; /* SSLv3 has no SNI */
811
812 /* allocate a shared creds struct */
813 result = Curl_gtls_shared_creds_create(data, >ls->shared_creds);
814 if(result)
815 return result;
816
817 #ifdef USE_GNUTLS_SRP
818 if(config->username && Curl_auth_allowed_to_host(data)) {
819 infof(data, "Using TLS-SRP username: %s", config->username);
820
821 rc = gnutls_srp_allocate_client_credentials(>ls->srp_client_cred);
822 if(rc != GNUTLS_E_SUCCESS) {
823 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
824 gnutls_strerror(rc));
825 return CURLE_OUT_OF_MEMORY;
826 }
827
828 rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
829 config->username,
830 config->password);
831 if(rc != GNUTLS_E_SUCCESS) {
832 failf(data, "gnutls_srp_set_client_cred() failed: %s",
833 gnutls_strerror(rc));
834 return CURLE_BAD_FUNCTION_ARGUMENT;
835 }
836 }
837 #endif
838
839 ssl_config->certverifyresult = 0;
840
841 /* Initialize TLS session as a client */
842 init_flags = GNUTLS_CLIENT;
843
844 #if defined(GNUTLS_FORCE_CLIENT_CERT)
845 init_flags |= GNUTLS_FORCE_CLIENT_CERT;
846 #endif
847
848 #if defined(GNUTLS_NO_TICKETS)
849 /* Disable TLS session tickets */
850 init_flags |= GNUTLS_NO_TICKETS;
851 #endif
852
853 #if defined(GNUTLS_NO_STATUS_REQUEST)
854 if(!config->verifystatus)
855 /* Disable the "status_request" TLS extension, enabled by default since
856 GnuTLS 3.8.0. */
857 init_flags |= GNUTLS_NO_STATUS_REQUEST;
858 #endif
859
860 rc = gnutls_init(>ls->session, init_flags);
861 if(rc != GNUTLS_E_SUCCESS) {
862 failf(data, "gnutls_init() failed: %d", rc);
863 return CURLE_SSL_CONNECT_ERROR;
864 }
865
866 if(sni && peer->sni) {
867 if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
868 peer->sni, strlen(peer->sni)) < 0) {
869 failf(data, "Failed to set SNI");
870 return CURLE_SSL_CONNECT_ERROR;
871 }
872 }
873
874 /* Use default priorities */
875 rc = gnutls_set_default_priority(gtls->session);
876 if(rc != GNUTLS_E_SUCCESS)
877 return CURLE_SSL_CONNECT_ERROR;
878
879 /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
880 tls13support = gnutls_check_version("3.6.5");
881
882 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
883 * removed if a runtime error indicates that SRP is not supported by this
884 * GnuTLS version */
885
886 if(config->version == CURL_SSLVERSION_SSLv2 ||
887 config->version == CURL_SSLVERSION_SSLv3) {
888 failf(data, "GnuTLS does not support SSLv2 or SSLv3");
889 return CURLE_SSL_CONNECT_ERROR;
890 }
891
892 if(config->version == CURL_SSLVERSION_TLSv1_3) {
893 if(!tls13support) {
894 failf(data, "This GnuTLS installation does not support TLS 1.3");
895 return CURLE_SSL_CONNECT_ERROR;
896 }
897 }
898
899 /* At this point we know we have a supported TLS version, so set it */
900 result = gnutls_set_ssl_version_min_max(data, peer,
901 config, &prioritylist, tls13support);
902 if(result)
903 return result;
904
905 #ifdef USE_GNUTLS_SRP
906 /* Only add SRP to the cipher list if SRP is requested. Otherwise
907 * GnuTLS will disable TLS 1.3 support. */
908 if(config->username) {
909 char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
910 if(!prioritysrp)
911 return CURLE_OUT_OF_MEMORY;
912 rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
913 free(prioritysrp);
914
915 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
916 infof(data, "This GnuTLS does not support SRP");
917 }
918 }
919 else {
920 #endif
921 infof(data, "GnuTLS ciphers: %s", prioritylist);
922 rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
923 #ifdef USE_GNUTLS_SRP
924 }
925 #endif
926
927 if(rc != GNUTLS_E_SUCCESS) {
928 failf(data, "Error %d setting GnuTLS cipher list starting with %s",
929 rc, err);
930 return CURLE_SSL_CONNECT_ERROR;
931 }
932
933 if(config->clientcert) {
934 if(!gtls->shared_creds->trust_setup) {
935 result = Curl_gtls_client_trust_setup(cf, data, gtls);
936 if(result)
937 return result;
938 }
939 if(ssl_config->cert_type && strcasecompare(ssl_config->cert_type, "P12")) {
940 rc = gnutls_certificate_set_x509_simple_pkcs12_file(
941 gtls->shared_creds->creds, config->clientcert, GNUTLS_X509_FMT_DER,
942 ssl_config->key_passwd ? ssl_config->key_passwd : "");
943 if(rc != GNUTLS_E_SUCCESS) {
944 failf(data,
945 "error reading X.509 potentially-encrypted key or certificate "
946 "file: %s",
947 gnutls_strerror(rc));
948 return CURLE_SSL_CONNECT_ERROR;
949 }
950 }
951 else if(ssl_config->key_passwd) {
952 const unsigned int supported_key_encryption_algorithms =
953 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
954 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
955 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
956 GNUTLS_PKCS_USE_PBES2_AES_256;
957 rc = gnutls_certificate_set_x509_key_file2(
958 gtls->shared_creds->creds,
959 config->clientcert,
960 ssl_config->key ? ssl_config->key : config->clientcert,
961 gnutls_do_file_type(ssl_config->cert_type),
962 ssl_config->key_passwd,
963 supported_key_encryption_algorithms);
964 if(rc != GNUTLS_E_SUCCESS) {
965 failf(data,
966 "error reading X.509 potentially-encrypted key file: %s",
967 gnutls_strerror(rc));
968 return CURLE_SSL_CONNECT_ERROR;
969 }
970 }
971 else {
972 if(gnutls_certificate_set_x509_key_file(
973 gtls->shared_creds->creds,
974 config->clientcert,
975 ssl_config->key ? ssl_config->key : config->clientcert,
976 gnutls_do_file_type(ssl_config->cert_type) ) !=
977 GNUTLS_E_SUCCESS) {
978 failf(data, "error reading X.509 key or certificate file");
979 return CURLE_SSL_CONNECT_ERROR;
980 }
981 }
982 }
983
984 #ifdef USE_GNUTLS_SRP
985 /* put the credentials to the current session */
986 if(config->username) {
987 rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
988 gtls->srp_client_cred);
989 if(rc != GNUTLS_E_SUCCESS) {
990 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
991 return CURLE_SSL_CONNECT_ERROR;
992 }
993 }
994 else
995 #endif
996 {
997 rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
998 gtls->shared_creds->creds);
999 if(rc != GNUTLS_E_SUCCESS) {
1000 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
1001 return CURLE_SSL_CONNECT_ERROR;
1002 }
1003 }
1004
1005 if(config->verifystatus) {
1006 rc = gnutls_ocsp_status_request_enable_client(gtls->session,
1007 NULL, 0, NULL);
1008 if(rc != GNUTLS_E_SUCCESS) {
1009 failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
1010 return CURLE_SSL_CONNECT_ERROR;
1011 }
1012 }
1013
1014 return CURLE_OK;
1015 }
1016
keylog_callback(gnutls_session_t session,const char * label,const gnutls_datum_t * secret)1017 static int keylog_callback(gnutls_session_t session, const char *label,
1018 const gnutls_datum_t *secret)
1019 {
1020 gnutls_datum_t crandom;
1021 gnutls_datum_t srandom;
1022
1023 gnutls_session_get_random(session, &crandom, &srandom);
1024 if(crandom.size != 32) {
1025 return -1;
1026 }
1027
1028 Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
1029 return 0;
1030 }
1031
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)1032 CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
1033 struct Curl_cfilter *cf,
1034 struct Curl_easy *data,
1035 struct ssl_peer *peer,
1036 const unsigned char *alpn, size_t alpn_len,
1037 Curl_gtls_ctx_setup_cb *cb_setup,
1038 void *cb_user_data,
1039 void *ssl_user_data)
1040 {
1041 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1042 CURLcode result;
1043
1044 DEBUGASSERT(gctx);
1045
1046 result = gtls_client_init(cf, data, peer, gctx);
1047 if(result)
1048 return result;
1049
1050 gnutls_session_set_ptr(gctx->session, ssl_user_data);
1051
1052 if(cb_setup) {
1053 result = cb_setup(cf, data, cb_user_data);
1054 if(result)
1055 return result;
1056 }
1057
1058 /* Open the file if a TLS or QUIC backend has not done this before. */
1059 Curl_tls_keylog_open();
1060 if(Curl_tls_keylog_enabled()) {
1061 gnutls_session_set_keylog_function(gctx->session, keylog_callback);
1062 }
1063
1064 /* convert the ALPN string from our arguments to a list of strings
1065 * that gnutls wants and will convert internally back to this very
1066 * string for sending to the server. nice. */
1067 if(alpn && alpn_len) {
1068 gnutls_datum_t alpns[5];
1069 size_t i, alen = alpn_len;
1070 unsigned char *s = (unsigned char *)alpn;
1071 unsigned char slen;
1072 for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
1073 slen = s[0];
1074 if(slen >= alen)
1075 return CURLE_FAILED_INIT;
1076 alpns[i].data = s + 1;
1077 alpns[i].size = slen;
1078 s += slen + 1;
1079 alen -= (size_t)slen + 1;
1080 }
1081 if(alen) /* not all alpn chars used, wrong format or too many */
1082 return CURLE_FAILED_INIT;
1083 if(i && gnutls_alpn_set_protocols(gctx->session,
1084 alpns, (unsigned int)i,
1085 GNUTLS_ALPN_MANDATORY)) {
1086 failf(data, "failed setting ALPN");
1087 return CURLE_SSL_CONNECT_ERROR;
1088 }
1089 }
1090
1091 /* This might be a reconnect, so we check for a session ID in the cache
1092 to speed up things */
1093 if(conn_config->cache_session) {
1094 void *ssl_sessionid;
1095 size_t ssl_idsize;
1096
1097 Curl_ssl_sessionid_lock(data);
1098 if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, &ssl_idsize)) {
1099 /* we got a session id, use it! */
1100 int rc;
1101
1102 rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
1103 if(rc < 0)
1104 infof(data, "SSL failed to set session ID");
1105 else
1106 infof(data, "SSL reusing session ID (size=%zu)", ssl_idsize);
1107 }
1108 Curl_ssl_sessionid_unlock(data);
1109 }
1110 return CURLE_OK;
1111 }
1112
1113 static CURLcode
gtls_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)1114 gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
1115 {
1116 struct ssl_connect_data *connssl = cf->ctx;
1117 struct gtls_ssl_backend_data *backend =
1118 (struct gtls_ssl_backend_data *)connssl->backend;
1119 struct alpn_proto_buf proto;
1120 CURLcode result;
1121
1122 DEBUGASSERT(backend);
1123 DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
1124
1125 if(connssl->state == ssl_connection_complete)
1126 /* to make us tolerant against being called more than once for the
1127 same connection */
1128 return CURLE_OK;
1129
1130 memset(&proto, 0, sizeof(proto));
1131 if(connssl->alpn) {
1132 result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
1133 if(result) {
1134 failf(data, "Error determining ALPN");
1135 return CURLE_SSL_CONNECT_ERROR;
1136 }
1137 }
1138
1139 result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
1140 proto.data, proto.len, NULL, NULL, cf);
1141 if(result)
1142 return result;
1143
1144 gnutls_handshake_set_hook_function(backend->gtls.session,
1145 GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
1146 gtls_handshake_cb);
1147
1148 /* register callback functions and handle to send and receive data. */
1149 gnutls_transport_set_ptr(backend->gtls.session, cf);
1150 gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
1151 gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
1152
1153 return CURLE_OK;
1154 }
1155
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)1156 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
1157 gnutls_x509_crt_t cert,
1158 const char *pinnedpubkey)
1159 {
1160 /* Scratch */
1161 size_t len1 = 0, len2 = 0;
1162 unsigned char *buff1 = NULL;
1163
1164 gnutls_pubkey_t key = NULL;
1165
1166 /* Result is returned to caller */
1167 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1168
1169 /* if a path was not specified, do not pin */
1170 if(!pinnedpubkey)
1171 return CURLE_OK;
1172
1173 if(!cert)
1174 return result;
1175
1176 do {
1177 int ret;
1178
1179 /* Begin Gyrations to get the public key */
1180 gnutls_pubkey_init(&key);
1181
1182 ret = gnutls_pubkey_import_x509(key, cert, 0);
1183 if(ret < 0)
1184 break; /* failed */
1185
1186 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
1187 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
1188 break; /* failed */
1189
1190 buff1 = malloc(len1);
1191 if(!buff1)
1192 break; /* failed */
1193
1194 len2 = len1;
1195
1196 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
1197 if(ret < 0 || len1 != len2)
1198 break; /* failed */
1199
1200 /* End Gyrations */
1201
1202 /* The one good exit point */
1203 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
1204 } while(0);
1205
1206 if(key)
1207 gnutls_pubkey_deinit(key);
1208
1209 Curl_safefree(buff1);
1210
1211 return result;
1212 }
1213
1214 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)1215 Curl_gtls_verifyserver(struct Curl_easy *data,
1216 gnutls_session_t session,
1217 struct ssl_primary_config *config,
1218 struct ssl_config_data *ssl_config,
1219 struct ssl_peer *peer,
1220 const char *pinned_key)
1221 {
1222 unsigned int cert_list_size;
1223 const gnutls_datum_t *chainp;
1224 unsigned int verify_status = 0;
1225 gnutls_x509_crt_t x509_cert, x509_issuer;
1226 gnutls_datum_t issuerp;
1227 gnutls_datum_t certfields;
1228 char certname[65] = ""; /* limited to 64 chars by ASN.1 */
1229 size_t size;
1230 time_t certclock;
1231 int rc;
1232 CURLcode result = CURLE_OK;
1233 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1234 const char *ptr;
1235 int algo;
1236 unsigned int bits;
1237 gnutls_protocol_t version = gnutls_protocol_get_version(session);
1238 #endif
1239 long * const certverifyresult = &ssl_config->certverifyresult;
1240
1241 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1242 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
1243 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
1244 gnutls_cipher_get(session),
1245 gnutls_mac_get(session));
1246
1247 infof(data, "SSL connection using %s / %s",
1248 gnutls_protocol_get_name(version), ptr);
1249 #endif
1250
1251 /* This function will return the peer's raw certificate (chain) as sent by
1252 the peer. These certificates are in raw format (DER encoded for
1253 X.509). In case of a X.509 then a certificate list may be present. The
1254 first certificate in the list is the peer's certificate, following the
1255 issuer's certificate, then the issuer's issuer etc. */
1256
1257 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1258 if(!chainp) {
1259 if(config->verifypeer ||
1260 config->verifyhost ||
1261 config->issuercert) {
1262 #ifdef USE_GNUTLS_SRP
1263 if(ssl_config->primary.username && !config->verifypeer &&
1264 gnutls_cipher_get(session)) {
1265 /* no peer cert, but auth is ok if we have SRP user and cipher and no
1266 peer verify */
1267 }
1268 else {
1269 #endif
1270 failf(data, "failed to get server cert");
1271 *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
1272 return CURLE_PEER_FAILED_VERIFICATION;
1273 #ifdef USE_GNUTLS_SRP
1274 }
1275 #endif
1276 }
1277 infof(data, " common name: WARNING could not obtain");
1278 }
1279
1280 if(data->set.ssl.certinfo && chainp) {
1281 unsigned int i;
1282
1283 result = Curl_ssl_init_certinfo(data, (int)cert_list_size);
1284 if(result)
1285 return result;
1286
1287 for(i = 0; i < cert_list_size; i++) {
1288 const char *beg = (const char *) chainp[i].data;
1289 const char *end = beg + chainp[i].size;
1290
1291 result = Curl_extract_certinfo(data, (int)i, beg, end);
1292 if(result)
1293 return result;
1294 }
1295 }
1296
1297 if(config->verifypeer) {
1298 /* This function will try to verify the peer's certificate and return its
1299 status (trusted, invalid etc.). The value of status should be one or
1300 more of the gnutls_certificate_status_t enumerated elements bitwise
1301 or'd. To avoid denial of service attacks some default upper limits
1302 regarding the certificate key size and chain size are set. To override
1303 them use gnutls_certificate_set_verify_limits(). */
1304
1305 rc = gnutls_certificate_verify_peers2(session, &verify_status);
1306 if(rc < 0) {
1307 failf(data, "server cert verify failed: %d", rc);
1308 *certverifyresult = rc;
1309 return CURLE_SSL_CONNECT_ERROR;
1310 }
1311
1312 *certverifyresult = verify_status;
1313
1314 /* verify_status is a bitmask of gnutls_certificate_status bits */
1315 if(verify_status & GNUTLS_CERT_INVALID) {
1316 if(config->verifypeer) {
1317 const char *cause = "certificate error, no details available";
1318 if(verify_status & GNUTLS_CERT_EXPIRED)
1319 cause = "certificate has expired";
1320 else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1321 cause = "certificate signer not trusted";
1322 else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
1323 cause = "certificate uses insecure algorithm";
1324 else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
1325 cause = "attached OCSP status response is invalid";
1326 failf(data, "server verification failed: %s. (CAfile: %s "
1327 "CRLfile: %s)", cause,
1328 config->CAfile ? config->CAfile : "none",
1329 ssl_config->primary.CRLfile ?
1330 ssl_config->primary.CRLfile : "none");
1331 return CURLE_PEER_FAILED_VERIFICATION;
1332 }
1333 else
1334 infof(data, " server certificate verification FAILED");
1335 }
1336 else
1337 infof(data, " server certificate verification OK");
1338 }
1339 else
1340 infof(data, " server certificate verification SKIPPED");
1341
1342 if(config->verifystatus) {
1343 gnutls_datum_t status_request;
1344 gnutls_ocsp_resp_t ocsp_resp;
1345 gnutls_ocsp_cert_status_t status;
1346 gnutls_x509_crl_reason_t reason;
1347
1348 rc = gnutls_ocsp_status_request_get(session, &status_request);
1349
1350 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1351 failf(data, "No OCSP response received");
1352 return CURLE_SSL_INVALIDCERTSTATUS;
1353 }
1354
1355 if(rc < 0) {
1356 failf(data, "Invalid OCSP response received");
1357 return CURLE_SSL_INVALIDCERTSTATUS;
1358 }
1359
1360 gnutls_ocsp_resp_init(&ocsp_resp);
1361
1362 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1363 if(rc < 0) {
1364 failf(data, "Invalid OCSP response received");
1365 return CURLE_SSL_INVALIDCERTSTATUS;
1366 }
1367
1368 (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1369 &status, NULL, NULL, NULL, &reason);
1370
1371 switch(status) {
1372 case GNUTLS_OCSP_CERT_GOOD:
1373 break;
1374
1375 case GNUTLS_OCSP_CERT_REVOKED: {
1376 const char *crl_reason;
1377
1378 switch(reason) {
1379 default:
1380 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1381 crl_reason = "unspecified reason";
1382 break;
1383
1384 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1385 crl_reason = "private key compromised";
1386 break;
1387
1388 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1389 crl_reason = "CA compromised";
1390 break;
1391
1392 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1393 crl_reason = "affiliation has changed";
1394 break;
1395
1396 case GNUTLS_X509_CRLREASON_SUPERSEDED:
1397 crl_reason = "certificate superseded";
1398 break;
1399
1400 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1401 crl_reason = "operation has ceased";
1402 break;
1403
1404 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1405 crl_reason = "certificate is on hold";
1406 break;
1407
1408 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1409 crl_reason = "will be removed from delta CRL";
1410 break;
1411
1412 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1413 crl_reason = "privilege withdrawn";
1414 break;
1415
1416 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1417 crl_reason = "AA compromised";
1418 break;
1419 }
1420
1421 failf(data, "Server certificate was revoked: %s", crl_reason);
1422 break;
1423 }
1424
1425 default:
1426 case GNUTLS_OCSP_CERT_UNKNOWN:
1427 failf(data, "Server certificate status is unknown");
1428 break;
1429 }
1430
1431 gnutls_ocsp_resp_deinit(ocsp_resp);
1432 if(status != GNUTLS_OCSP_CERT_GOOD)
1433 return CURLE_SSL_INVALIDCERTSTATUS;
1434 }
1435 else
1436 infof(data, " server certificate status verification SKIPPED");
1437
1438 /* initialize an X.509 certificate structure. */
1439 gnutls_x509_crt_init(&x509_cert);
1440
1441 if(chainp)
1442 /* convert the given DER or PEM encoded Certificate to the native
1443 gnutls_x509_crt_t format */
1444 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1445
1446 if(config->issuercert) {
1447 gnutls_x509_crt_init(&x509_issuer);
1448 issuerp = load_file(config->issuercert);
1449 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1450 rc = (int)gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1451 gnutls_x509_crt_deinit(x509_issuer);
1452 unload_file(issuerp);
1453 if(rc <= 0) {
1454 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1455 config->issuercert ? config->issuercert : "none");
1456 gnutls_x509_crt_deinit(x509_cert);
1457 return CURLE_SSL_ISSUER_ERROR;
1458 }
1459 infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
1460 config->issuercert ? config->issuercert : "none");
1461 }
1462
1463 size = sizeof(certname);
1464 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1465 0, /* the first and only one */
1466 FALSE,
1467 certname,
1468 &size);
1469 if(rc) {
1470 infof(data, "error fetching CN from cert:%s",
1471 gnutls_strerror(rc));
1472 }
1473
1474 /* This function will check if the given certificate's subject matches the
1475 given hostname. This is a basic implementation of the matching described
1476 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1477 alternative name PKIX extension. Returns non zero on success, and zero on
1478 failure. */
1479
1480 /* This function does not handle trailing dots, so if we have an SNI name
1481 use that and fallback to the hostname only if there is no SNI (like for
1482 IP addresses) */
1483 rc = (int)gnutls_x509_crt_check_hostname(x509_cert,
1484 peer->sni ? peer->sni :
1485 peer->hostname);
1486 #if GNUTLS_VERSION_NUMBER < 0x030306
1487 /* Before 3.3.6, gnutls_x509_crt_check_hostname() did not check IP
1488 addresses. */
1489 if(!rc) {
1490 #ifdef USE_IPV6
1491 #define use_addr in6_addr
1492 #else
1493 #define use_addr in_addr
1494 #endif
1495 unsigned char addrbuf[sizeof(struct use_addr)];
1496 size_t addrlen = 0;
1497
1498 if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
1499 addrlen = 4;
1500 #ifdef USE_IPV6
1501 else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
1502 addrlen = 16;
1503 #endif
1504
1505 if(addrlen) {
1506 unsigned char certaddr[sizeof(struct use_addr)];
1507 int i;
1508
1509 for(i = 0; ; i++) {
1510 size_t certaddrlen = sizeof(certaddr);
1511 int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1512 &certaddrlen, NULL);
1513 /* If this happens, it was not an IP address. */
1514 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1515 continue;
1516 if(ret < 0)
1517 break;
1518 if(ret != GNUTLS_SAN_IPADDRESS)
1519 continue;
1520 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1521 rc = 1;
1522 break;
1523 }
1524 }
1525 }
1526 }
1527 #endif
1528 if(!rc) {
1529 if(config->verifyhost) {
1530 failf(data, "SSL: certificate subject name (%s) does not match "
1531 "target hostname '%s'", certname, peer->dispname);
1532 gnutls_x509_crt_deinit(x509_cert);
1533 return CURLE_PEER_FAILED_VERIFICATION;
1534 }
1535 else
1536 infof(data, " common name: %s (does not match '%s')",
1537 certname, peer->dispname);
1538 }
1539 else
1540 infof(data, " common name: %s (matched)", certname);
1541
1542 /* Check for time-based validity */
1543 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1544
1545 if(certclock == (time_t)-1) {
1546 if(config->verifypeer) {
1547 failf(data, "server cert expiration date verify failed");
1548 *certverifyresult = GNUTLS_CERT_EXPIRED;
1549 gnutls_x509_crt_deinit(x509_cert);
1550 return CURLE_SSL_CONNECT_ERROR;
1551 }
1552 else
1553 infof(data, " server certificate expiration date verify FAILED");
1554 }
1555 else {
1556 if(certclock < time(NULL)) {
1557 if(config->verifypeer) {
1558 failf(data, "server certificate expiration date has passed.");
1559 *certverifyresult = GNUTLS_CERT_EXPIRED;
1560 gnutls_x509_crt_deinit(x509_cert);
1561 return CURLE_PEER_FAILED_VERIFICATION;
1562 }
1563 else
1564 infof(data, " server certificate expiration date FAILED");
1565 }
1566 else
1567 infof(data, " server certificate expiration date OK");
1568 }
1569
1570 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1571
1572 if(certclock == (time_t)-1) {
1573 if(config->verifypeer) {
1574 failf(data, "server cert activation date verify failed");
1575 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1576 gnutls_x509_crt_deinit(x509_cert);
1577 return CURLE_SSL_CONNECT_ERROR;
1578 }
1579 else
1580 infof(data, " server certificate activation date verify FAILED");
1581 }
1582 else {
1583 if(certclock > time(NULL)) {
1584 if(config->verifypeer) {
1585 failf(data, "server certificate not activated yet.");
1586 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1587 gnutls_x509_crt_deinit(x509_cert);
1588 return CURLE_PEER_FAILED_VERIFICATION;
1589 }
1590 else
1591 infof(data, " server certificate activation date FAILED");
1592 }
1593 else
1594 infof(data, " server certificate activation date OK");
1595 }
1596
1597 if(pinned_key) {
1598 result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
1599 if(result != CURLE_OK) {
1600 failf(data, "SSL: public key does not match pinned public key");
1601 gnutls_x509_crt_deinit(x509_cert);
1602 return result;
1603 }
1604 }
1605
1606 /* Show:
1607
1608 - subject
1609 - start date
1610 - expire date
1611 - common name
1612 - issuer
1613
1614 */
1615
1616 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1617 /* public key algorithm's parameters */
1618 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1619 infof(data, " certificate public key: %s",
1620 gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo));
1621
1622 /* version of the X.509 certificate. */
1623 infof(data, " certificate version: #%d",
1624 gnutls_x509_crt_get_version(x509_cert));
1625
1626
1627 rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1628 if(rc)
1629 infof(data, "Failed to get certificate name");
1630 else {
1631 infof(data, " subject: %s", certfields.data);
1632
1633 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1634 showtime(data, "start date", certclock);
1635
1636 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1637 showtime(data, "expire date", certclock);
1638
1639 gnutls_free(certfields.data);
1640 }
1641
1642 rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1643 if(rc)
1644 infof(data, "Failed to get certificate issuer");
1645 else {
1646 infof(data, " issuer: %s", certfields.data);
1647
1648 gnutls_free(certfields.data);
1649 }
1650 #endif
1651
1652 gnutls_x509_crt_deinit(x509_cert);
1653
1654 return result;
1655 }
1656
gtls_verifyserver(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)1657 static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
1658 struct Curl_easy *data,
1659 gnutls_session_t session)
1660 {
1661 struct ssl_connect_data *connssl = cf->ctx;
1662 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1663 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1664 #ifndef CURL_DISABLE_PROXY
1665 const char *pinned_key = Curl_ssl_cf_is_proxy(cf) ?
1666 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1667 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1668 #else
1669 const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1670 #endif
1671 CURLcode result;
1672
1673 result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
1674 &connssl->peer, pinned_key);
1675 if(result)
1676 goto out;
1677
1678 if(connssl->alpn) {
1679 gnutls_datum_t proto;
1680 int rc;
1681
1682 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1683 if(rc == 0)
1684 Curl_alpn_set_negotiated(cf, data, proto.data, proto.size);
1685 else
1686 Curl_alpn_set_negotiated(cf, data, NULL, 0);
1687 }
1688
1689 /* Only on TLSv1.2 or lower do we have the session id now. For
1690 * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
1691 if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
1692 result = gtls_update_session_id(cf, data, session);
1693
1694 out:
1695 return result;
1696 }
1697
1698 /*
1699 * This function is called after the TCP connect has completed. Setup the TLS
1700 * layer and do all necessary magic.
1701 */
1702 /* We use connssl->connecting_state to keep track of the connection status;
1703 there are three states: 'ssl_connect_1' (not started yet or complete),
1704 'ssl_connect_2' (doing handshake with the server), and
1705 'ssl_connect_3' (verifying and getting stats).
1706 */
1707 static CURLcode
gtls_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1708 gtls_connect_common(struct Curl_cfilter *cf,
1709 struct Curl_easy *data,
1710 bool nonblocking,
1711 bool *done)
1712 {
1713 struct ssl_connect_data *connssl = cf->ctx;
1714 CURLcode rc;
1715 CURLcode result = CURLE_OK;
1716
1717 /* Initiate the connection, if not already done */
1718 if(ssl_connect_1 == connssl->connecting_state) {
1719 rc = gtls_connect_step1(cf, data);
1720 if(rc) {
1721 result = rc;
1722 goto out;
1723 }
1724 }
1725
1726 rc = handshake(cf, data, TRUE, nonblocking);
1727 if(rc) {
1728 /* handshake() sets its own error message with failf() */
1729 result = rc;
1730 goto out;
1731 }
1732
1733 /* Finish connecting once the handshake is done */
1734 if(ssl_connect_1 == connssl->connecting_state) {
1735 struct gtls_ssl_backend_data *backend =
1736 (struct gtls_ssl_backend_data *)connssl->backend;
1737 gnutls_session_t session;
1738 DEBUGASSERT(backend);
1739 session = backend->gtls.session;
1740 rc = gtls_verifyserver(cf, data, session);
1741 if(rc) {
1742 result = rc;
1743 goto out;
1744 }
1745 connssl->state = ssl_connection_complete;
1746 }
1747
1748 out:
1749 *done = ssl_connect_1 == connssl->connecting_state;
1750
1751 return result;
1752 }
1753
gtls_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1754 static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
1755 struct Curl_easy *data,
1756 bool *done)
1757 {
1758 return gtls_connect_common(cf, data, TRUE, done);
1759 }
1760
gtls_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1761 static CURLcode gtls_connect(struct Curl_cfilter *cf,
1762 struct Curl_easy *data)
1763 {
1764 CURLcode result;
1765 bool done = FALSE;
1766
1767 result = gtls_connect_common(cf, data, FALSE, &done);
1768 if(result)
1769 return result;
1770
1771 DEBUGASSERT(done);
1772
1773 return CURLE_OK;
1774 }
1775
gtls_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1776 static bool gtls_data_pending(struct Curl_cfilter *cf,
1777 const struct Curl_easy *data)
1778 {
1779 struct ssl_connect_data *ctx = cf->ctx;
1780 struct gtls_ssl_backend_data *backend;
1781
1782 (void)data;
1783 DEBUGASSERT(ctx && ctx->backend);
1784 backend = (struct gtls_ssl_backend_data *)ctx->backend;
1785 if(backend->gtls.session &&
1786 0 != gnutls_record_check_pending(backend->gtls.session))
1787 return TRUE;
1788 return FALSE;
1789 }
1790
gtls_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t blen,CURLcode * curlcode)1791 static ssize_t gtls_send(struct Curl_cfilter *cf,
1792 struct Curl_easy *data,
1793 const void *buf,
1794 size_t blen,
1795 CURLcode *curlcode)
1796 {
1797 struct ssl_connect_data *connssl = cf->ctx;
1798 struct gtls_ssl_backend_data *backend =
1799 (struct gtls_ssl_backend_data *)connssl->backend;
1800 ssize_t rc;
1801 size_t nwritten, total_written = 0;
1802
1803 (void)data;
1804 DEBUGASSERT(backend);
1805 while(blen) {
1806 backend->gtls.io_result = CURLE_OK;
1807 rc = gnutls_record_send(backend->gtls.session, buf, blen);
1808
1809 if(rc < 0) {
1810 if(total_written && (rc == GNUTLS_E_AGAIN)) {
1811 *curlcode = CURLE_OK;
1812 rc = (ssize_t)total_written;
1813 goto out;
1814 }
1815 *curlcode = (rc == GNUTLS_E_AGAIN) ?
1816 CURLE_AGAIN :
1817 (backend->gtls.io_result ? backend->gtls.io_result : CURLE_SEND_ERROR);
1818
1819 rc = -1;
1820 goto out;
1821 }
1822 nwritten = (size_t)rc;
1823 total_written += nwritten;
1824 DEBUGASSERT(nwritten <= blen);
1825 buf = (char *)buf + nwritten;
1826 blen -= nwritten;
1827 }
1828 rc = total_written;
1829
1830 out:
1831 return rc;
1832 }
1833
1834 /*
1835 * This function is called to shut down the SSL layer but keep the
1836 * socket open (CCC - Clear Command Channel)
1837 */
gtls_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)1838 static CURLcode gtls_shutdown(struct Curl_cfilter *cf,
1839 struct Curl_easy *data,
1840 bool send_shutdown, bool *done)
1841 {
1842 struct ssl_connect_data *connssl = cf->ctx;
1843 struct gtls_ssl_backend_data *backend =
1844 (struct gtls_ssl_backend_data *)connssl->backend;
1845 char buf[1024];
1846 CURLcode result = CURLE_OK;
1847 ssize_t nread;
1848 size_t i;
1849
1850 DEBUGASSERT(backend);
1851 if(!backend->gtls.session || cf->shutdown) {
1852 *done = TRUE;
1853 goto out;
1854 }
1855
1856 connssl->io_need = CURL_SSL_IO_NEED_NONE;
1857 *done = FALSE;
1858
1859 if(!backend->gtls.sent_shutdown) {
1860 /* do this only once */
1861 backend->gtls.sent_shutdown = TRUE;
1862 if(send_shutdown) {
1863 int ret = gnutls_bye(backend->gtls.session, GNUTLS_SHUT_RDWR);
1864 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1865 CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye EAGAIN");
1866 connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
1867 CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
1868 backend->gtls.sent_shutdown = FALSE;
1869 result = CURLE_OK;
1870 goto out;
1871 }
1872 if(ret != GNUTLS_E_SUCCESS) {
1873 CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye error: '%s'(%d)",
1874 gnutls_strerror((int)ret), (int)ret);
1875 result = CURLE_RECV_ERROR;
1876 goto out;
1877 }
1878 }
1879 }
1880
1881 /* SSL should now have started the shutdown from our side. Since it
1882 * was not complete, we are lacking the close notify from the server. */
1883 for(i = 0; i < 10; ++i) {
1884 nread = gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
1885 if(nread <= 0)
1886 break;
1887 }
1888 if(nread > 0) {
1889 /* still data coming in? */
1890 }
1891 else if(nread == 0) {
1892 /* We got the close notify alert and are done. */
1893 *done = TRUE;
1894 }
1895 else if((nread == GNUTLS_E_AGAIN) || (nread == GNUTLS_E_INTERRUPTED)) {
1896 connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
1897 CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
1898 }
1899 else {
1900 CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)",
1901 gnutls_strerror((int)nread), (int)nread);
1902 result = CURLE_RECV_ERROR;
1903 }
1904
1905 out:
1906 cf->shutdown = (result || *done);
1907 return result;
1908 }
1909
gtls_close(struct Curl_cfilter * cf,struct Curl_easy * data)1910 static void gtls_close(struct Curl_cfilter *cf,
1911 struct Curl_easy *data)
1912 {
1913 struct ssl_connect_data *connssl = cf->ctx;
1914 struct gtls_ssl_backend_data *backend =
1915 (struct gtls_ssl_backend_data *)connssl->backend;
1916
1917 (void) data;
1918 DEBUGASSERT(backend);
1919 CURL_TRC_CF(data, cf, "close");
1920 if(backend->gtls.session) {
1921 gnutls_deinit(backend->gtls.session);
1922 backend->gtls.session = NULL;
1923 }
1924 if(backend->gtls.shared_creds) {
1925 Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
1926 }
1927 #ifdef USE_GNUTLS_SRP
1928 if(backend->gtls.srp_client_cred) {
1929 gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1930 backend->gtls.srp_client_cred = NULL;
1931 }
1932 #endif
1933 }
1934
gtls_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t buffersize,CURLcode * curlcode)1935 static ssize_t gtls_recv(struct Curl_cfilter *cf,
1936 struct Curl_easy *data,
1937 char *buf,
1938 size_t buffersize,
1939 CURLcode *curlcode)
1940 {
1941 struct ssl_connect_data *connssl = cf->ctx;
1942 struct gtls_ssl_backend_data *backend =
1943 (struct gtls_ssl_backend_data *)connssl->backend;
1944 ssize_t ret;
1945
1946 (void)data;
1947 DEBUGASSERT(backend);
1948
1949 backend->gtls.io_result = CURLE_OK;
1950 ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
1951 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1952 *curlcode = CURLE_AGAIN;
1953 ret = -1;
1954 goto out;
1955 }
1956
1957 if(ret == GNUTLS_E_REHANDSHAKE) {
1958 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1959 proper way" takes a whole lot of work. */
1960 CURLcode result = handshake(cf, data, FALSE, FALSE);
1961 if(result)
1962 /* handshake() writes error message on its own */
1963 *curlcode = result;
1964 else
1965 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1966 ret = -1;
1967 goto out;
1968 }
1969
1970 if(ret < 0) {
1971 failf(data, "GnuTLS recv error (%d): %s",
1972 (int)ret, gnutls_strerror((int)ret));
1973 *curlcode = backend->gtls.io_result ?
1974 backend->gtls.io_result : CURLE_RECV_ERROR;
1975 ret = -1;
1976 goto out;
1977 }
1978
1979 out:
1980 return ret;
1981 }
1982
gtls_version(char * buffer,size_t size)1983 static size_t gtls_version(char *buffer, size_t size)
1984 {
1985 return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1986 }
1987
1988 /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1989 static CURLcode gtls_random(struct Curl_easy *data,
1990 unsigned char *entropy, size_t length)
1991 {
1992 int rc;
1993 (void)data;
1994 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1995 return rc ? CURLE_FAILED_INIT : CURLE_OK;
1996 }
1997
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)1998 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1999 size_t tmplen,
2000 unsigned char *sha256sum, /* output */
2001 size_t sha256len)
2002 {
2003 struct sha256_ctx SHA256pw;
2004 sha256_init(&SHA256pw);
2005 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
2006 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
2007 return CURLE_OK;
2008 }
2009
gtls_cert_status_request(void)2010 static bool gtls_cert_status_request(void)
2011 {
2012 return TRUE;
2013 }
2014
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)2015 static void *gtls_get_internals(struct ssl_connect_data *connssl,
2016 CURLINFO info UNUSED_PARAM)
2017 {
2018 struct gtls_ssl_backend_data *backend =
2019 (struct gtls_ssl_backend_data *)connssl->backend;
2020 (void)info;
2021 DEBUGASSERT(backend);
2022 return backend->gtls.session;
2023 }
2024
2025 const struct Curl_ssl Curl_ssl_gnutls = {
2026 { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
2027
2028 SSLSUPP_CA_PATH |
2029 SSLSUPP_CERTINFO |
2030 SSLSUPP_PINNEDPUBKEY |
2031 SSLSUPP_HTTPS_PROXY |
2032 SSLSUPP_CA_CACHE,
2033
2034 sizeof(struct gtls_ssl_backend_data),
2035
2036 gtls_init, /* init */
2037 gtls_cleanup, /* cleanup */
2038 gtls_version, /* version */
2039 Curl_none_check_cxn, /* check_cxn */
2040 gtls_shutdown, /* shutdown */
2041 gtls_data_pending, /* data_pending */
2042 gtls_random, /* random */
2043 gtls_cert_status_request, /* cert_status_request */
2044 gtls_connect, /* connect */
2045 gtls_connect_nonblocking, /* connect_nonblocking */
2046 Curl_ssl_adjust_pollset, /* adjust_pollset */
2047 gtls_get_internals, /* get_internals */
2048 gtls_close, /* close_one */
2049 Curl_none_close_all, /* close_all */
2050 Curl_none_set_engine, /* set_engine */
2051 Curl_none_set_engine_default, /* set_engine_default */
2052 Curl_none_engines_list, /* engines_list */
2053 Curl_none_false_start, /* false_start */
2054 gtls_sha256sum, /* sha256sum */
2055 NULL, /* associate_connection */
2056 NULL, /* disassociate_connection */
2057 gtls_recv, /* recv decrypted data */
2058 gtls_send, /* send data to encrypt */
2059 NULL, /* get_channel_binding */
2060 };
2061
2062 #endif /* USE_GNUTLS */
2063