VirtualBox

source: vbox/trunk/src/libs/curl-7.87.0/lib/vtls/gtls.c@ 98326

最後變更 在這個檔案從98326是 98326,由 vboxsync 提交於 2 年 前

curl-7.87.0: Applied and adjusted our curl changes to 7.83.1. bugref:10356

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

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