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