VirtualBox

source: vbox/trunk/src/libs/curl-7.83.1/lib/vtls/gtls.c@ 97623

Last change on this file since 97623 was 95312, checked in by vboxsync, 3 years ago

libs/{curl,libxml2}: OSE export fixes, bugref:8515

  • Property svn:eol-style set to native
File size: 51.2 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <[email protected]>, 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 ***************************************************************************/
22
23/*
24 * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
25 * but vtls.c should ever call or use these functions.
26 *
27 * Note: don't use the GnuTLS' *_t variable type names in this source code,
28 * since they were not present in 1.0.X.
29 */
30
31#include "curl_setup.h"
32
33#ifdef USE_GNUTLS
34
35#include <gnutls/abstract.h>
36#include <gnutls/gnutls.h>
37#include <gnutls/x509.h>
38#include <gnutls/crypto.h>
39#include <nettle/sha2.h>
40
41#include "urldata.h"
42#include "sendf.h"
43#include "inet_pton.h"
44#include "gtls.h"
45#include "vtls.h"
46#include "parsedate.h"
47#include "connect.h" /* for the connect timeout */
48#include "select.h"
49#include "strcase.h"
50#include "warnless.h"
51#include "x509asn1.h"
52#include "multiif.h"
53#include "curl_printf.h"
54#include "curl_memory.h"
55/* The last #include file should be: */
56#include "memdebug.h"
57
58#ifdef HAVE_GNUTLS_SRP
59/* the function exists */
60#ifdef USE_TLS_SRP
61/* the functionality is not disabled */
62#define USE_GNUTLS_SRP
63#endif
64#endif
65
66/* Enable GnuTLS debugging by defining GTLSDEBUG */
67/*#define GTLSDEBUG */
68
69#ifdef GTLSDEBUG
70static void tls_log_func(int level, const char *str)
71{
72 fprintf(stderr, "|<%d>| %s", level, str);
73}
74#endif
75static bool gtls_inited = FALSE;
76
77#if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
78#error "too old GnuTLS version"
79#endif
80
81# include <gnutls/ocsp.h>
82
83struct ssl_backend_data {
84 gnutls_session_t session;
85 gnutls_certificate_credentials_t cred;
86#ifdef USE_GNUTLS_SRP
87 gnutls_srp_client_credentials_t srp_client_cred;
88#endif
89};
90
91static ssize_t gtls_push(void *s, const void *buf, size_t len)
92{
93 curl_socket_t sock = *(curl_socket_t *)s;
94 ssize_t ret = swrite(sock, buf, len);
95 return ret;
96}
97
98static ssize_t gtls_pull(void *s, void *buf, size_t len)
99{
100 curl_socket_t sock = *(curl_socket_t *)s;
101 ssize_t ret = sread(sock, buf, len);
102 return ret;
103}
104
105static ssize_t gtls_push_ssl(void *s, const void *buf, size_t len)
106{
107 return gnutls_record_send((gnutls_session_t) s, buf, len);
108}
109
110static ssize_t gtls_pull_ssl(void *s, void *buf, size_t len)
111{
112 return gnutls_record_recv((gnutls_session_t) s, buf, len);
113}
114
115/* gtls_init()
116 *
117 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
118 * are not thread-safe and thus this function itself is not thread-safe and
119 * must only be called from within curl_global_init() to keep the thread
120 * situation under control!
121 */
122static int gtls_init(void)
123{
124 int ret = 1;
125 if(!gtls_inited) {
126 ret = gnutls_global_init()?0:1;
127#ifdef GTLSDEBUG
128 gnutls_global_set_log_function(tls_log_func);
129 gnutls_global_set_log_level(2);
130#endif
131 gtls_inited = TRUE;
132 }
133 return ret;
134}
135
136static void gtls_cleanup(void)
137{
138 if(gtls_inited) {
139 gnutls_global_deinit();
140 gtls_inited = FALSE;
141 }
142}
143
144#ifndef CURL_DISABLE_VERBOSE_STRINGS
145static void showtime(struct Curl_easy *data,
146 const char *text,
147 time_t stamp)
148{
149 struct tm buffer;
150 const struct tm *tm = &buffer;
151 char str[96];
152 CURLcode result = Curl_gmtime(stamp, &buffer);
153 if(result)
154 return;
155
156 msnprintf(str,
157 sizeof(str),
158 " %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
159 text,
160 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
161 tm->tm_mday,
162 Curl_month[tm->tm_mon],
163 tm->tm_year + 1900,
164 tm->tm_hour,
165 tm->tm_min,
166 tm->tm_sec);
167 infof(data, "%s", str);
168}
169#endif
170
171static gnutls_datum_t load_file(const char *file)
172{
173 FILE *f;
174 gnutls_datum_t loaded_file = { NULL, 0 };
175 long filelen;
176 void *ptr;
177
178 f = fopen(file, "rb");
179 if(!f)
180 return loaded_file;
181 if(fseek(f, 0, SEEK_END) != 0
182 || (filelen = ftell(f)) < 0
183 || fseek(f, 0, SEEK_SET) != 0
184 || !(ptr = malloc((size_t)filelen)))
185 goto out;
186 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
187 free(ptr);
188 goto out;
189 }
190
191 loaded_file.data = ptr;
192 loaded_file.size = (unsigned int)filelen;
193out:
194 fclose(f);
195 return loaded_file;
196}
197
198static void unload_file(gnutls_datum_t data)
199{
200 free(data.data);
201}
202
203
204/* this function does a SSL/TLS (re-)handshake */
205static CURLcode handshake(struct Curl_easy *data,
206 struct connectdata *conn,
207 int sockindex,
208 bool duringconnect,
209 bool nonblocking)
210{
211 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
212 struct ssl_backend_data *backend = connssl->backend;
213 gnutls_session_t session;
214 curl_socket_t sockfd = conn->sock[sockindex];
215
216 DEBUGASSERT(backend);
217 session = backend->session;
218
219 for(;;) {
220 timediff_t timeout_ms;
221 int rc;
222
223 /* check allowed time left */
224 timeout_ms = Curl_timeleft(data, NULL, duringconnect);
225
226 if(timeout_ms < 0) {
227 /* no need to continue if time already is up */
228 failf(data, "SSL connection timeout");
229 return CURLE_OPERATION_TIMEDOUT;
230 }
231
232 /* if ssl is expecting something, check if it's available. */
233 if(connssl->connecting_state == ssl_connect_2_reading
234 || connssl->connecting_state == ssl_connect_2_writing) {
235 int what;
236 curl_socket_t writefd = ssl_connect_2_writing ==
237 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
238 curl_socket_t readfd = ssl_connect_2_reading ==
239 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
240
241 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
242 nonblocking?0:
243 timeout_ms?timeout_ms:1000);
244 if(what < 0) {
245 /* fatal error */
246 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
247 return CURLE_SSL_CONNECT_ERROR;
248 }
249 else if(0 == what) {
250 if(nonblocking)
251 return CURLE_OK;
252 else if(timeout_ms) {
253 /* timeout */
254 failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
255 return CURLE_OPERATION_TIMEDOUT;
256 }
257 }
258 /* socket is readable or writable */
259 }
260
261 rc = gnutls_handshake(session);
262
263 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
264 connssl->connecting_state =
265 gnutls_record_get_direction(session)?
266 ssl_connect_2_writing:ssl_connect_2_reading;
267 continue;
268 }
269 else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
270 const char *strerr = NULL;
271
272 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
273 int alert = gnutls_alert_get(session);
274 strerr = gnutls_alert_get_name(alert);
275 }
276
277 if(!strerr)
278 strerr = gnutls_strerror(rc);
279
280 infof(data, "gnutls_handshake() warning: %s", strerr);
281 continue;
282 }
283 else if(rc < 0) {
284 const char *strerr = NULL;
285
286 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
287 int alert = gnutls_alert_get(session);
288 strerr = gnutls_alert_get_name(alert);
289 }
290
291 if(!strerr)
292 strerr = gnutls_strerror(rc);
293
294 failf(data, "gnutls_handshake() failed: %s", strerr);
295 return CURLE_SSL_CONNECT_ERROR;
296 }
297
298 /* Reset our connect state machine */
299 connssl->connecting_state = ssl_connect_1;
300 return CURLE_OK;
301 }
302}
303
304static gnutls_x509_crt_fmt_t do_file_type(const char *type)
305{
306 if(!type || !type[0])
307 return GNUTLS_X509_FMT_PEM;
308 if(strcasecompare(type, "PEM"))
309 return GNUTLS_X509_FMT_PEM;
310 if(strcasecompare(type, "DER"))
311 return GNUTLS_X509_FMT_DER;
312 return GNUTLS_X509_FMT_PEM; /* default to PEM */
313}
314
315#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
316/* If GnuTLS was compiled without support for SRP it will error out if SRP is
317 requested in the priority string, so treat it specially
318 */
319#define GNUTLS_SRP "+SRP"
320
321static CURLcode
322set_ssl_version_min_max(struct Curl_easy *data,
323 const char **prioritylist,
324 const char *tls13support)
325{
326 struct connectdata *conn = data->conn;
327 long ssl_version = SSL_CONN_CONFIG(version);
328 long ssl_version_max = SSL_CONN_CONFIG(version_max);
329
330 if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
331 (ssl_version == CURL_SSLVERSION_TLSv1))
332 ssl_version = CURL_SSLVERSION_TLSv1_0;
333 if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
334 ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
335 if(!tls13support) {
336 /* If the running GnuTLS doesn't support TLS 1.3, we must not specify a
337 prioritylist involving that since it will make GnuTLS return an en
338 error back at us */
339 if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
340 (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
341 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
342 }
343 }
344 else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
345 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
346 }
347
348 switch(ssl_version | ssl_version_max) {
349 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
350 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
351 "+VERS-TLS1.0";
352 return CURLE_OK;
353 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
354 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
355 "+VERS-TLS1.1:+VERS-TLS1.0";
356 return CURLE_OK;
357 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
358 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
359 "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
360 return CURLE_OK;
361 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
362 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
363 "+VERS-TLS1.1";
364 return CURLE_OK;
365 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
366 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
367 "+VERS-TLS1.2:+VERS-TLS1.1";
368 return CURLE_OK;
369 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
370 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
371 "+VERS-TLS1.2";
372 return CURLE_OK;
373 case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
374 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
375 "+VERS-TLS1.3";
376 return CURLE_OK;
377 case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
378 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
379 return CURLE_OK;
380 case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
381 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
382 "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
383 return CURLE_OK;
384 case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
385 *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
386 "+VERS-TLS1.3:+VERS-TLS1.2";
387 return CURLE_OK;
388 }
389
390 failf(data, "GnuTLS: cannot set ssl protocol");
391 return CURLE_SSL_CONNECT_ERROR;
392}
393
394static CURLcode
395gtls_connect_step1(struct Curl_easy *data,
396 struct connectdata *conn,
397 int sockindex)
398{
399 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
400 struct ssl_backend_data *backend = connssl->backend;
401 unsigned int init_flags;
402 gnutls_session_t session;
403 int rc;
404 bool sni = TRUE; /* default is SNI enabled */
405 void *transport_ptr = NULL;
406 gnutls_push_func gnutls_transport_push = NULL;
407 gnutls_pull_func gnutls_transport_pull = NULL;
408#ifdef ENABLE_IPV6
409 struct in6_addr addr;
410#else
411 struct in_addr addr;
412#endif
413 const char *prioritylist;
414 const char *err = NULL;
415 const char * const hostname = SSL_HOST_NAME();
416 long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
417 const char *tls13support;
418 CURLcode result;
419
420 DEBUGASSERT(backend);
421
422 if(connssl->state == ssl_connection_complete)
423 /* to make us tolerant against being called more than once for the
424 same connection */
425 return CURLE_OK;
426
427 if(!gtls_inited)
428 gtls_init();
429
430 /* Initialize certverifyresult to OK */
431 *certverifyresult = 0;
432
433 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
434 failf(data, "GnuTLS does not support SSLv2");
435 return CURLE_SSL_CONNECT_ERROR;
436 }
437 else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
438 sni = FALSE; /* SSLv3 has no SNI */
439
440 /* allocate a cred struct */
441 rc = gnutls_certificate_allocate_credentials(&backend->cred);
442 if(rc != GNUTLS_E_SUCCESS) {
443 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
444 return CURLE_SSL_CONNECT_ERROR;
445 }
446
447#ifdef USE_GNUTLS_SRP
448 if((SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) &&
449 Curl_allow_auth_to_host(data)) {
450 infof(data, "Using TLS-SRP username: %s",
451 SSL_SET_OPTION(primary.username));
452
453 rc = gnutls_srp_allocate_client_credentials(&backend->srp_client_cred);
454 if(rc != GNUTLS_E_SUCCESS) {
455 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
456 gnutls_strerror(rc));
457 return CURLE_OUT_OF_MEMORY;
458 }
459
460 rc = gnutls_srp_set_client_credentials(backend->srp_client_cred,
461 SSL_SET_OPTION(primary.username),
462 SSL_SET_OPTION(primary.password));
463 if(rc != GNUTLS_E_SUCCESS) {
464 failf(data, "gnutls_srp_set_client_cred() failed: %s",
465 gnutls_strerror(rc));
466 return CURLE_BAD_FUNCTION_ARGUMENT;
467 }
468 }
469#endif
470
471 if(SSL_CONN_CONFIG(CAfile)) {
472 /* set the trusted CA cert bundle file */
473 gnutls_certificate_set_verify_flags(backend->cred,
474 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
475
476 rc = gnutls_certificate_set_x509_trust_file(backend->cred,
477 SSL_CONN_CONFIG(CAfile),
478 GNUTLS_X509_FMT_PEM);
479 if(rc < 0) {
480 infof(data, "error reading ca cert file %s (%s)",
481 SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
482 if(SSL_CONN_CONFIG(verifypeer)) {
483 *certverifyresult = rc;
484 return CURLE_SSL_CACERT_BADFILE;
485 }
486 }
487 else
488 infof(data, "found %d certificates in %s", rc,
489 SSL_CONN_CONFIG(CAfile));
490 }
491
492 if(SSL_CONN_CONFIG(CApath)) {
493 /* set the trusted CA cert directory */
494 rc = gnutls_certificate_set_x509_trust_dir(backend->cred,
495 SSL_CONN_CONFIG(CApath),
496 GNUTLS_X509_FMT_PEM);
497 if(rc < 0) {
498 infof(data, "error reading ca cert file %s (%s)",
499 SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
500 if(SSL_CONN_CONFIG(verifypeer)) {
501 *certverifyresult = rc;
502 return CURLE_SSL_CACERT_BADFILE;
503 }
504 }
505 else
506 infof(data, "found %d certificates in %s",
507 rc, SSL_CONN_CONFIG(CApath));
508 }
509
510#ifdef CURL_CA_FALLBACK
511 /* use system ca certificate store as fallback */
512 if(SSL_CONN_CONFIG(verifypeer) &&
513 !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
514 /* this ignores errors on purpose */
515 gnutls_certificate_set_x509_system_trust(backend->cred);
516 }
517#endif
518
519 if(SSL_SET_OPTION(primary.CRLfile)) {
520 /* set the CRL list file */
521 rc = gnutls_certificate_set_x509_crl_file(backend->cred,
522 SSL_SET_OPTION(primary.CRLfile),
523 GNUTLS_X509_FMT_PEM);
524 if(rc < 0) {
525 failf(data, "error reading crl file %s (%s)",
526 SSL_SET_OPTION(primary.CRLfile), gnutls_strerror(rc));
527 return CURLE_SSL_CRL_BADFILE;
528 }
529 else
530 infof(data, "found %d CRL in %s",
531 rc, SSL_SET_OPTION(primary.CRLfile));
532 }
533
534 /* Initialize TLS session as a client */
535 init_flags = GNUTLS_CLIENT;
536
537#if defined(GNUTLS_FORCE_CLIENT_CERT)
538 init_flags |= GNUTLS_FORCE_CLIENT_CERT;
539#endif
540
541#if defined(GNUTLS_NO_TICKETS)
542 /* Disable TLS session tickets */
543 init_flags |= GNUTLS_NO_TICKETS;
544#endif
545
546 rc = gnutls_init(&backend->session, init_flags);
547 if(rc != GNUTLS_E_SUCCESS) {
548 failf(data, "gnutls_init() failed: %d", rc);
549 return CURLE_SSL_CONNECT_ERROR;
550 }
551
552 /* convenient assign */
553 session = backend->session;
554
555 if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
556#ifdef ENABLE_IPV6
557 (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
558#endif
559 sni) {
560 size_t snilen;
561 char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
562 if(!snihost || gnutls_server_name_set(session, GNUTLS_NAME_DNS, snihost,
563 snilen) < 0) {
564 failf(data, "Failed to set SNI");
565 return CURLE_SSL_CONNECT_ERROR;
566 }
567 }
568
569 /* Use default priorities */
570 rc = gnutls_set_default_priority(session);
571 if(rc != GNUTLS_E_SUCCESS)
572 return CURLE_SSL_CONNECT_ERROR;
573
574 /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
575 tls13support = gnutls_check_version("3.6.5");
576
577 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
578 * removed if a run-time error indicates that SRP is not supported by this
579 * GnuTLS version */
580
581 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2 ||
582 SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) {
583 failf(data, "GnuTLS does not support SSLv2 or SSLv3");
584 return CURLE_SSL_CONNECT_ERROR;
585 }
586
587 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_TLSv1_3) {
588 if(!tls13support) {
589 failf(data, "This GnuTLS installation does not support TLS 1.3");
590 return CURLE_SSL_CONNECT_ERROR;
591 }
592 }
593
594 /* At this point we know we have a supported TLS version, so set it */
595 result = set_ssl_version_min_max(data, &prioritylist, tls13support);
596 if(result)
597 return result;
598
599#ifdef USE_GNUTLS_SRP
600 /* Only add SRP to the cipher list if SRP is requested. Otherwise
601 * GnuTLS will disable TLS 1.3 support. */
602 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
603 size_t len = strlen(prioritylist);
604
605 char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
606 if(!prioritysrp)
607 return CURLE_OUT_OF_MEMORY;
608 strcpy(prioritysrp, prioritylist);
609 strcpy(prioritysrp + len, ":" GNUTLS_SRP);
610 rc = gnutls_priority_set_direct(session, prioritysrp, &err);
611 free(prioritysrp);
612
613 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
614 infof(data, "This GnuTLS does not support SRP");
615 }
616 }
617 else {
618#endif
619 infof(data, "GnuTLS ciphers: %s", prioritylist);
620 rc = gnutls_priority_set_direct(session, prioritylist, &err);
621#ifdef USE_GNUTLS_SRP
622 }
623#endif
624
625 if(rc != GNUTLS_E_SUCCESS) {
626 failf(data, "Error %d setting GnuTLS cipher list starting with %s",
627 rc, err);
628 return CURLE_SSL_CONNECT_ERROR;
629 }
630
631 if(conn->bits.tls_enable_alpn) {
632 int cur = 0;
633 gnutls_datum_t protocols[2];
634
635#ifdef USE_HTTP2
636 if(data->state.httpwant >= CURL_HTTP_VERSION_2
637#ifndef CURL_DISABLE_PROXY
638 && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
639#endif
640 ) {
641 protocols[cur].data = (unsigned char *)ALPN_H2;
642 protocols[cur].size = ALPN_H2_LENGTH;
643 cur++;
644 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
645 }
646#endif
647
648 protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
649 protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
650 cur++;
651 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
652
653 if(gnutls_alpn_set_protocols(session, protocols, cur, 0)) {
654 failf(data, "failed setting ALPN");
655 return CURLE_SSL_CONNECT_ERROR;
656 }
657 }
658
659 if(SSL_SET_OPTION(primary.clientcert)) {
660 if(SSL_SET_OPTION(key_passwd)) {
661 const unsigned int supported_key_encryption_algorithms =
662 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
663 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
664 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
665 GNUTLS_PKCS_USE_PBES2_AES_256;
666 rc = gnutls_certificate_set_x509_key_file2(
667 backend->cred,
668 SSL_SET_OPTION(primary.clientcert),
669 SSL_SET_OPTION(key) ?
670 SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
671 do_file_type(SSL_SET_OPTION(cert_type)),
672 SSL_SET_OPTION(key_passwd),
673 supported_key_encryption_algorithms);
674 if(rc != GNUTLS_E_SUCCESS) {
675 failf(data,
676 "error reading X.509 potentially-encrypted key file: %s",
677 gnutls_strerror(rc));
678 return CURLE_SSL_CONNECT_ERROR;
679 }
680 }
681 else {
682 if(gnutls_certificate_set_x509_key_file(
683 backend->cred,
684 SSL_SET_OPTION(primary.clientcert),
685 SSL_SET_OPTION(key) ?
686 SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
687 do_file_type(SSL_SET_OPTION(cert_type)) ) !=
688 GNUTLS_E_SUCCESS) {
689 failf(data, "error reading X.509 key or certificate file");
690 return CURLE_SSL_CONNECT_ERROR;
691 }
692 }
693 }
694
695#ifdef USE_GNUTLS_SRP
696 /* put the credentials to the current session */
697 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
698 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
699 backend->srp_client_cred);
700 if(rc != GNUTLS_E_SUCCESS) {
701 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
702 return CURLE_SSL_CONNECT_ERROR;
703 }
704 }
705 else
706#endif
707 {
708 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
709 backend->cred);
710 if(rc != GNUTLS_E_SUCCESS) {
711 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
712 return CURLE_SSL_CONNECT_ERROR;
713 }
714 }
715
716#ifndef CURL_DISABLE_PROXY
717 if(conn->proxy_ssl[sockindex].use) {
718 struct ssl_backend_data *proxy_backend;
719 proxy_backend = conn->proxy_ssl[sockindex].backend;
720 DEBUGASSERT(proxy_backend);
721 transport_ptr = proxy_backend->session;
722 gnutls_transport_push = gtls_push_ssl;
723 gnutls_transport_pull = gtls_pull_ssl;
724 }
725 else
726#endif
727 {
728 /* file descriptor for the socket */
729 transport_ptr = &conn->sock[sockindex];
730 gnutls_transport_push = gtls_push;
731 gnutls_transport_pull = gtls_pull;
732 }
733
734 /* set the connection handle */
735 gnutls_transport_set_ptr(session, transport_ptr);
736
737 /* register callback functions to send and receive data. */
738 gnutls_transport_set_push_function(session, gnutls_transport_push);
739 gnutls_transport_set_pull_function(session, gnutls_transport_pull);
740
741 if(SSL_CONN_CONFIG(verifystatus)) {
742 rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
743 if(rc != GNUTLS_E_SUCCESS) {
744 failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
745 return CURLE_SSL_CONNECT_ERROR;
746 }
747 }
748
749 /* This might be a reconnect, so we check for a session ID in the cache
750 to speed up things */
751 if(SSL_SET_OPTION(primary.sessionid)) {
752 void *ssl_sessionid;
753 size_t ssl_idsize;
754
755 Curl_ssl_sessionid_lock(data);
756 if(!Curl_ssl_getsessionid(data, conn,
757 SSL_IS_PROXY() ? TRUE : FALSE,
758 &ssl_sessionid, &ssl_idsize, sockindex)) {
759 /* we got a session id, use it! */
760 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
761
762 /* Informational message */
763 infof(data, "SSL re-using session ID");
764 }
765 Curl_ssl_sessionid_unlock(data);
766 }
767
768 return CURLE_OK;
769}
770
771static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
772 gnutls_x509_crt_t cert,
773 const char *pinnedpubkey)
774{
775 /* Scratch */
776 size_t len1 = 0, len2 = 0;
777 unsigned char *buff1 = NULL;
778
779 gnutls_pubkey_t key = NULL;
780
781 /* Result is returned to caller */
782 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
783
784 /* if a path wasn't specified, don't pin */
785 if(!pinnedpubkey)
786 return CURLE_OK;
787
788 if(!cert)
789 return result;
790
791 do {
792 int ret;
793
794 /* Begin Gyrations to get the public key */
795 gnutls_pubkey_init(&key);
796
797 ret = gnutls_pubkey_import_x509(key, cert, 0);
798 if(ret < 0)
799 break; /* failed */
800
801 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
802 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
803 break; /* failed */
804
805 buff1 = malloc(len1);
806 if(!buff1)
807 break; /* failed */
808
809 len2 = len1;
810
811 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
812 if(ret < 0 || len1 != len2)
813 break; /* failed */
814
815 /* End Gyrations */
816
817 /* The one good exit point */
818 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
819 } while(0);
820
821 if(key)
822 gnutls_pubkey_deinit(key);
823
824 Curl_safefree(buff1);
825
826 return result;
827}
828
829static Curl_recv gtls_recv;
830static Curl_send gtls_send;
831
832CURLcode
833Curl_gtls_verifyserver(struct Curl_easy *data,
834 struct connectdata *conn,
835 gnutls_session_t session,
836 int sockindex)
837{
838 unsigned int cert_list_size;
839 const gnutls_datum_t *chainp;
840 unsigned int verify_status = 0;
841 gnutls_x509_crt_t x509_cert, x509_issuer;
842 gnutls_datum_t issuerp;
843 gnutls_datum_t certfields;
844 char certname[65] = ""; /* limited to 64 chars by ASN.1 */
845 size_t size;
846 time_t certclock;
847 const char *ptr;
848 int rc;
849 gnutls_datum_t proto;
850 CURLcode result = CURLE_OK;
851#ifndef CURL_DISABLE_VERBOSE_STRINGS
852 unsigned int algo;
853 unsigned int bits;
854 gnutls_protocol_t version = gnutls_protocol_get_version(session);
855#endif
856 const char * const hostname = SSL_HOST_NAME();
857 long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
858
859 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
860 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
861 gnutls_cipher_get(session),
862 gnutls_mac_get(session));
863
864 infof(data, "SSL connection using %s / %s",
865 gnutls_protocol_get_name(version), ptr);
866
867 /* This function will return the peer's raw certificate (chain) as sent by
868 the peer. These certificates are in raw format (DER encoded for
869 X.509). In case of a X.509 then a certificate list may be present. The
870 first certificate in the list is the peer's certificate, following the
871 issuer's certificate, then the issuer's issuer etc. */
872
873 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
874 if(!chainp) {
875 if(SSL_CONN_CONFIG(verifypeer) ||
876 SSL_CONN_CONFIG(verifyhost) ||
877 SSL_CONN_CONFIG(issuercert)) {
878#ifdef USE_GNUTLS_SRP
879 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
880 && SSL_SET_OPTION(primary.username)
881 && !SSL_CONN_CONFIG(verifypeer)
882 && gnutls_cipher_get(session)) {
883 /* no peer cert, but auth is ok if we have SRP user and cipher and no
884 peer verify */
885 }
886 else {
887#endif
888 failf(data, "failed to get server cert");
889 *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
890 return CURLE_PEER_FAILED_VERIFICATION;
891#ifdef USE_GNUTLS_SRP
892 }
893#endif
894 }
895 infof(data, " common name: WARNING couldn't obtain");
896 }
897
898 if(data->set.ssl.certinfo && chainp) {
899 unsigned int i;
900
901 result = Curl_ssl_init_certinfo(data, cert_list_size);
902 if(result)
903 return result;
904
905 for(i = 0; i < cert_list_size; i++) {
906 const char *beg = (const char *) chainp[i].data;
907 const char *end = beg + chainp[i].size;
908
909 result = Curl_extract_certinfo(data, i, beg, end);
910 if(result)
911 return result;
912 }
913 }
914
915 if(SSL_CONN_CONFIG(verifypeer)) {
916 /* This function will try to verify the peer's certificate and return its
917 status (trusted, invalid etc.). The value of status should be one or
918 more of the gnutls_certificate_status_t enumerated elements bitwise
919 or'd. To avoid denial of service attacks some default upper limits
920 regarding the certificate key size and chain size are set. To override
921 them use gnutls_certificate_set_verify_limits(). */
922
923 rc = gnutls_certificate_verify_peers2(session, &verify_status);
924 if(rc < 0) {
925 failf(data, "server cert verify failed: %d", rc);
926 *certverifyresult = rc;
927 return CURLE_SSL_CONNECT_ERROR;
928 }
929
930 *certverifyresult = verify_status;
931
932 /* verify_status is a bitmask of gnutls_certificate_status bits */
933 if(verify_status & GNUTLS_CERT_INVALID) {
934 if(SSL_CONN_CONFIG(verifypeer)) {
935 failf(data, "server certificate verification failed. CAfile: %s "
936 "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
937 "none",
938 SSL_SET_OPTION(primary.CRLfile) ?
939 SSL_SET_OPTION(primary.CRLfile) : "none");
940 return CURLE_PEER_FAILED_VERIFICATION;
941 }
942 else
943 infof(data, " server certificate verification FAILED");
944 }
945 else
946 infof(data, " server certificate verification OK");
947 }
948 else
949 infof(data, " server certificate verification SKIPPED");
950
951 if(SSL_CONN_CONFIG(verifystatus)) {
952 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
953 gnutls_datum_t status_request;
954 gnutls_ocsp_resp_t ocsp_resp;
955
956 gnutls_ocsp_cert_status_t status;
957 gnutls_x509_crl_reason_t reason;
958
959 rc = gnutls_ocsp_status_request_get(session, &status_request);
960
961 infof(data, " server certificate status verification FAILED");
962
963 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
964 failf(data, "No OCSP response received");
965 return CURLE_SSL_INVALIDCERTSTATUS;
966 }
967
968 if(rc < 0) {
969 failf(data, "Invalid OCSP response received");
970 return CURLE_SSL_INVALIDCERTSTATUS;
971 }
972
973 gnutls_ocsp_resp_init(&ocsp_resp);
974
975 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
976 if(rc < 0) {
977 failf(data, "Invalid OCSP response received");
978 return CURLE_SSL_INVALIDCERTSTATUS;
979 }
980
981 (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
982 &status, NULL, NULL, NULL, &reason);
983
984 switch(status) {
985 case GNUTLS_OCSP_CERT_GOOD:
986 break;
987
988 case GNUTLS_OCSP_CERT_REVOKED: {
989 const char *crl_reason;
990
991 switch(reason) {
992 default:
993 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
994 crl_reason = "unspecified reason";
995 break;
996
997 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
998 crl_reason = "private key compromised";
999 break;
1000
1001 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1002 crl_reason = "CA compromised";
1003 break;
1004
1005 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1006 crl_reason = "affiliation has changed";
1007 break;
1008
1009 case GNUTLS_X509_CRLREASON_SUPERSEDED:
1010 crl_reason = "certificate superseded";
1011 break;
1012
1013 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1014 crl_reason = "operation has ceased";
1015 break;
1016
1017 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1018 crl_reason = "certificate is on hold";
1019 break;
1020
1021 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1022 crl_reason = "will be removed from delta CRL";
1023 break;
1024
1025 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1026 crl_reason = "privilege withdrawn";
1027 break;
1028
1029 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1030 crl_reason = "AA compromised";
1031 break;
1032 }
1033
1034 failf(data, "Server certificate was revoked: %s", crl_reason);
1035 break;
1036 }
1037
1038 default:
1039 case GNUTLS_OCSP_CERT_UNKNOWN:
1040 failf(data, "Server certificate status is unknown");
1041 break;
1042 }
1043
1044 gnutls_ocsp_resp_deinit(ocsp_resp);
1045
1046 return CURLE_SSL_INVALIDCERTSTATUS;
1047 }
1048 else
1049 infof(data, " server certificate status verification OK");
1050 }
1051 else
1052 infof(data, " server certificate status verification SKIPPED");
1053
1054 /* initialize an X.509 certificate structure. */
1055 gnutls_x509_crt_init(&x509_cert);
1056
1057 if(chainp)
1058 /* convert the given DER or PEM encoded Certificate to the native
1059 gnutls_x509_crt_t format */
1060 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1061
1062 if(SSL_CONN_CONFIG(issuercert)) {
1063 gnutls_x509_crt_init(&x509_issuer);
1064 issuerp = load_file(SSL_CONN_CONFIG(issuercert));
1065 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1066 rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1067 gnutls_x509_crt_deinit(x509_issuer);
1068 unload_file(issuerp);
1069 if(rc <= 0) {
1070 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1071 SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
1072 gnutls_x509_crt_deinit(x509_cert);
1073 return CURLE_SSL_ISSUER_ERROR;
1074 }
1075 infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
1076 SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
1077 }
1078
1079 size = sizeof(certname);
1080 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1081 0, /* the first and only one */
1082 FALSE,
1083 certname,
1084 &size);
1085 if(rc) {
1086 infof(data, "error fetching CN from cert:%s",
1087 gnutls_strerror(rc));
1088 }
1089
1090 /* This function will check if the given certificate's subject matches the
1091 given hostname. This is a basic implementation of the matching described
1092 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1093 alternative name PKIX extension. Returns non zero on success, and zero on
1094 failure. */
1095 rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
1096#if GNUTLS_VERSION_NUMBER < 0x030306
1097 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1098 addresses. */
1099 if(!rc) {
1100#ifdef ENABLE_IPV6
1101 #define use_addr in6_addr
1102#else
1103 #define use_addr in_addr
1104#endif
1105 unsigned char addrbuf[sizeof(struct use_addr)];
1106 size_t addrlen = 0;
1107
1108 if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
1109 addrlen = 4;
1110#ifdef ENABLE_IPV6
1111 else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
1112 addrlen = 16;
1113#endif
1114
1115 if(addrlen) {
1116 unsigned char certaddr[sizeof(struct use_addr)];
1117 int i;
1118
1119 for(i = 0; ; i++) {
1120 size_t certaddrlen = sizeof(certaddr);
1121 int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1122 &certaddrlen, NULL);
1123 /* If this happens, it wasn't an IP address. */
1124 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1125 continue;
1126 if(ret < 0)
1127 break;
1128 if(ret != GNUTLS_SAN_IPADDRESS)
1129 continue;
1130 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1131 rc = 1;
1132 break;
1133 }
1134 }
1135 }
1136 }
1137#endif
1138 if(!rc) {
1139 if(SSL_CONN_CONFIG(verifyhost)) {
1140 failf(data, "SSL: certificate subject name (%s) does not match "
1141 "target host name '%s'", certname, SSL_HOST_DISPNAME());
1142 gnutls_x509_crt_deinit(x509_cert);
1143 return CURLE_PEER_FAILED_VERIFICATION;
1144 }
1145 else
1146 infof(data, " common name: %s (does not match '%s')",
1147 certname, SSL_HOST_DISPNAME());
1148 }
1149 else
1150 infof(data, " common name: %s (matched)", certname);
1151
1152 /* Check for time-based validity */
1153 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1154
1155 if(certclock == (time_t)-1) {
1156 if(SSL_CONN_CONFIG(verifypeer)) {
1157 failf(data, "server cert expiration date verify failed");
1158 *certverifyresult = GNUTLS_CERT_EXPIRED;
1159 gnutls_x509_crt_deinit(x509_cert);
1160 return CURLE_SSL_CONNECT_ERROR;
1161 }
1162 else
1163 infof(data, " server certificate expiration date verify FAILED");
1164 }
1165 else {
1166 if(certclock < time(NULL)) {
1167 if(SSL_CONN_CONFIG(verifypeer)) {
1168 failf(data, "server certificate expiration date has passed.");
1169 *certverifyresult = GNUTLS_CERT_EXPIRED;
1170 gnutls_x509_crt_deinit(x509_cert);
1171 return CURLE_PEER_FAILED_VERIFICATION;
1172 }
1173 else
1174 infof(data, " server certificate expiration date FAILED");
1175 }
1176 else
1177 infof(data, " server certificate expiration date OK");
1178 }
1179
1180 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1181
1182 if(certclock == (time_t)-1) {
1183 if(SSL_CONN_CONFIG(verifypeer)) {
1184 failf(data, "server cert activation date verify failed");
1185 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1186 gnutls_x509_crt_deinit(x509_cert);
1187 return CURLE_SSL_CONNECT_ERROR;
1188 }
1189 else
1190 infof(data, " server certificate activation date verify FAILED");
1191 }
1192 else {
1193 if(certclock > time(NULL)) {
1194 if(SSL_CONN_CONFIG(verifypeer)) {
1195 failf(data, "server certificate not activated yet.");
1196 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1197 gnutls_x509_crt_deinit(x509_cert);
1198 return CURLE_PEER_FAILED_VERIFICATION;
1199 }
1200 else
1201 infof(data, " server certificate activation date FAILED");
1202 }
1203 else
1204 infof(data, " server certificate activation date OK");
1205 }
1206
1207 ptr = SSL_PINNED_PUB_KEY();
1208 if(ptr) {
1209 result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
1210 if(result != CURLE_OK) {
1211 failf(data, "SSL: public key does not match pinned public key");
1212 gnutls_x509_crt_deinit(x509_cert);
1213 return result;
1214 }
1215 }
1216
1217 /* Show:
1218
1219 - subject
1220 - start date
1221 - expire date
1222 - common name
1223 - issuer
1224
1225 */
1226
1227#ifndef CURL_DISABLE_VERBOSE_STRINGS
1228 /* public key algorithm's parameters */
1229 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1230 infof(data, " certificate public key: %s",
1231 gnutls_pk_algorithm_get_name(algo));
1232
1233 /* version of the X.509 certificate. */
1234 infof(data, " certificate version: #%d",
1235 gnutls_x509_crt_get_version(x509_cert));
1236
1237
1238 rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1239 if(rc)
1240 infof(data, "Failed to get certificate name");
1241 else {
1242 infof(data, " subject: %s", certfields.data);
1243
1244 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1245 showtime(data, "start date", certclock);
1246
1247 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1248 showtime(data, "expire date", certclock);
1249
1250 gnutls_free(certfields.data);
1251 }
1252
1253 rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1254 if(rc)
1255 infof(data, "Failed to get certificate issuer");
1256 else {
1257 infof(data, " issuer: %s", certfields.data);
1258
1259 gnutls_free(certfields.data);
1260 }
1261#endif
1262
1263 gnutls_x509_crt_deinit(x509_cert);
1264
1265 if(conn->bits.tls_enable_alpn) {
1266 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1267 if(rc == 0) {
1268 infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, proto.size,
1269 proto.data);
1270
1271#ifdef USE_HTTP2
1272 if(proto.size == ALPN_H2_LENGTH &&
1273 !memcmp(ALPN_H2, proto.data,
1274 ALPN_H2_LENGTH)) {
1275 conn->negnpn = CURL_HTTP_VERSION_2;
1276 }
1277 else
1278#endif
1279 if(proto.size == ALPN_HTTP_1_1_LENGTH &&
1280 !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
1281 conn->negnpn = CURL_HTTP_VERSION_1_1;
1282 }
1283 }
1284 else
1285 infof(data, VTLS_INFOF_NO_ALPN);
1286
1287 Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
1288 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
1289 }
1290
1291 conn->ssl[sockindex].state = ssl_connection_complete;
1292
1293 if(SSL_SET_OPTION(primary.sessionid)) {
1294 /* we always unconditionally get the session id here, as even if we
1295 already got it from the cache and asked to use it in the connection, it
1296 might've been rejected and then a new one is in use now and we need to
1297 detect that. */
1298 void *connect_sessionid;
1299 size_t connect_idsize = 0;
1300
1301 /* get the session ID data size */
1302 gnutls_session_get_data(session, NULL, &connect_idsize);
1303 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1304
1305 if(connect_sessionid) {
1306 bool incache;
1307 bool added = FALSE;
1308 void *ssl_sessionid;
1309
1310 /* extract session ID to the allocated buffer */
1311 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1312
1313 Curl_ssl_sessionid_lock(data);
1314 incache = !(Curl_ssl_getsessionid(data, conn,
1315 SSL_IS_PROXY() ? TRUE : FALSE,
1316 &ssl_sessionid, NULL, sockindex));
1317 if(incache) {
1318 /* there was one before in the cache, so instead of risking that the
1319 previous one was rejected, we just kill that and store the new */
1320 Curl_ssl_delsessionid(data, ssl_sessionid);
1321 }
1322
1323 /* store this session id */
1324 result = Curl_ssl_addsessionid(data, conn,
1325 SSL_IS_PROXY() ? TRUE : FALSE,
1326 connect_sessionid, connect_idsize,
1327 sockindex, &added);
1328 Curl_ssl_sessionid_unlock(data);
1329 if(!added)
1330 free(connect_sessionid);
1331 if(result) {
1332 result = CURLE_OUT_OF_MEMORY;
1333 }
1334 }
1335 else
1336 result = CURLE_OUT_OF_MEMORY;
1337 }
1338
1339 return result;
1340}
1341
1342
1343/*
1344 * This function is called after the TCP connect has completed. Setup the TLS
1345 * layer and do all necessary magic.
1346 */
1347/* We use connssl->connecting_state to keep track of the connection status;
1348 there are three states: 'ssl_connect_1' (not started yet or complete),
1349 'ssl_connect_2_reading' (waiting for data from server), and
1350 'ssl_connect_2_writing' (waiting to be able to write).
1351 */
1352static CURLcode
1353gtls_connect_common(struct Curl_easy *data,
1354 struct connectdata *conn,
1355 int sockindex,
1356 bool nonblocking,
1357 bool *done)
1358{
1359 int rc;
1360 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1361
1362 /* Initiate the connection, if not already done */
1363 if(ssl_connect_1 == connssl->connecting_state) {
1364 rc = gtls_connect_step1(data, conn, sockindex);
1365 if(rc)
1366 return rc;
1367 }
1368
1369 rc = handshake(data, conn, sockindex, TRUE, nonblocking);
1370 if(rc)
1371 /* handshake() sets its own error message with failf() */
1372 return rc;
1373
1374 /* Finish connecting once the handshake is done */
1375 if(ssl_connect_1 == connssl->connecting_state) {
1376 struct ssl_backend_data *backend = connssl->backend;
1377 gnutls_session_t session;
1378 DEBUGASSERT(backend);
1379 session = backend->session;
1380 rc = Curl_gtls_verifyserver(data, conn, session, sockindex);
1381 if(rc)
1382 return rc;
1383 conn->recv[sockindex] = gtls_recv;
1384 conn->send[sockindex] = gtls_send;
1385 }
1386
1387 *done = ssl_connect_1 == connssl->connecting_state;
1388
1389 return CURLE_OK;
1390}
1391
1392static CURLcode gtls_connect_nonblocking(struct Curl_easy *data,
1393 struct connectdata *conn,
1394 int sockindex, bool *done)
1395{
1396 return gtls_connect_common(data, conn, sockindex, TRUE, done);
1397}
1398
1399static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn,
1400 int sockindex)
1401{
1402 CURLcode result;
1403 bool done = FALSE;
1404
1405 result = gtls_connect_common(data, conn, sockindex, FALSE, &done);
1406 if(result)
1407 return result;
1408
1409 DEBUGASSERT(done);
1410
1411 return CURLE_OK;
1412}
1413
1414static bool gtls_data_pending(const struct connectdata *conn,
1415 int connindex)
1416{
1417 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
1418 bool res = FALSE;
1419 struct ssl_backend_data *backend = connssl->backend;
1420
1421 DEBUGASSERT(backend);
1422
1423 if(backend->session &&
1424 0 != gnutls_record_check_pending(backend->session))
1425 res = TRUE;
1426
1427#ifndef CURL_DISABLE_PROXY
1428 connssl = &conn->proxy_ssl[connindex];
1429 backend = connssl->backend;
1430 DEBUGASSERT(backend);
1431 if(backend->session &&
1432 0 != gnutls_record_check_pending(backend->session))
1433 res = TRUE;
1434#endif
1435
1436 return res;
1437}
1438
1439static ssize_t gtls_send(struct Curl_easy *data,
1440 int sockindex,
1441 const void *mem,
1442 size_t len,
1443 CURLcode *curlcode)
1444{
1445 struct connectdata *conn = data->conn;
1446 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1447 struct ssl_backend_data *backend = connssl->backend;
1448 ssize_t rc;
1449
1450 DEBUGASSERT(backend);
1451 rc = gnutls_record_send(backend->session, mem, len);
1452
1453 if(rc < 0) {
1454 *curlcode = (rc == GNUTLS_E_AGAIN)
1455 ? CURLE_AGAIN
1456 : CURLE_SEND_ERROR;
1457
1458 rc = -1;
1459 }
1460
1461 return rc;
1462}
1463
1464static void close_one(struct ssl_connect_data *connssl)
1465{
1466 struct ssl_backend_data *backend = connssl->backend;
1467 DEBUGASSERT(backend);
1468
1469 if(backend->session) {
1470 char buf[32];
1471 /* Maybe the server has already sent a close notify alert.
1472 Read it to avoid an RST on the TCP connection. */
1473 (void)gnutls_record_recv(backend->session, buf, sizeof(buf));
1474 gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1475 gnutls_deinit(backend->session);
1476 backend->session = NULL;
1477 }
1478 if(backend->cred) {
1479 gnutls_certificate_free_credentials(backend->cred);
1480 backend->cred = NULL;
1481 }
1482#ifdef USE_GNUTLS_SRP
1483 if(backend->srp_client_cred) {
1484 gnutls_srp_free_client_credentials(backend->srp_client_cred);
1485 backend->srp_client_cred = NULL;
1486 }
1487#endif
1488}
1489
1490static void gtls_close(struct Curl_easy *data, struct connectdata *conn,
1491 int sockindex)
1492{
1493 (void) data;
1494 close_one(&conn->ssl[sockindex]);
1495#ifndef CURL_DISABLE_PROXY
1496 close_one(&conn->proxy_ssl[sockindex]);
1497#endif
1498}
1499
1500/*
1501 * This function is called to shut down the SSL layer but keep the
1502 * socket open (CCC - Clear Command Channel)
1503 */
1504static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
1505 int sockindex)
1506{
1507 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1508 struct ssl_backend_data *backend = connssl->backend;
1509 int retval = 0;
1510
1511 DEBUGASSERT(backend);
1512
1513#ifndef CURL_DISABLE_FTP
1514 /* This has only been tested on the proftpd server, and the mod_tls code
1515 sends a close notify alert without waiting for a close notify alert in
1516 response. Thus we wait for a close notify alert from the server, but
1517 we do not send one. Let's hope other servers do the same... */
1518
1519 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1520 gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1521#endif
1522
1523 if(backend->session) {
1524 ssize_t result;
1525 bool done = FALSE;
1526 char buf[120];
1527
1528 while(!done) {
1529 int what = SOCKET_READABLE(conn->sock[sockindex],
1530 SSL_SHUTDOWN_TIMEOUT);
1531 if(what > 0) {
1532 /* Something to read, let's do it and hope that it is the close
1533 notify alert from the server */
1534 result = gnutls_record_recv(backend->session,
1535 buf, sizeof(buf));
1536 switch(result) {
1537 case 0:
1538 /* This is the expected response. There was no data but only
1539 the close notify alert */
1540 done = TRUE;
1541 break;
1542 case GNUTLS_E_AGAIN:
1543 case GNUTLS_E_INTERRUPTED:
1544 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED");
1545 break;
1546 default:
1547 retval = -1;
1548 done = TRUE;
1549 break;
1550 }
1551 }
1552 else if(0 == what) {
1553 /* timeout */
1554 failf(data, "SSL shutdown timeout");
1555 done = TRUE;
1556 }
1557 else {
1558 /* anything that gets here is fatally bad */
1559 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1560 retval = -1;
1561 done = TRUE;
1562 }
1563 }
1564 gnutls_deinit(backend->session);
1565 }
1566 gnutls_certificate_free_credentials(backend->cred);
1567
1568#ifdef USE_GNUTLS_SRP
1569 if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
1570 && SSL_SET_OPTION(primary.username) != NULL)
1571 gnutls_srp_free_client_credentials(backend->srp_client_cred);
1572#endif
1573
1574 backend->cred = NULL;
1575 backend->session = NULL;
1576
1577 return retval;
1578}
1579
1580static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
1581 int num, /* socketindex */
1582 char *buf, /* store read data here */
1583 size_t buffersize, /* max amount to read */
1584 CURLcode *curlcode)
1585{
1586 struct connectdata *conn = data->conn;
1587 struct ssl_connect_data *connssl = &conn->ssl[num];
1588 struct ssl_backend_data *backend = connssl->backend;
1589 ssize_t ret;
1590
1591 DEBUGASSERT(backend);
1592
1593 ret = gnutls_record_recv(backend->session, buf, buffersize);
1594 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1595 *curlcode = CURLE_AGAIN;
1596 return -1;
1597 }
1598
1599 if(ret == GNUTLS_E_REHANDSHAKE) {
1600 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1601 proper way" takes a whole lot of work. */
1602 CURLcode result = handshake(data, conn, num, FALSE, FALSE);
1603 if(result)
1604 /* handshake() writes error message on its own */
1605 *curlcode = result;
1606 else
1607 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1608 return -1;
1609 }
1610
1611 if(ret < 0) {
1612 failf(data, "GnuTLS recv error (%d): %s",
1613
1614 (int)ret, gnutls_strerror((int)ret));
1615 *curlcode = CURLE_RECV_ERROR;
1616 return -1;
1617 }
1618
1619 return ret;
1620}
1621
1622static void gtls_session_free(void *ptr)
1623{
1624 free(ptr);
1625}
1626
1627static size_t gtls_version(char *buffer, size_t size)
1628{
1629 return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1630}
1631
1632/* data might be NULL! */
1633static CURLcode gtls_random(struct Curl_easy *data,
1634 unsigned char *entropy, size_t length)
1635{
1636 int rc;
1637 (void)data;
1638 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1639 return rc?CURLE_FAILED_INIT:CURLE_OK;
1640}
1641
1642static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1643 size_t tmplen,
1644 unsigned char *sha256sum, /* output */
1645 size_t sha256len)
1646{
1647 struct sha256_ctx SHA256pw;
1648 sha256_init(&SHA256pw);
1649 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1650 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1651 return CURLE_OK;
1652}
1653
1654static bool gtls_cert_status_request(void)
1655{
1656 return TRUE;
1657}
1658
1659static void *gtls_get_internals(struct ssl_connect_data *connssl,
1660 CURLINFO info UNUSED_PARAM)
1661{
1662 struct ssl_backend_data *backend = connssl->backend;
1663 (void)info;
1664 DEBUGASSERT(backend);
1665 return backend->session;
1666}
1667
1668const struct Curl_ssl Curl_ssl_gnutls = {
1669 { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
1670
1671 SSLSUPP_CA_PATH |
1672 SSLSUPP_CERTINFO |
1673 SSLSUPP_PINNEDPUBKEY |
1674 SSLSUPP_HTTPS_PROXY,
1675
1676 sizeof(struct ssl_backend_data),
1677
1678 gtls_init, /* init */
1679 gtls_cleanup, /* cleanup */
1680 gtls_version, /* version */
1681 Curl_none_check_cxn, /* check_cxn */
1682 gtls_shutdown, /* shutdown */
1683 gtls_data_pending, /* data_pending */
1684 gtls_random, /* random */
1685 gtls_cert_status_request, /* cert_status_request */
1686 gtls_connect, /* connect */
1687 gtls_connect_nonblocking, /* connect_nonblocking */
1688 Curl_ssl_getsock, /* getsock */
1689 gtls_get_internals, /* get_internals */
1690 gtls_close, /* close_one */
1691 Curl_none_close_all, /* close_all */
1692 gtls_session_free, /* session_free */
1693 Curl_none_set_engine, /* set_engine */
1694 Curl_none_set_engine_default, /* set_engine_default */
1695 Curl_none_engines_list, /* engines_list */
1696 Curl_none_false_start, /* false_start */
1697 gtls_sha256sum, /* sha256sum */
1698 NULL, /* associate_connection */
1699 NULL /* disassociate_connection */
1700};
1701
1702#endif /* USE_GNUTLS */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette