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
tls_log_func(int level,const char * str)66 static void tls_log_func(int level, const char *str)
67 {
68 fprintf(stderr, "|<%d>| %s", level, str);
69 }
70 #endif
71 static 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
79 struct gtls_ssl_backend_data {
80 struct gtls_instance gtls;
81 };
82
gtls_push(void * s,const void * buf,size_t blen)83 static 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
gtls_pull(void * s,void * buf,size_t blen)103 static 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 */
gtls_init(void)130 static 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
gtls_cleanup(void)144 static 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
showtime(struct Curl_easy * data,const char * text,time_t stamp)153 static 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
load_file(const char * file)179 static 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;
201 out:
202 fclose(f);
203 return loaded_file;
204 }
205
unload_file(gnutls_datum_t data)206 static void unload_file(gnutls_datum_t data)
207 {
208 free(data.data);
209 }
210
211
212 /* this function does a SSL/TLS (re-)handshake */
handshake(struct Curl_cfilter * cf,struct Curl_easy * data,bool duringconnect,bool nonblocking)213 static 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
do_file_type(const char * type)312 static 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
329 static CURLcode
set_ssl_version_min_max(struct Curl_easy * data,struct ssl_primary_config * conn_config,const char ** prioritylist,const char * tls13support)330 set_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
gtls_client_init(struct Curl_easy * data,struct ssl_primary_config * config,struct ssl_config_data * ssl_config,struct ssl_peer * peer,struct gtls_instance * gtls,long * pverifyresult)402 CURLcode gtls_client_init(struct Curl_easy *data,
403 struct ssl_primary_config *config,
404 struct ssl_config_data *ssl_config,
405 struct ssl_peer *peer,
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 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(>ls->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->username && Curl_auth_allowed_to_host(data)) {
438 infof(data, "Using TLS-SRP username: %s", config->username);
439
440 rc = gnutls_srp_allocate_client_credentials(>ls->srp_client_cred);
441 if(rc != GNUTLS_E_SUCCESS) {
442 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
443 gnutls_strerror(rc));
444 return CURLE_OUT_OF_MEMORY;
445 }
446
447 rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
448 config->username,
449 config->password);
450 if(rc != GNUTLS_E_SUCCESS) {
451 failf(data, "gnutls_srp_set_client_cred() failed: %s",
452 gnutls_strerror(rc));
453 return CURLE_BAD_FUNCTION_ARGUMENT;
454 }
455 }
456 #endif
457
458 if(config->verifypeer) {
459 bool imported_native_ca = false;
460
461 if(ssl_config->native_ca_store) {
462 rc = gnutls_certificate_set_x509_system_trust(gtls->cred);
463 if(rc < 0)
464 infof(data, "error reading native ca store (%s), continuing anyway",
465 gnutls_strerror(rc));
466 else {
467 infof(data, "found %d certificates in native ca store", rc);
468 if(rc > 0)
469 imported_native_ca = true;
470 }
471 }
472
473 if(config->CAfile) {
474 /* set the trusted CA cert bundle file */
475 gnutls_certificate_set_verify_flags(gtls->cred,
476 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
477
478 rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
479 config->CAfile,
480 GNUTLS_X509_FMT_PEM);
481 if(rc < 0) {
482 infof(data, "error reading ca cert file %s (%s)%s",
483 config->CAfile, gnutls_strerror(rc),
484 (imported_native_ca ? ", continuing anyway" : ""));
485 if(!imported_native_ca) {
486 *pverifyresult = rc;
487 return CURLE_SSL_CACERT_BADFILE;
488 }
489 }
490 else
491 infof(data, "found %d certificates in %s", rc, config->CAfile);
492 }
493
494 if(config->CApath) {
495 /* set the trusted CA cert directory */
496 rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
497 config->CApath,
498 GNUTLS_X509_FMT_PEM);
499 if(rc < 0) {
500 infof(data, "error reading ca cert file %s (%s)%s",
501 config->CApath, gnutls_strerror(rc),
502 (imported_native_ca ? ", continuing anyway" : ""));
503 if(!imported_native_ca) {
504 *pverifyresult = rc;
505 return CURLE_SSL_CACERT_BADFILE;
506 }
507 }
508 else
509 infof(data, "found %d certificates in %s", rc, config->CApath);
510 }
511 }
512
513 if(config->CRLfile) {
514 /* set the CRL list file */
515 rc = gnutls_certificate_set_x509_crl_file(gtls->cred,
516 config->CRLfile,
517 GNUTLS_X509_FMT_PEM);
518 if(rc < 0) {
519 failf(data, "error reading crl file %s (%s)",
520 config->CRLfile, gnutls_strerror(rc));
521 return CURLE_SSL_CRL_BADFILE;
522 }
523 else
524 infof(data, "found %d CRL in %s", rc, config->CRLfile);
525 }
526
527 /* Initialize TLS session as a client */
528 init_flags = GNUTLS_CLIENT;
529
530 #if defined(GNUTLS_FORCE_CLIENT_CERT)
531 init_flags |= GNUTLS_FORCE_CLIENT_CERT;
532 #endif
533
534 #if defined(GNUTLS_NO_TICKETS)
535 /* Disable TLS session tickets */
536 init_flags |= GNUTLS_NO_TICKETS;
537 #endif
538
539 rc = gnutls_init(>ls->session, init_flags);
540 if(rc != GNUTLS_E_SUCCESS) {
541 failf(data, "gnutls_init() failed: %d", rc);
542 return CURLE_SSL_CONNECT_ERROR;
543 }
544
545 if(sni && peer->sni) {
546 if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
547 peer->sni, strlen(peer->sni)) < 0) {
548 failf(data, "Failed to set SNI");
549 return CURLE_SSL_CONNECT_ERROR;
550 }
551 }
552
553 /* Use default priorities */
554 rc = gnutls_set_default_priority(gtls->session);
555 if(rc != GNUTLS_E_SUCCESS)
556 return CURLE_SSL_CONNECT_ERROR;
557
558 /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
559 tls13support = gnutls_check_version("3.6.5");
560
561 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
562 * removed if a run-time error indicates that SRP is not supported by this
563 * GnuTLS version */
564
565 if(config->version == CURL_SSLVERSION_SSLv2 ||
566 config->version == CURL_SSLVERSION_SSLv3) {
567 failf(data, "GnuTLS does not support SSLv2 or SSLv3");
568 return CURLE_SSL_CONNECT_ERROR;
569 }
570
571 if(config->version == CURL_SSLVERSION_TLSv1_3) {
572 if(!tls13support) {
573 failf(data, "This GnuTLS installation does not support TLS 1.3");
574 return CURLE_SSL_CONNECT_ERROR;
575 }
576 }
577
578 /* At this point we know we have a supported TLS version, so set it */
579 result = set_ssl_version_min_max(data, config, &prioritylist, tls13support);
580 if(result)
581 return result;
582
583 #ifdef USE_GNUTLS_SRP
584 /* Only add SRP to the cipher list if SRP is requested. Otherwise
585 * GnuTLS will disable TLS 1.3 support. */
586 if(config->username) {
587 char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
588 if(!prioritysrp)
589 return CURLE_OUT_OF_MEMORY;
590 rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
591 free(prioritysrp);
592
593 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
594 infof(data, "This GnuTLS does not support SRP");
595 }
596 }
597 else {
598 #endif
599 infof(data, "GnuTLS ciphers: %s", prioritylist);
600 rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
601 #ifdef USE_GNUTLS_SRP
602 }
603 #endif
604
605 if(rc != GNUTLS_E_SUCCESS) {
606 failf(data, "Error %d setting GnuTLS cipher list starting with %s",
607 rc, err);
608 return CURLE_SSL_CONNECT_ERROR;
609 }
610
611 if(config->clientcert) {
612 if(ssl_config->key_passwd) {
613 const unsigned int supported_key_encryption_algorithms =
614 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
615 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
616 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
617 GNUTLS_PKCS_USE_PBES2_AES_256;
618 rc = gnutls_certificate_set_x509_key_file2(
619 gtls->cred,
620 config->clientcert,
621 ssl_config->key ? ssl_config->key : config->clientcert,
622 do_file_type(ssl_config->cert_type),
623 ssl_config->key_passwd,
624 supported_key_encryption_algorithms);
625 if(rc != GNUTLS_E_SUCCESS) {
626 failf(data,
627 "error reading X.509 potentially-encrypted key file: %s",
628 gnutls_strerror(rc));
629 return CURLE_SSL_CONNECT_ERROR;
630 }
631 }
632 else {
633 if(gnutls_certificate_set_x509_key_file(
634 gtls->cred,
635 config->clientcert,
636 ssl_config->key ? ssl_config->key : config->clientcert,
637 do_file_type(ssl_config->cert_type) ) !=
638 GNUTLS_E_SUCCESS) {
639 failf(data, "error reading X.509 key or certificate file");
640 return CURLE_SSL_CONNECT_ERROR;
641 }
642 }
643 }
644
645 #ifdef USE_GNUTLS_SRP
646 /* put the credentials to the current session */
647 if(config->username) {
648 rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
649 gtls->srp_client_cred);
650 if(rc != GNUTLS_E_SUCCESS) {
651 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
652 return CURLE_SSL_CONNECT_ERROR;
653 }
654 }
655 else
656 #endif
657 {
658 rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
659 gtls->cred);
660 if(rc != GNUTLS_E_SUCCESS) {
661 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
662 return CURLE_SSL_CONNECT_ERROR;
663 }
664 }
665
666 if(config->verifystatus) {
667 rc = gnutls_ocsp_status_request_enable_client(gtls->session,
668 NULL, 0, NULL);
669 if(rc != GNUTLS_E_SUCCESS) {
670 failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
671 return CURLE_SSL_CONNECT_ERROR;
672 }
673 }
674
675 return CURLE_OK;
676 }
677
678 static CURLcode
gtls_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)679 gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
680 {
681 struct ssl_connect_data *connssl = cf->ctx;
682 struct gtls_ssl_backend_data *backend =
683 (struct gtls_ssl_backend_data *)connssl->backend;
684 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
685 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
686 long * const pverifyresult = &ssl_config->certverifyresult;
687 CURLcode result;
688
689 DEBUGASSERT(backend);
690
691 if(connssl->state == ssl_connection_complete)
692 /* to make us tolerant against being called more than once for the
693 same connection */
694 return CURLE_OK;
695
696 result = gtls_client_init(data, conn_config, ssl_config,
697 &connssl->peer,
698 &backend->gtls, pverifyresult);
699 if(result)
700 return result;
701
702 if(connssl->alpn) {
703 struct alpn_proto_buf proto;
704 gnutls_datum_t alpn[ALPN_ENTRIES_MAX];
705 size_t i;
706
707 for(i = 0; i < connssl->alpn->count; ++i) {
708 alpn[i].data = (unsigned char *)connssl->alpn->entries[i];
709 alpn[i].size = (unsigned)strlen(connssl->alpn->entries[i]);
710 }
711 if(gnutls_alpn_set_protocols(backend->gtls.session, alpn,
712 (unsigned)connssl->alpn->count, 0)) {
713 failf(data, "failed setting ALPN");
714 return CURLE_SSL_CONNECT_ERROR;
715 }
716 Curl_alpn_to_proto_str(&proto, connssl->alpn);
717 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
718 }
719
720 /* This might be a reconnect, so we check for a session ID in the cache
721 to speed up things */
722 if(conn_config->sessionid) {
723 void *ssl_sessionid;
724 size_t ssl_idsize;
725
726 Curl_ssl_sessionid_lock(data);
727 if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, &ssl_idsize)) {
728 /* we got a session id, use it! */
729 gnutls_session_set_data(backend->gtls.session,
730 ssl_sessionid, ssl_idsize);
731
732 /* Informational message */
733 infof(data, "SSL reusing session ID");
734 }
735 Curl_ssl_sessionid_unlock(data);
736 }
737
738 /* register callback functions and handle to send and receive data. */
739 gnutls_transport_set_ptr(backend->gtls.session, cf);
740 gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
741 gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
742
743 return CURLE_OK;
744 }
745
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)746 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
747 gnutls_x509_crt_t cert,
748 const char *pinnedpubkey)
749 {
750 /* Scratch */
751 size_t len1 = 0, len2 = 0;
752 unsigned char *buff1 = NULL;
753
754 gnutls_pubkey_t key = NULL;
755
756 /* Result is returned to caller */
757 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
758
759 /* if a path wasn't specified, don't pin */
760 if(!pinnedpubkey)
761 return CURLE_OK;
762
763 if(!cert)
764 return result;
765
766 do {
767 int ret;
768
769 /* Begin Gyrations to get the public key */
770 gnutls_pubkey_init(&key);
771
772 ret = gnutls_pubkey_import_x509(key, cert, 0);
773 if(ret < 0)
774 break; /* failed */
775
776 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
777 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
778 break; /* failed */
779
780 buff1 = malloc(len1);
781 if(!buff1)
782 break; /* failed */
783
784 len2 = len1;
785
786 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
787 if(ret < 0 || len1 != len2)
788 break; /* failed */
789
790 /* End Gyrations */
791
792 /* The one good exit point */
793 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
794 } while(0);
795
796 if(key)
797 gnutls_pubkey_deinit(key);
798
799 Curl_safefree(buff1);
800
801 return result;
802 }
803
804 CURLcode
Curl_gtls_verifyserver(struct Curl_easy * data,gnutls_session_t session,struct ssl_primary_config * config,struct ssl_config_data * ssl_config,struct ssl_peer * peer,const char * pinned_key)805 Curl_gtls_verifyserver(struct Curl_easy *data,
806 gnutls_session_t session,
807 struct ssl_primary_config *config,
808 struct ssl_config_data *ssl_config,
809 struct ssl_peer *peer,
810 const char *pinned_key)
811 {
812 unsigned int cert_list_size;
813 const gnutls_datum_t *chainp;
814 unsigned int verify_status = 0;
815 gnutls_x509_crt_t x509_cert, x509_issuer;
816 gnutls_datum_t issuerp;
817 gnutls_datum_t certfields;
818 char certname[65] = ""; /* limited to 64 chars by ASN.1 */
819 size_t size;
820 time_t certclock;
821 int rc;
822 CURLcode result = CURLE_OK;
823 #ifndef CURL_DISABLE_VERBOSE_STRINGS
824 const char *ptr;
825 unsigned int algo;
826 unsigned int bits;
827 gnutls_protocol_t version = gnutls_protocol_get_version(session);
828 #endif
829 long * const certverifyresult = &ssl_config->certverifyresult;
830
831 #ifndef CURL_DISABLE_VERBOSE_STRINGS
832 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
833 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
834 gnutls_cipher_get(session),
835 gnutls_mac_get(session));
836
837 infof(data, "SSL connection using %s / %s",
838 gnutls_protocol_get_name(version), ptr);
839 #endif
840
841 /* This function will return the peer's raw certificate (chain) as sent by
842 the peer. These certificates are in raw format (DER encoded for
843 X.509). In case of a X.509 then a certificate list may be present. The
844 first certificate in the list is the peer's certificate, following the
845 issuer's certificate, then the issuer's issuer etc. */
846
847 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
848 if(!chainp) {
849 if(config->verifypeer ||
850 config->verifyhost ||
851 config->issuercert) {
852 #ifdef USE_GNUTLS_SRP
853 if(ssl_config->primary.username && !config->verifypeer &&
854 gnutls_cipher_get(session)) {
855 /* no peer cert, but auth is ok if we have SRP user and cipher and no
856 peer verify */
857 }
858 else {
859 #endif
860 failf(data, "failed to get server cert");
861 *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
862 return CURLE_PEER_FAILED_VERIFICATION;
863 #ifdef USE_GNUTLS_SRP
864 }
865 #endif
866 }
867 infof(data, " common name: WARNING couldn't obtain");
868 }
869
870 if(data->set.ssl.certinfo && chainp) {
871 unsigned int i;
872
873 result = Curl_ssl_init_certinfo(data, cert_list_size);
874 if(result)
875 return result;
876
877 for(i = 0; i < cert_list_size; i++) {
878 const char *beg = (const char *) chainp[i].data;
879 const char *end = beg + chainp[i].size;
880
881 result = Curl_extract_certinfo(data, i, beg, end);
882 if(result)
883 return result;
884 }
885 }
886
887 if(config->verifypeer) {
888 /* This function will try to verify the peer's certificate and return its
889 status (trusted, invalid etc.). The value of status should be one or
890 more of the gnutls_certificate_status_t enumerated elements bitwise
891 or'd. To avoid denial of service attacks some default upper limits
892 regarding the certificate key size and chain size are set. To override
893 them use gnutls_certificate_set_verify_limits(). */
894
895 rc = gnutls_certificate_verify_peers2(session, &verify_status);
896 if(rc < 0) {
897 failf(data, "server cert verify failed: %d", rc);
898 *certverifyresult = rc;
899 return CURLE_SSL_CONNECT_ERROR;
900 }
901
902 *certverifyresult = verify_status;
903
904 /* verify_status is a bitmask of gnutls_certificate_status bits */
905 if(verify_status & GNUTLS_CERT_INVALID) {
906 if(config->verifypeer) {
907 failf(data, "server certificate verification failed. CAfile: %s "
908 "CRLfile: %s", config->CAfile ? config->CAfile:
909 "none",
910 ssl_config->primary.CRLfile ?
911 ssl_config->primary.CRLfile : "none");
912 return CURLE_PEER_FAILED_VERIFICATION;
913 }
914 else
915 infof(data, " server certificate verification FAILED");
916 }
917 else
918 infof(data, " server certificate verification OK");
919 }
920 else
921 infof(data, " server certificate verification SKIPPED");
922
923 if(config->verifystatus) {
924 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
925 gnutls_datum_t status_request;
926 gnutls_ocsp_resp_t ocsp_resp;
927
928 gnutls_ocsp_cert_status_t status;
929 gnutls_x509_crl_reason_t reason;
930
931 rc = gnutls_ocsp_status_request_get(session, &status_request);
932
933 infof(data, " server certificate status verification FAILED");
934
935 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
936 failf(data, "No OCSP response received");
937 return CURLE_SSL_INVALIDCERTSTATUS;
938 }
939
940 if(rc < 0) {
941 failf(data, "Invalid OCSP response received");
942 return CURLE_SSL_INVALIDCERTSTATUS;
943 }
944
945 gnutls_ocsp_resp_init(&ocsp_resp);
946
947 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
948 if(rc < 0) {
949 failf(data, "Invalid OCSP response received");
950 return CURLE_SSL_INVALIDCERTSTATUS;
951 }
952
953 (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
954 &status, NULL, NULL, NULL, &reason);
955
956 switch(status) {
957 case GNUTLS_OCSP_CERT_GOOD:
958 break;
959
960 case GNUTLS_OCSP_CERT_REVOKED: {
961 const char *crl_reason;
962
963 switch(reason) {
964 default:
965 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
966 crl_reason = "unspecified reason";
967 break;
968
969 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
970 crl_reason = "private key compromised";
971 break;
972
973 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
974 crl_reason = "CA compromised";
975 break;
976
977 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
978 crl_reason = "affiliation has changed";
979 break;
980
981 case GNUTLS_X509_CRLREASON_SUPERSEDED:
982 crl_reason = "certificate superseded";
983 break;
984
985 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
986 crl_reason = "operation has ceased";
987 break;
988
989 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
990 crl_reason = "certificate is on hold";
991 break;
992
993 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
994 crl_reason = "will be removed from delta CRL";
995 break;
996
997 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
998 crl_reason = "privilege withdrawn";
999 break;
1000
1001 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1002 crl_reason = "AA compromised";
1003 break;
1004 }
1005
1006 failf(data, "Server certificate was revoked: %s", crl_reason);
1007 break;
1008 }
1009
1010 default:
1011 case GNUTLS_OCSP_CERT_UNKNOWN:
1012 failf(data, "Server certificate status is unknown");
1013 break;
1014 }
1015
1016 gnutls_ocsp_resp_deinit(ocsp_resp);
1017
1018 return CURLE_SSL_INVALIDCERTSTATUS;
1019 }
1020 else
1021 infof(data, " server certificate status verification OK");
1022 }
1023 else
1024 infof(data, " server certificate status verification SKIPPED");
1025
1026 /* initialize an X.509 certificate structure. */
1027 gnutls_x509_crt_init(&x509_cert);
1028
1029 if(chainp)
1030 /* convert the given DER or PEM encoded Certificate to the native
1031 gnutls_x509_crt_t format */
1032 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1033
1034 if(config->issuercert) {
1035 gnutls_x509_crt_init(&x509_issuer);
1036 issuerp = load_file(config->issuercert);
1037 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1038 rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1039 gnutls_x509_crt_deinit(x509_issuer);
1040 unload_file(issuerp);
1041 if(rc <= 0) {
1042 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1043 config->issuercert?config->issuercert:"none");
1044 gnutls_x509_crt_deinit(x509_cert);
1045 return CURLE_SSL_ISSUER_ERROR;
1046 }
1047 infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
1048 config->issuercert?config->issuercert:"none");
1049 }
1050
1051 size = sizeof(certname);
1052 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1053 0, /* the first and only one */
1054 FALSE,
1055 certname,
1056 &size);
1057 if(rc) {
1058 infof(data, "error fetching CN from cert:%s",
1059 gnutls_strerror(rc));
1060 }
1061
1062 /* This function will check if the given certificate's subject matches the
1063 given hostname. This is a basic implementation of the matching described
1064 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1065 alternative name PKIX extension. Returns non zero on success, and zero on
1066 failure. */
1067 rc = gnutls_x509_crt_check_hostname(x509_cert, peer->hostname);
1068 #if GNUTLS_VERSION_NUMBER < 0x030306
1069 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1070 addresses. */
1071 if(!rc) {
1072 #ifdef ENABLE_IPV6
1073 #define use_addr in6_addr
1074 #else
1075 #define use_addr in_addr
1076 #endif
1077 unsigned char addrbuf[sizeof(struct use_addr)];
1078 size_t addrlen = 0;
1079
1080 if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
1081 addrlen = 4;
1082 #ifdef ENABLE_IPV6
1083 else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
1084 addrlen = 16;
1085 #endif
1086
1087 if(addrlen) {
1088 unsigned char certaddr[sizeof(struct use_addr)];
1089 int i;
1090
1091 for(i = 0; ; i++) {
1092 size_t certaddrlen = sizeof(certaddr);
1093 int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1094 &certaddrlen, NULL);
1095 /* If this happens, it wasn't an IP address. */
1096 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1097 continue;
1098 if(ret < 0)
1099 break;
1100 if(ret != GNUTLS_SAN_IPADDRESS)
1101 continue;
1102 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1103 rc = 1;
1104 break;
1105 }
1106 }
1107 }
1108 }
1109 #endif
1110 if(!rc) {
1111 if(config->verifyhost) {
1112 failf(data, "SSL: certificate subject name (%s) does not match "
1113 "target host name '%s'", certname, peer->dispname);
1114 gnutls_x509_crt_deinit(x509_cert);
1115 return CURLE_PEER_FAILED_VERIFICATION;
1116 }
1117 else
1118 infof(data, " common name: %s (does not match '%s')",
1119 certname, peer->dispname);
1120 }
1121 else
1122 infof(data, " common name: %s (matched)", certname);
1123
1124 /* Check for time-based validity */
1125 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1126
1127 if(certclock == (time_t)-1) {
1128 if(config->verifypeer) {
1129 failf(data, "server cert expiration date verify failed");
1130 *certverifyresult = GNUTLS_CERT_EXPIRED;
1131 gnutls_x509_crt_deinit(x509_cert);
1132 return CURLE_SSL_CONNECT_ERROR;
1133 }
1134 else
1135 infof(data, " server certificate expiration date verify FAILED");
1136 }
1137 else {
1138 if(certclock < time(NULL)) {
1139 if(config->verifypeer) {
1140 failf(data, "server certificate expiration date has passed.");
1141 *certverifyresult = GNUTLS_CERT_EXPIRED;
1142 gnutls_x509_crt_deinit(x509_cert);
1143 return CURLE_PEER_FAILED_VERIFICATION;
1144 }
1145 else
1146 infof(data, " server certificate expiration date FAILED");
1147 }
1148 else
1149 infof(data, " server certificate expiration date OK");
1150 }
1151
1152 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1153
1154 if(certclock == (time_t)-1) {
1155 if(config->verifypeer) {
1156 failf(data, "server cert activation date verify failed");
1157 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1158 gnutls_x509_crt_deinit(x509_cert);
1159 return CURLE_SSL_CONNECT_ERROR;
1160 }
1161 else
1162 infof(data, " server certificate activation date verify FAILED");
1163 }
1164 else {
1165 if(certclock > time(NULL)) {
1166 if(config->verifypeer) {
1167 failf(data, "server certificate not activated yet.");
1168 *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1169 gnutls_x509_crt_deinit(x509_cert);
1170 return CURLE_PEER_FAILED_VERIFICATION;
1171 }
1172 else
1173 infof(data, " server certificate activation date FAILED");
1174 }
1175 else
1176 infof(data, " server certificate activation date OK");
1177 }
1178
1179 if(pinned_key) {
1180 result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
1181 if(result != CURLE_OK) {
1182 failf(data, "SSL: public key does not match pinned public key");
1183 gnutls_x509_crt_deinit(x509_cert);
1184 return result;
1185 }
1186 }
1187
1188 /* Show:
1189
1190 - subject
1191 - start date
1192 - expire date
1193 - common name
1194 - issuer
1195
1196 */
1197
1198 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1199 /* public key algorithm's parameters */
1200 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1201 infof(data, " certificate public key: %s",
1202 gnutls_pk_algorithm_get_name(algo));
1203
1204 /* version of the X.509 certificate. */
1205 infof(data, " certificate version: #%d",
1206 gnutls_x509_crt_get_version(x509_cert));
1207
1208
1209 rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1210 if(rc)
1211 infof(data, "Failed to get certificate name");
1212 else {
1213 infof(data, " subject: %s", certfields.data);
1214
1215 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1216 showtime(data, "start date", certclock);
1217
1218 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1219 showtime(data, "expire date", certclock);
1220
1221 gnutls_free(certfields.data);
1222 }
1223
1224 rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1225 if(rc)
1226 infof(data, "Failed to get certificate issuer");
1227 else {
1228 infof(data, " issuer: %s", certfields.data);
1229
1230 gnutls_free(certfields.data);
1231 }
1232 #endif
1233
1234 gnutls_x509_crt_deinit(x509_cert);
1235
1236 return result;
1237 }
1238
gtls_verifyserver(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)1239 static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
1240 struct Curl_easy *data,
1241 gnutls_session_t session)
1242 {
1243 struct ssl_connect_data *connssl = cf->ctx;
1244 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1245 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1246 const char *pinned_key = Curl_ssl_cf_is_proxy(cf)?
1247 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
1248 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1249 CURLcode result;
1250
1251 result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
1252 &connssl->peer, pinned_key);
1253 if(result)
1254 goto out;
1255
1256 if(connssl->alpn) {
1257 gnutls_datum_t proto;
1258 int rc;
1259
1260 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1261 if(rc == 0)
1262 Curl_alpn_set_negotiated(cf, data, proto.data, proto.size);
1263 else
1264 Curl_alpn_set_negotiated(cf, data, NULL, 0);
1265 }
1266
1267 if(ssl_config->primary.sessionid) {
1268 /* we always unconditionally get the session id here, as even if we
1269 already got it from the cache and asked to use it in the connection, it
1270 might've been rejected and then a new one is in use now and we need to
1271 detect that. */
1272 void *connect_sessionid;
1273 size_t connect_idsize = 0;
1274
1275 /* get the session ID data size */
1276 gnutls_session_get_data(session, NULL, &connect_idsize);
1277 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1278
1279 if(connect_sessionid) {
1280 bool incache;
1281 bool added = FALSE;
1282 void *ssl_sessionid;
1283
1284 /* extract session ID to the allocated buffer */
1285 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1286
1287 Curl_ssl_sessionid_lock(data);
1288 incache = !(Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL));
1289 if(incache) {
1290 /* there was one before in the cache, so instead of risking that the
1291 previous one was rejected, we just kill that and store the new */
1292 Curl_ssl_delsessionid(data, ssl_sessionid);
1293 }
1294
1295 /* store this session id */
1296 result = Curl_ssl_addsessionid(cf, data, connect_sessionid,
1297 connect_idsize, &added);
1298 Curl_ssl_sessionid_unlock(data);
1299 if(!added)
1300 free(connect_sessionid);
1301 if(result) {
1302 result = CURLE_OUT_OF_MEMORY;
1303 }
1304 }
1305 else
1306 result = CURLE_OUT_OF_MEMORY;
1307 }
1308
1309 out:
1310 return result;
1311 }
1312
1313 /*
1314 * This function is called after the TCP connect has completed. Setup the TLS
1315 * layer and do all necessary magic.
1316 */
1317 /* We use connssl->connecting_state to keep track of the connection status;
1318 there are three states: 'ssl_connect_1' (not started yet or complete),
1319 'ssl_connect_2_reading' (waiting for data from server), and
1320 'ssl_connect_2_writing' (waiting to be able to write).
1321 */
1322 static CURLcode
gtls_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1323 gtls_connect_common(struct Curl_cfilter *cf,
1324 struct Curl_easy *data,
1325 bool nonblocking,
1326 bool *done)
1327 {
1328 struct ssl_connect_data *connssl = cf->ctx;
1329 int rc;
1330 CURLcode result = CURLE_OK;
1331
1332 /* Initiate the connection, if not already done */
1333 if(ssl_connect_1 == connssl->connecting_state) {
1334 rc = gtls_connect_step1(cf, data);
1335 if(rc) {
1336 result = rc;
1337 goto out;
1338 }
1339 }
1340
1341 rc = handshake(cf, data, TRUE, nonblocking);
1342 if(rc) {
1343 /* handshake() sets its own error message with failf() */
1344 result = rc;
1345 goto out;
1346 }
1347
1348 /* Finish connecting once the handshake is done */
1349 if(ssl_connect_1 == connssl->connecting_state) {
1350 struct gtls_ssl_backend_data *backend =
1351 (struct gtls_ssl_backend_data *)connssl->backend;
1352 gnutls_session_t session;
1353 DEBUGASSERT(backend);
1354 session = backend->gtls.session;
1355 rc = gtls_verifyserver(cf, data, session);
1356 if(rc) {
1357 result = rc;
1358 goto out;
1359 }
1360 connssl->state = ssl_connection_complete;
1361 }
1362
1363 out:
1364 *done = ssl_connect_1 == connssl->connecting_state;
1365
1366 return result;
1367 }
1368
gtls_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1369 static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
1370 struct Curl_easy *data,
1371 bool *done)
1372 {
1373 return gtls_connect_common(cf, data, TRUE, done);
1374 }
1375
gtls_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1376 static CURLcode gtls_connect(struct Curl_cfilter *cf,
1377 struct Curl_easy *data)
1378 {
1379 CURLcode result;
1380 bool done = FALSE;
1381
1382 result = gtls_connect_common(cf, data, FALSE, &done);
1383 if(result)
1384 return result;
1385
1386 DEBUGASSERT(done);
1387
1388 return CURLE_OK;
1389 }
1390
gtls_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1391 static bool gtls_data_pending(struct Curl_cfilter *cf,
1392 const struct Curl_easy *data)
1393 {
1394 struct ssl_connect_data *ctx = cf->ctx;
1395 struct gtls_ssl_backend_data *backend;
1396
1397 (void)data;
1398 DEBUGASSERT(ctx && ctx->backend);
1399 backend = (struct gtls_ssl_backend_data *)ctx->backend;
1400 if(backend->gtls.session &&
1401 0 != gnutls_record_check_pending(backend->gtls.session))
1402 return TRUE;
1403 return FALSE;
1404 }
1405
gtls_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * mem,size_t len,CURLcode * curlcode)1406 static ssize_t gtls_send(struct Curl_cfilter *cf,
1407 struct Curl_easy *data,
1408 const void *mem,
1409 size_t len,
1410 CURLcode *curlcode)
1411 {
1412 struct ssl_connect_data *connssl = cf->ctx;
1413 struct gtls_ssl_backend_data *backend =
1414 (struct gtls_ssl_backend_data *)connssl->backend;
1415 ssize_t rc;
1416
1417 (void)data;
1418 DEBUGASSERT(backend);
1419 rc = gnutls_record_send(backend->gtls.session, mem, len);
1420
1421 if(rc < 0) {
1422 *curlcode = (rc == GNUTLS_E_AGAIN)
1423 ? CURLE_AGAIN
1424 : CURLE_SEND_ERROR;
1425
1426 rc = -1;
1427 }
1428
1429 return rc;
1430 }
1431
gtls_close(struct Curl_cfilter * cf,struct Curl_easy * data)1432 static void gtls_close(struct Curl_cfilter *cf,
1433 struct Curl_easy *data)
1434 {
1435 struct ssl_connect_data *connssl = cf->ctx;
1436 struct gtls_ssl_backend_data *backend =
1437 (struct gtls_ssl_backend_data *)connssl->backend;
1438
1439 (void) data;
1440 DEBUGASSERT(backend);
1441
1442 if(backend->gtls.session) {
1443 char buf[32];
1444 /* Maybe the server has already sent a close notify alert.
1445 Read it to avoid an RST on the TCP connection. */
1446 (void)gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
1447 gnutls_bye(backend->gtls.session, GNUTLS_SHUT_WR);
1448 gnutls_deinit(backend->gtls.session);
1449 backend->gtls.session = NULL;
1450 }
1451 if(backend->gtls.cred) {
1452 gnutls_certificate_free_credentials(backend->gtls.cred);
1453 backend->gtls.cred = NULL;
1454 }
1455 #ifdef USE_GNUTLS_SRP
1456 if(backend->gtls.srp_client_cred) {
1457 gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1458 backend->gtls.srp_client_cred = NULL;
1459 }
1460 #endif
1461 }
1462
1463 /*
1464 * This function is called to shut down the SSL layer but keep the
1465 * socket open (CCC - Clear Command Channel)
1466 */
gtls_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data)1467 static int gtls_shutdown(struct Curl_cfilter *cf,
1468 struct Curl_easy *data)
1469 {
1470 struct ssl_connect_data *connssl = cf->ctx;
1471 struct gtls_ssl_backend_data *backend =
1472 (struct gtls_ssl_backend_data *)connssl->backend;
1473 int retval = 0;
1474
1475 DEBUGASSERT(backend);
1476
1477 #ifndef CURL_DISABLE_FTP
1478 /* This has only been tested on the proftpd server, and the mod_tls code
1479 sends a close notify alert without waiting for a close notify alert in
1480 response. Thus we wait for a close notify alert from the server, but
1481 we do not send one. Let's hope other servers do the same... */
1482
1483 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1484 gnutls_bye(backend->gtls.session, GNUTLS_SHUT_WR);
1485 #endif
1486
1487 if(backend->gtls.session) {
1488 ssize_t result;
1489 bool done = FALSE;
1490 char buf[120];
1491
1492 while(!done) {
1493 int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
1494 SSL_SHUTDOWN_TIMEOUT);
1495 if(what > 0) {
1496 /* Something to read, let's do it and hope that it is the close
1497 notify alert from the server */
1498 result = gnutls_record_recv(backend->gtls.session,
1499 buf, sizeof(buf));
1500 switch(result) {
1501 case 0:
1502 /* This is the expected response. There was no data but only
1503 the close notify alert */
1504 done = TRUE;
1505 break;
1506 case GNUTLS_E_AGAIN:
1507 case GNUTLS_E_INTERRUPTED:
1508 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED");
1509 break;
1510 default:
1511 retval = -1;
1512 done = TRUE;
1513 break;
1514 }
1515 }
1516 else if(0 == what) {
1517 /* timeout */
1518 failf(data, "SSL shutdown timeout");
1519 done = TRUE;
1520 }
1521 else {
1522 /* anything that gets here is fatally bad */
1523 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1524 retval = -1;
1525 done = TRUE;
1526 }
1527 }
1528 gnutls_deinit(backend->gtls.session);
1529 }
1530 gnutls_certificate_free_credentials(backend->gtls.cred);
1531
1532 #ifdef USE_GNUTLS_SRP
1533 {
1534 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1535 if(ssl_config->primary.username)
1536 gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1537 }
1538 #endif
1539
1540 backend->gtls.cred = NULL;
1541 backend->gtls.session = NULL;
1542
1543 return retval;
1544 }
1545
gtls_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t buffersize,CURLcode * curlcode)1546 static ssize_t gtls_recv(struct Curl_cfilter *cf,
1547 struct Curl_easy *data,
1548 char *buf,
1549 size_t buffersize,
1550 CURLcode *curlcode)
1551 {
1552 struct ssl_connect_data *connssl = cf->ctx;
1553 struct gtls_ssl_backend_data *backend =
1554 (struct gtls_ssl_backend_data *)connssl->backend;
1555 ssize_t ret;
1556
1557 (void)data;
1558 DEBUGASSERT(backend);
1559
1560 ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
1561 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1562 *curlcode = CURLE_AGAIN;
1563 ret = -1;
1564 goto out;
1565 }
1566
1567 if(ret == GNUTLS_E_REHANDSHAKE) {
1568 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1569 proper way" takes a whole lot of work. */
1570 CURLcode result = handshake(cf, data, FALSE, FALSE);
1571 if(result)
1572 /* handshake() writes error message on its own */
1573 *curlcode = result;
1574 else
1575 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1576 ret = -1;
1577 goto out;
1578 }
1579
1580 if(ret < 0) {
1581 failf(data, "GnuTLS recv error (%d): %s",
1582
1583 (int)ret, gnutls_strerror((int)ret));
1584 *curlcode = CURLE_RECV_ERROR;
1585 ret = -1;
1586 goto out;
1587 }
1588
1589 out:
1590 return ret;
1591 }
1592
gtls_session_free(void * ptr)1593 static void gtls_session_free(void *ptr)
1594 {
1595 free(ptr);
1596 }
1597
gtls_version(char * buffer,size_t size)1598 static size_t gtls_version(char *buffer, size_t size)
1599 {
1600 return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1601 }
1602
1603 /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1604 static CURLcode gtls_random(struct Curl_easy *data,
1605 unsigned char *entropy, size_t length)
1606 {
1607 int rc;
1608 (void)data;
1609 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1610 return rc?CURLE_FAILED_INIT:CURLE_OK;
1611 }
1612
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)1613 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1614 size_t tmplen,
1615 unsigned char *sha256sum, /* output */
1616 size_t sha256len)
1617 {
1618 struct sha256_ctx SHA256pw;
1619 sha256_init(&SHA256pw);
1620 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1621 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1622 return CURLE_OK;
1623 }
1624
gtls_cert_status_request(void)1625 static bool gtls_cert_status_request(void)
1626 {
1627 return TRUE;
1628 }
1629
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1630 static void *gtls_get_internals(struct ssl_connect_data *connssl,
1631 CURLINFO info UNUSED_PARAM)
1632 {
1633 struct gtls_ssl_backend_data *backend =
1634 (struct gtls_ssl_backend_data *)connssl->backend;
1635 (void)info;
1636 DEBUGASSERT(backend);
1637 return backend->gtls.session;
1638 }
1639
1640 const struct Curl_ssl Curl_ssl_gnutls = {
1641 { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
1642
1643 SSLSUPP_CA_PATH |
1644 SSLSUPP_CERTINFO |
1645 SSLSUPP_PINNEDPUBKEY |
1646 SSLSUPP_HTTPS_PROXY,
1647
1648 sizeof(struct gtls_ssl_backend_data),
1649
1650 gtls_init, /* init */
1651 gtls_cleanup, /* cleanup */
1652 gtls_version, /* version */
1653 Curl_none_check_cxn, /* check_cxn */
1654 gtls_shutdown, /* shutdown */
1655 gtls_data_pending, /* data_pending */
1656 gtls_random, /* random */
1657 gtls_cert_status_request, /* cert_status_request */
1658 gtls_connect, /* connect */
1659 gtls_connect_nonblocking, /* connect_nonblocking */
1660 Curl_ssl_adjust_pollset, /* adjust_pollset */
1661 gtls_get_internals, /* get_internals */
1662 gtls_close, /* close_one */
1663 Curl_none_close_all, /* close_all */
1664 gtls_session_free, /* session_free */
1665 Curl_none_set_engine, /* set_engine */
1666 Curl_none_set_engine_default, /* set_engine_default */
1667 Curl_none_engines_list, /* engines_list */
1668 Curl_none_false_start, /* false_start */
1669 gtls_sha256sum, /* sha256sum */
1670 NULL, /* associate_connection */
1671 NULL, /* disassociate_connection */
1672 NULL, /* free_multi_ssl_backend_data */
1673 gtls_recv, /* recv decrypted data */
1674 gtls_send, /* send data to encrypt */
1675 };
1676
1677 #endif /* USE_GNUTLS */
1678