xref: /curl/lib/vtls/gtls.c (revision 7307c1a2)
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 
25 /*
26  * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
27  * but vtls.c should ever call or use these functions.
28  *
29  * Note: do not use the GnuTLS' *_t variable type names in this source code,
30  * since they were not present in 1.0.X.
31  */
32 
33 #include "curl_setup.h"
34 
35 #ifdef USE_GNUTLS
36 
37 #include <gnutls/abstract.h>
38 #include <gnutls/gnutls.h>
39 #include <gnutls/x509.h>
40 #include <gnutls/crypto.h>
41 #include <nettle/sha2.h>
42 
43 #include "urldata.h"
44 #include "sendf.h"
45 #include "inet_pton.h"
46 #include "keylog.h"
47 #include "gtls.h"
48 #include "vtls.h"
49 #include "vtls_int.h"
50 #include "vauth/vauth.h"
51 #include "parsedate.h"
52 #include "connect.h" /* for the connect timeout */
53 #include "select.h"
54 #include "strcase.h"
55 #include "warnless.h"
56 #include "x509asn1.h"
57 #include "multiif.h"
58 #include "curl_printf.h"
59 #include "curl_memory.h"
60 /* The last #include file should be: */
61 #include "memdebug.h"
62 
63 #ifndef ARRAYSIZE
64 #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
65 #endif
66 
67 #define QUIC_PRIORITY \
68   "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
69   "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
70   "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
71   "%DISABLE_TLS13_COMPAT_MODE"
72 
73 /* Enable GnuTLS debugging by defining GTLSDEBUG */
74 /*#define GTLSDEBUG */
75 
76 #ifdef GTLSDEBUG
tls_log_func(int level,const char * str)77 static void tls_log_func(int level, const char *str)
78 {
79     fprintf(stderr, "|<%d>| %s", level, str);
80 }
81 #endif
82 static bool gtls_inited = FALSE;
83 
84 #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
85 #error "too old GnuTLS version"
86 #endif
87 
88 # include <gnutls/ocsp.h>
89 
90 struct gtls_ssl_backend_data {
91   struct gtls_ctx gtls;
92 };
93 
gtls_push(void * s,const void * buf,size_t blen)94 static ssize_t gtls_push(void *s, const void *buf, size_t blen)
95 {
96   struct Curl_cfilter *cf = s;
97   struct ssl_connect_data *connssl = cf->ctx;
98   struct gtls_ssl_backend_data *backend =
99     (struct gtls_ssl_backend_data *)connssl->backend;
100   struct Curl_easy *data = CF_DATA_CURRENT(cf);
101   ssize_t nwritten;
102   CURLcode result;
103 
104   DEBUGASSERT(data);
105   nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &result);
106   CURL_TRC_CF(data, cf, "gtls_push(len=%zu) -> %zd, err=%d",
107               blen, nwritten, result);
108   backend->gtls.io_result = result;
109   if(nwritten < 0) {
110     gnutls_transport_set_errno(backend->gtls.session,
111                                (CURLE_AGAIN == result) ? EAGAIN : EINVAL);
112     nwritten = -1;
113   }
114   return nwritten;
115 }
116 
gtls_pull(void * s,void * buf,size_t blen)117 static ssize_t gtls_pull(void *s, void *buf, size_t blen)
118 {
119   struct Curl_cfilter *cf = s;
120   struct ssl_connect_data *connssl = cf->ctx;
121   struct gtls_ssl_backend_data *backend =
122     (struct gtls_ssl_backend_data *)connssl->backend;
123   struct Curl_easy *data = CF_DATA_CURRENT(cf);
124   ssize_t nread;
125   CURLcode result;
126 
127   DEBUGASSERT(data);
128   if(!backend->gtls.shared_creds->trust_setup) {
129     result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
130     if(result) {
131       gnutls_transport_set_errno(backend->gtls.session, EINVAL);
132       backend->gtls.io_result = result;
133       return -1;
134     }
135   }
136 
137   nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
138   CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %zd, err=%d",
139               blen, nread, result);
140   backend->gtls.io_result = result;
141   if(nread < 0) {
142     gnutls_transport_set_errno(backend->gtls.session,
143                                (CURLE_AGAIN == result) ? EAGAIN : EINVAL);
144     nread = -1;
145   }
146   else if(nread == 0)
147     connssl->peer_closed = TRUE;
148   return nread;
149 }
150 
151 /* gtls_init()
152  *
153  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
154  * are not thread-safe and thus this function itself is not thread-safe and
155  * must only be called from within curl_global_init() to keep the thread
156  * situation under control!
157  */
gtls_init(void)158 static int gtls_init(void)
159 {
160   int ret = 1;
161   if(!gtls_inited) {
162     ret = gnutls_global_init() ? 0 : 1;
163 #ifdef GTLSDEBUG
164     gnutls_global_set_log_function(tls_log_func);
165     gnutls_global_set_log_level(2);
166 #endif
167     gtls_inited = TRUE;
168   }
169   return ret;
170 }
171 
gtls_cleanup(void)172 static void gtls_cleanup(void)
173 {
174   if(gtls_inited) {
175     gnutls_global_deinit();
176     gtls_inited = FALSE;
177   }
178 }
179 
180 #ifndef CURL_DISABLE_VERBOSE_STRINGS
showtime(struct Curl_easy * data,const char * text,time_t stamp)181 static void showtime(struct Curl_easy *data,
182                      const char *text,
183                      time_t stamp)
184 {
185   struct tm buffer;
186   const struct tm *tm = &buffer;
187   char str[96];
188   CURLcode result = Curl_gmtime(stamp, &buffer);
189   if(result)
190     return;
191 
192   msnprintf(str,
193             sizeof(str),
194             "  %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
195             text,
196             Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
197             tm->tm_mday,
198             Curl_month[tm->tm_mon],
199             tm->tm_year + 1900,
200             tm->tm_hour,
201             tm->tm_min,
202             tm->tm_sec);
203   infof(data, "%s", str);
204 }
205 #endif
206 
load_file(const char * file)207 static gnutls_datum_t load_file(const char *file)
208 {
209   FILE *f;
210   gnutls_datum_t loaded_file = { NULL, 0 };
211   long filelen;
212   void *ptr;
213 
214   f = fopen(file, "rb");
215   if(!f)
216     return loaded_file;
217   if(fseek(f, 0, SEEK_END) != 0
218      || (filelen = ftell(f)) < 0
219      || fseek(f, 0, SEEK_SET) != 0
220      || !(ptr = malloc((size_t)filelen)))
221     goto out;
222   if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
223     free(ptr);
224     goto out;
225   }
226 
227   loaded_file.data = ptr;
228   loaded_file.size = (unsigned int)filelen;
229 out:
230   fclose(f);
231   return loaded_file;
232 }
233 
unload_file(gnutls_datum_t data)234 static void unload_file(gnutls_datum_t data)
235 {
236   free(data.data);
237 }
238 
239 
240 /* this function does a SSL/TLS (re-)handshake */
handshake(struct Curl_cfilter * cf,struct Curl_easy * data,bool duringconnect,bool nonblocking)241 static CURLcode handshake(struct Curl_cfilter *cf,
242                           struct Curl_easy *data,
243                           bool duringconnect,
244                           bool nonblocking)
245 {
246   struct ssl_connect_data *connssl = cf->ctx;
247   struct gtls_ssl_backend_data *backend =
248     (struct gtls_ssl_backend_data *)connssl->backend;
249   gnutls_session_t session;
250   curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
251 
252   DEBUGASSERT(backend);
253   session = backend->gtls.session;
254   connssl->connecting_state = ssl_connect_2;
255 
256   for(;;) {
257     timediff_t timeout_ms;
258     int rc;
259 
260     /* check allowed time left */
261     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
262 
263     if(timeout_ms < 0) {
264       /* no need to continue if time already is up */
265       failf(data, "SSL connection timeout");
266       return CURLE_OPERATION_TIMEDOUT;
267     }
268 
269     /* if ssl is expecting something, check if it is available. */
270     if(connssl->io_need) {
271       int what;
272       curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
273         sockfd : CURL_SOCKET_BAD;
274       curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
275         sockfd : CURL_SOCKET_BAD;
276 
277       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
278                                nonblocking ? 0 :
279                                timeout_ms ? timeout_ms : 1000);
280       if(what < 0) {
281         /* fatal error */
282         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
283         return CURLE_SSL_CONNECT_ERROR;
284       }
285       else if(0 == what) {
286         if(nonblocking)
287           return CURLE_OK;
288         else if(timeout_ms) {
289           /* timeout */
290           failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
291           return CURLE_OPERATION_TIMEDOUT;
292         }
293       }
294       /* socket is readable or writable */
295     }
296 
297     connssl->io_need = CURL_SSL_IO_NEED_NONE;
298     backend->gtls.io_result = CURLE_OK;
299     rc = gnutls_handshake(session);
300 
301     if(!backend->gtls.shared_creds->trust_setup) {
302       /* After having send off the ClientHello, we prepare the trust
303        * store to verify the coming certificate from the server */
304       CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
305       if(result)
306         return result;
307     }
308 
309     if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
310       connssl->io_need =
311         gnutls_record_get_direction(session) ?
312         CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
313       continue;
314     }
315     else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
316       const char *strerr = NULL;
317 
318       if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
319         gnutls_alert_description_t alert = gnutls_alert_get(session);
320         strerr = gnutls_alert_get_name(alert);
321       }
322 
323       if(!strerr)
324         strerr = gnutls_strerror(rc);
325 
326       infof(data, "gnutls_handshake() warning: %s", strerr);
327       continue;
328     }
329     else if((rc < 0) && backend->gtls.io_result) {
330       return backend->gtls.io_result;
331     }
332     else if(rc < 0) {
333       const char *strerr = NULL;
334 
335       if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
336         gnutls_alert_description_t alert = gnutls_alert_get(session);
337         strerr = gnutls_alert_get_name(alert);
338       }
339 
340       if(!strerr)
341         strerr = gnutls_strerror(rc);
342 
343       failf(data, "GnuTLS, handshake failed: %s", strerr);
344       return CURLE_SSL_CONNECT_ERROR;
345     }
346 
347     /* Reset our connect state machine */
348     connssl->connecting_state = ssl_connect_1;
349     return CURLE_OK;
350   }
351 }
352 
gnutls_do_file_type(const char * type)353 static gnutls_x509_crt_fmt_t gnutls_do_file_type(const char *type)
354 {
355   if(!type || !type[0])
356     return GNUTLS_X509_FMT_PEM;
357   if(strcasecompare(type, "PEM"))
358     return GNUTLS_X509_FMT_PEM;
359   if(strcasecompare(type, "DER"))
360     return GNUTLS_X509_FMT_DER;
361   return GNUTLS_X509_FMT_PEM; /* default to PEM */
362 }
363 
364 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
365 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
366    requested in the priority string, so treat it specially
367  */
368 #define GNUTLS_SRP "+SRP"
369 
370 static CURLcode
gnutls_set_ssl_version_min_max(struct Curl_easy * data,struct ssl_peer * peer,struct ssl_primary_config * conn_config,const char ** prioritylist,const char * tls13support)371 gnutls_set_ssl_version_min_max(struct Curl_easy *data,
372                                struct ssl_peer *peer,
373                                struct ssl_primary_config *conn_config,
374                                const char **prioritylist,
375                                const char *tls13support)
376 {
377   long ssl_version = conn_config->version;
378   long ssl_version_max = conn_config->version_max;
379 
380   if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
381      (ssl_version == CURL_SSLVERSION_TLSv1))
382     ssl_version = CURL_SSLVERSION_TLSv1_0;
383   if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
384     ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
385 
386   if(peer->transport == TRNSPRT_QUIC) {
387     if((ssl_version_max != CURL_SSLVERSION_MAX_DEFAULT) &&
388        (ssl_version_max < CURL_SSLVERSION_MAX_TLSv1_3)) {
389       failf(data, "QUIC needs at least TLS version 1.3");
390       return CURLE_SSL_CONNECT_ERROR;
391      }
392     *prioritylist = QUIC_PRIORITY;
393     return CURLE_OK;
394   }
395 
396   if(!tls13support) {
397     /* If the running GnuTLS does not support TLS 1.3, we must not specify a
398        prioritylist involving that since it will make GnuTLS return an en
399        error back at us */
400     if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
401        (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
402       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
403     }
404   }
405   else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
406     ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
407   }
408 
409   switch(ssl_version | ssl_version_max) {
410   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
411     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
412       "+VERS-TLS1.0";
413     return CURLE_OK;
414   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
415     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
416       "+VERS-TLS1.1:+VERS-TLS1.0";
417     return CURLE_OK;
418   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
419     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
420       "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
421     return CURLE_OK;
422   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
423     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
424       "+VERS-TLS1.1";
425     return CURLE_OK;
426   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
427     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
428       "+VERS-TLS1.2:+VERS-TLS1.1";
429     return CURLE_OK;
430   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
431     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
432       "+VERS-TLS1.2";
433     return CURLE_OK;
434   case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
435     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
436       "+VERS-TLS1.3";
437     return CURLE_OK;
438   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
439     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
440     return CURLE_OK;
441   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
442     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
443       "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
444     return CURLE_OK;
445   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
446     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
447       "+VERS-TLS1.3:+VERS-TLS1.2";
448     return CURLE_OK;
449   }
450 
451   failf(data, "GnuTLS: cannot set ssl protocol");
452   return CURLE_SSL_CONNECT_ERROR;
453 }
454 
Curl_gtls_shared_creds_create(struct Curl_easy * data,struct gtls_shared_creds ** pcreds)455 CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data,
456                                        struct gtls_shared_creds **pcreds)
457 {
458   struct gtls_shared_creds *shared;
459   int rc;
460 
461   *pcreds = NULL;
462   shared = calloc(1, sizeof(*shared));
463   if(!shared)
464     return CURLE_OUT_OF_MEMORY;
465 
466   rc = gnutls_certificate_allocate_credentials(&shared->creds);
467   if(rc != GNUTLS_E_SUCCESS) {
468     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
469     free(shared);
470     return CURLE_SSL_CONNECT_ERROR;
471   }
472 
473   shared->refcount = 1;
474   shared->time = Curl_now();
475   *pcreds = shared;
476   return CURLE_OK;
477 }
478 
Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds * creds)479 CURLcode Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds *creds)
480 {
481   DEBUGASSERT(creds);
482   if(creds->refcount < SIZE_T_MAX) {
483     ++creds->refcount;
484     return CURLE_OK;
485   }
486   return CURLE_BAD_FUNCTION_ARGUMENT;
487 }
488 
Curl_gtls_shared_creds_free(struct gtls_shared_creds ** pcreds)489 void Curl_gtls_shared_creds_free(struct gtls_shared_creds **pcreds)
490 {
491   struct gtls_shared_creds *shared = *pcreds;
492   *pcreds = NULL;
493   if(shared) {
494     --shared->refcount;
495     if(!shared->refcount) {
496       gnutls_certificate_free_credentials(shared->creds);
497       free(shared->CAfile);
498       free(shared);
499     }
500   }
501 }
502 
gtls_populate_creds(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_certificate_credentials_t creds)503 static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
504                                     struct Curl_easy *data,
505                                     gnutls_certificate_credentials_t creds)
506 {
507   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
508   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
509   int rc;
510 
511   if(config->verifypeer) {
512     bool imported_native_ca = false;
513 
514     if(ssl_config->native_ca_store) {
515       rc = gnutls_certificate_set_x509_system_trust(creds);
516       if(rc < 0)
517         infof(data, "error reading native ca store (%s), continuing anyway",
518               gnutls_strerror(rc));
519       else {
520         infof(data, "found %d certificates in native ca store", rc);
521         if(rc > 0)
522           imported_native_ca = true;
523       }
524     }
525 
526     if(config->CAfile) {
527       /* set the trusted CA cert bundle file */
528       gnutls_certificate_set_verify_flags(creds,
529                                           GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
530 
531       rc = gnutls_certificate_set_x509_trust_file(creds,
532                                                   config->CAfile,
533                                                   GNUTLS_X509_FMT_PEM);
534       if(rc < 0) {
535         infof(data, "error reading ca cert file %s (%s)%s",
536               config->CAfile, gnutls_strerror(rc),
537               (imported_native_ca ? ", continuing anyway" : ""));
538         if(!imported_native_ca) {
539           ssl_config->certverifyresult = rc;
540           return CURLE_SSL_CACERT_BADFILE;
541         }
542       }
543       else
544         infof(data, "found %d certificates in %s", rc, config->CAfile);
545     }
546 
547     if(config->CApath) {
548       /* set the trusted CA cert directory */
549       rc = gnutls_certificate_set_x509_trust_dir(creds, config->CApath,
550                                                  GNUTLS_X509_FMT_PEM);
551       if(rc < 0) {
552         infof(data, "error reading ca cert file %s (%s)%s",
553               config->CApath, gnutls_strerror(rc),
554               (imported_native_ca ? ", continuing anyway" : ""));
555         if(!imported_native_ca) {
556           ssl_config->certverifyresult = rc;
557           return CURLE_SSL_CACERT_BADFILE;
558         }
559       }
560       else
561         infof(data, "found %d certificates in %s", rc, config->CApath);
562     }
563   }
564 
565   if(config->CRLfile) {
566     /* set the CRL list file */
567     rc = gnutls_certificate_set_x509_crl_file(creds, config->CRLfile,
568                                               GNUTLS_X509_FMT_PEM);
569     if(rc < 0) {
570       failf(data, "error reading crl file %s (%s)",
571             config->CRLfile, gnutls_strerror(rc));
572       return CURLE_SSL_CRL_BADFILE;
573     }
574     else
575       infof(data, "found %d CRL in %s", rc, config->CRLfile);
576   }
577 
578   return CURLE_OK;
579 }
580 
581 /* key to use at `multi->proto_hash` */
582 #define MPROTO_GTLS_X509_KEY   "tls:gtls:x509:share"
583 
gtls_shared_creds_expired(const struct Curl_easy * data,const struct gtls_shared_creds * sc)584 static bool gtls_shared_creds_expired(const struct Curl_easy *data,
585                                       const struct gtls_shared_creds *sc)
586 {
587   const struct ssl_general_config *cfg = &data->set.general_ssl;
588   struct curltime now = Curl_now();
589   timediff_t elapsed_ms = Curl_timediff(now, sc->time);
590   timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
591 
592   if(timeout_ms < 0)
593     return false;
594 
595   return elapsed_ms >= timeout_ms;
596 }
597 
gtls_shared_creds_different(struct Curl_cfilter * cf,const struct gtls_shared_creds * sc)598 static bool gtls_shared_creds_different(struct Curl_cfilter *cf,
599                                         const struct gtls_shared_creds *sc)
600 {
601   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
602   if(!sc->CAfile || !conn_config->CAfile)
603     return sc->CAfile != conn_config->CAfile;
604 
605   return strcmp(sc->CAfile, conn_config->CAfile);
606 }
607 
608 static struct gtls_shared_creds*
gtls_get_cached_creds(struct Curl_cfilter * cf,struct Curl_easy * data)609 gtls_get_cached_creds(struct Curl_cfilter *cf, struct Curl_easy *data)
610 {
611   struct gtls_shared_creds *shared_creds;
612 
613   if(data->multi) {
614     shared_creds = Curl_hash_pick(&data->multi->proto_hash,
615                                   (void *)MPROTO_GTLS_X509_KEY,
616                                   sizeof(MPROTO_GTLS_X509_KEY)-1);
617      if(shared_creds && shared_creds->creds &&
618         !gtls_shared_creds_expired(data, shared_creds) &&
619         !gtls_shared_creds_different(cf, shared_creds)) {
620        return shared_creds;
621      }
622   }
623   return NULL;
624 }
625 
gtls_shared_creds_hash_free(void * key,size_t key_len,void * p)626 static void gtls_shared_creds_hash_free(void *key, size_t key_len, void *p)
627 {
628   struct gtls_shared_creds *sc = p;
629   DEBUGASSERT(key_len == (sizeof(MPROTO_GTLS_X509_KEY)-1));
630   DEBUGASSERT(!memcmp(MPROTO_GTLS_X509_KEY, key, key_len));
631   (void)key;
632   (void)key_len;
633   Curl_gtls_shared_creds_free(&sc); /* down reference */
634 }
635 
gtls_set_cached_creds(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_shared_creds * sc)636 static void gtls_set_cached_creds(struct Curl_cfilter *cf,
637                                   struct Curl_easy *data,
638                                   struct gtls_shared_creds *sc)
639 {
640   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
641 
642   DEBUGASSERT(sc);
643   DEBUGASSERT(sc->creds);
644   DEBUGASSERT(!sc->CAfile);
645   DEBUGASSERT(sc->refcount == 1);
646   if(!data->multi)
647     return;
648 
649   if(conn_config->CAfile) {
650     sc->CAfile = strdup(conn_config->CAfile);
651     if(!sc->CAfile)
652       return;
653   }
654 
655   if(Curl_gtls_shared_creds_up_ref(sc))
656     return;
657 
658   if(!Curl_hash_add2(&data->multi->proto_hash,
659                     (void *)MPROTO_GTLS_X509_KEY,
660                     sizeof(MPROTO_GTLS_X509_KEY)-1,
661                     sc, gtls_shared_creds_hash_free)) {
662     Curl_gtls_shared_creds_free(&sc); /* down reference again */
663     return;
664   }
665 }
666 
Curl_gtls_client_trust_setup(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_ctx * gtls)667 CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
668                                       struct Curl_easy *data,
669                                       struct gtls_ctx *gtls)
670 {
671   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
672   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
673   struct gtls_shared_creds *cached_creds = NULL;
674   bool cache_criteria_met;
675   CURLcode result;
676   int rc;
677 
678 
679   /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
680      or no source is provided and we are falling back to OpenSSL's built-in
681      default. */
682   cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
683     conn_config->verifypeer &&
684     !conn_config->CApath &&
685     !conn_config->ca_info_blob &&
686     !ssl_config->primary.CRLfile &&
687     !ssl_config->native_ca_store &&
688     !conn_config->clientcert; /* GnuTLS adds client cert to its credentials! */
689 
690   if(cache_criteria_met)
691     cached_creds = gtls_get_cached_creds(cf, data);
692 
693   if(cached_creds && !Curl_gtls_shared_creds_up_ref(cached_creds)) {
694     CURL_TRC_CF(data, cf, "using shared trust anchors and CRLs");
695     Curl_gtls_shared_creds_free(&gtls->shared_creds);
696     gtls->shared_creds = cached_creds;
697     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
698                                 gtls->shared_creds->creds);
699     if(rc != GNUTLS_E_SUCCESS) {
700       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
701       return CURLE_SSL_CONNECT_ERROR;
702     }
703   }
704   else {
705     CURL_TRC_CF(data, cf, "loading trust anchors and CRLs");
706     result = gtls_populate_creds(cf, data, gtls->shared_creds->creds);
707     if(result)
708       return result;
709     gtls->shared_creds->trust_setup = TRUE;
710     if(cache_criteria_met)
711       gtls_set_cached_creds(cf, data, gtls->shared_creds);
712   }
713   return CURLE_OK;
714 }
715 
gtls_sessionid_free(void * sessionid,size_t idsize)716 static void gtls_sessionid_free(void *sessionid, size_t idsize)
717 {
718   (void)idsize;
719   free(sessionid);
720 }
721 
gtls_update_session_id(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)722 static CURLcode gtls_update_session_id(struct Curl_cfilter *cf,
723                                        struct Curl_easy *data,
724                                        gnutls_session_t session)
725 {
726   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
727   struct ssl_connect_data *connssl = cf->ctx;
728   CURLcode result = CURLE_OK;
729 
730   if(ssl_config->primary.cache_session) {
731     /* we always unconditionally get the session id here, as even if we
732        already got it from the cache and asked to use it in the connection, it
733        might've been rejected and then a new one is in use now and we need to
734        detect that. */
735     void *connect_sessionid;
736     size_t connect_idsize = 0;
737 
738     /* get the session ID data size */
739     gnutls_session_get_data(session, NULL, &connect_idsize);
740     connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
741     if(!connect_sessionid) {
742       return CURLE_OUT_OF_MEMORY;
743     }
744     else {
745       /* extract session ID to the allocated buffer */
746       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
747 
748       CURL_TRC_CF(data, cf, "get session id (len=%zu) and store in cache",
749                   connect_idsize);
750       Curl_ssl_sessionid_lock(data);
751       /* store this session id, takes ownership */
752       result = Curl_ssl_set_sessionid(cf, data, &connssl->peer,
753                                       connect_sessionid, connect_idsize,
754                                       gtls_sessionid_free);
755       Curl_ssl_sessionid_unlock(data);
756     }
757   }
758   return result;
759 }
760 
gtls_handshake_cb(gnutls_session_t session,unsigned int htype,unsigned when,unsigned int incoming,const gnutls_datum_t * msg)761 static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
762                              unsigned when, unsigned int incoming,
763                              const gnutls_datum_t *msg)
764 {
765   struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
766 
767   (void)msg;
768   (void)incoming;
769   if(when) { /* after message has been processed */
770     struct Curl_easy *data = CF_DATA_CURRENT(cf);
771     if(data) {
772       CURL_TRC_CF(data, cf, "handshake: %s message type %d",
773                   incoming ? "incoming" : "outgoing", htype);
774       switch(htype) {
775       case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
776         gtls_update_session_id(cf, data, session);
777         break;
778       }
779       default:
780         break;
781       }
782     }
783   }
784   return 0;
785 }
786 
gtls_client_init(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,struct gtls_ctx * gtls)787 static CURLcode gtls_client_init(struct Curl_cfilter *cf,
788                                  struct Curl_easy *data,
789                                  struct ssl_peer *peer,
790                                  struct gtls_ctx *gtls)
791 {
792   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
793   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
794   unsigned int init_flags;
795   int rc;
796   bool sni = TRUE; /* default is SNI enabled */
797   const char *prioritylist;
798   const char *err = NULL;
799   const char *tls13support;
800   CURLcode result;
801 
802   if(!gtls_inited)
803     gtls_init();
804 
805   if(config->version == CURL_SSLVERSION_SSLv2) {
806     failf(data, "GnuTLS does not support SSLv2");
807     return CURLE_SSL_CONNECT_ERROR;
808   }
809   else if(config->version == CURL_SSLVERSION_SSLv3)
810     sni = FALSE; /* SSLv3 has no SNI */
811 
812   /* allocate a shared creds struct */
813   result = Curl_gtls_shared_creds_create(data, &gtls->shared_creds);
814   if(result)
815     return result;
816 
817 #ifdef USE_GNUTLS_SRP
818   if(config->username && Curl_auth_allowed_to_host(data)) {
819     infof(data, "Using TLS-SRP username: %s", config->username);
820 
821     rc = gnutls_srp_allocate_client_credentials(&gtls->srp_client_cred);
822     if(rc != GNUTLS_E_SUCCESS) {
823       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
824             gnutls_strerror(rc));
825       return CURLE_OUT_OF_MEMORY;
826     }
827 
828     rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
829                                            config->username,
830                                            config->password);
831     if(rc != GNUTLS_E_SUCCESS) {
832       failf(data, "gnutls_srp_set_client_cred() failed: %s",
833             gnutls_strerror(rc));
834       return CURLE_BAD_FUNCTION_ARGUMENT;
835     }
836   }
837 #endif
838 
839   ssl_config->certverifyresult = 0;
840 
841   /* Initialize TLS session as a client */
842   init_flags = GNUTLS_CLIENT;
843 
844 #if defined(GNUTLS_FORCE_CLIENT_CERT)
845   init_flags |= GNUTLS_FORCE_CLIENT_CERT;
846 #endif
847 
848 #if defined(GNUTLS_NO_TICKETS)
849   /* Disable TLS session tickets */
850   init_flags |= GNUTLS_NO_TICKETS;
851 #endif
852 
853 #if defined(GNUTLS_NO_STATUS_REQUEST)
854   if(!config->verifystatus)
855     /* Disable the "status_request" TLS extension, enabled by default since
856        GnuTLS 3.8.0. */
857     init_flags |= GNUTLS_NO_STATUS_REQUEST;
858 #endif
859 
860   rc = gnutls_init(&gtls->session, init_flags);
861   if(rc != GNUTLS_E_SUCCESS) {
862     failf(data, "gnutls_init() failed: %d", rc);
863     return CURLE_SSL_CONNECT_ERROR;
864   }
865 
866   if(sni && peer->sni) {
867     if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
868                               peer->sni, strlen(peer->sni)) < 0) {
869       failf(data, "Failed to set SNI");
870       return CURLE_SSL_CONNECT_ERROR;
871     }
872   }
873 
874   /* Use default priorities */
875   rc = gnutls_set_default_priority(gtls->session);
876   if(rc != GNUTLS_E_SUCCESS)
877     return CURLE_SSL_CONNECT_ERROR;
878 
879   /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
880   tls13support = gnutls_check_version("3.6.5");
881 
882   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
883    * removed if a runtime error indicates that SRP is not supported by this
884    * GnuTLS version */
885 
886   if(config->version == CURL_SSLVERSION_SSLv2 ||
887      config->version == CURL_SSLVERSION_SSLv3) {
888     failf(data, "GnuTLS does not support SSLv2 or SSLv3");
889     return CURLE_SSL_CONNECT_ERROR;
890   }
891 
892   if(config->version == CURL_SSLVERSION_TLSv1_3) {
893     if(!tls13support) {
894       failf(data, "This GnuTLS installation does not support TLS 1.3");
895       return CURLE_SSL_CONNECT_ERROR;
896     }
897   }
898 
899   /* At this point we know we have a supported TLS version, so set it */
900   result = gnutls_set_ssl_version_min_max(data, peer,
901                                           config, &prioritylist, tls13support);
902   if(result)
903     return result;
904 
905 #ifdef USE_GNUTLS_SRP
906   /* Only add SRP to the cipher list if SRP is requested. Otherwise
907    * GnuTLS will disable TLS 1.3 support. */
908   if(config->username) {
909     char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
910     if(!prioritysrp)
911       return CURLE_OUT_OF_MEMORY;
912     rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
913     free(prioritysrp);
914 
915     if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
916       infof(data, "This GnuTLS does not support SRP");
917     }
918   }
919   else {
920 #endif
921     infof(data, "GnuTLS ciphers: %s", prioritylist);
922     rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
923 #ifdef USE_GNUTLS_SRP
924   }
925 #endif
926 
927   if(rc != GNUTLS_E_SUCCESS) {
928     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
929           rc, err);
930     return CURLE_SSL_CONNECT_ERROR;
931   }
932 
933   if(config->clientcert) {
934     if(!gtls->shared_creds->trust_setup) {
935       result = Curl_gtls_client_trust_setup(cf, data, gtls);
936       if(result)
937         return result;
938     }
939     if(ssl_config->cert_type && strcasecompare(ssl_config->cert_type, "P12")) {
940       rc = gnutls_certificate_set_x509_simple_pkcs12_file(
941         gtls->shared_creds->creds, config->clientcert, GNUTLS_X509_FMT_DER,
942         ssl_config->key_passwd ? ssl_config->key_passwd : "");
943       if(rc != GNUTLS_E_SUCCESS) {
944         failf(data,
945               "error reading X.509 potentially-encrypted key or certificate "
946               "file: %s",
947               gnutls_strerror(rc));
948         return CURLE_SSL_CONNECT_ERROR;
949       }
950     }
951     else if(ssl_config->key_passwd) {
952       const unsigned int supported_key_encryption_algorithms =
953         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
954         GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
955         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
956         GNUTLS_PKCS_USE_PBES2_AES_256;
957       rc = gnutls_certificate_set_x509_key_file2(
958            gtls->shared_creds->creds,
959            config->clientcert,
960            ssl_config->key ? ssl_config->key : config->clientcert,
961            gnutls_do_file_type(ssl_config->cert_type),
962            ssl_config->key_passwd,
963            supported_key_encryption_algorithms);
964       if(rc != GNUTLS_E_SUCCESS) {
965         failf(data,
966               "error reading X.509 potentially-encrypted key file: %s",
967               gnutls_strerror(rc));
968         return CURLE_SSL_CONNECT_ERROR;
969       }
970     }
971     else {
972       if(gnutls_certificate_set_x509_key_file(
973            gtls->shared_creds->creds,
974            config->clientcert,
975            ssl_config->key ? ssl_config->key : config->clientcert,
976            gnutls_do_file_type(ssl_config->cert_type) ) !=
977          GNUTLS_E_SUCCESS) {
978         failf(data, "error reading X.509 key or certificate file");
979         return CURLE_SSL_CONNECT_ERROR;
980       }
981     }
982   }
983 
984 #ifdef USE_GNUTLS_SRP
985   /* put the credentials to the current session */
986   if(config->username) {
987     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
988                                 gtls->srp_client_cred);
989     if(rc != GNUTLS_E_SUCCESS) {
990       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
991       return CURLE_SSL_CONNECT_ERROR;
992     }
993   }
994   else
995 #endif
996   {
997     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
998                                 gtls->shared_creds->creds);
999     if(rc != GNUTLS_E_SUCCESS) {
1000       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
1001       return CURLE_SSL_CONNECT_ERROR;
1002     }
1003   }
1004 
1005   if(config->verifystatus) {
1006     rc = gnutls_ocsp_status_request_enable_client(gtls->session,
1007                                                   NULL, 0, NULL);
1008     if(rc != GNUTLS_E_SUCCESS) {
1009       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
1010       return CURLE_SSL_CONNECT_ERROR;
1011     }
1012   }
1013 
1014   return CURLE_OK;
1015 }
1016 
keylog_callback(gnutls_session_t session,const char * label,const gnutls_datum_t * secret)1017 static int keylog_callback(gnutls_session_t session, const char *label,
1018                            const gnutls_datum_t *secret)
1019 {
1020   gnutls_datum_t crandom;
1021   gnutls_datum_t srandom;
1022 
1023   gnutls_session_get_random(session, &crandom, &srandom);
1024   if(crandom.size != 32) {
1025     return -1;
1026   }
1027 
1028   Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
1029   return 0;
1030 }
1031 
Curl_gtls_ctx_init(struct gtls_ctx * gctx,struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,const unsigned char * alpn,size_t alpn_len,Curl_gtls_ctx_setup_cb * cb_setup,void * cb_user_data,void * ssl_user_data)1032 CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
1033                             struct Curl_cfilter *cf,
1034                             struct Curl_easy *data,
1035                             struct ssl_peer *peer,
1036                             const unsigned char *alpn, size_t alpn_len,
1037                             Curl_gtls_ctx_setup_cb *cb_setup,
1038                             void *cb_user_data,
1039                             void *ssl_user_data)
1040 {
1041   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1042   CURLcode result;
1043 
1044   DEBUGASSERT(gctx);
1045 
1046   result = gtls_client_init(cf, data, peer, gctx);
1047   if(result)
1048     return result;
1049 
1050   gnutls_session_set_ptr(gctx->session, ssl_user_data);
1051 
1052   if(cb_setup) {
1053     result = cb_setup(cf, data, cb_user_data);
1054     if(result)
1055       return result;
1056   }
1057 
1058   /* Open the file if a TLS or QUIC backend has not done this before. */
1059   Curl_tls_keylog_open();
1060   if(Curl_tls_keylog_enabled()) {
1061     gnutls_session_set_keylog_function(gctx->session, keylog_callback);
1062   }
1063 
1064   /* convert the ALPN string from our arguments to a list of strings
1065    * that gnutls wants and will convert internally back to this very
1066    * string for sending to the server. nice. */
1067   if(alpn && alpn_len) {
1068     gnutls_datum_t alpns[5];
1069     size_t i, alen = alpn_len;
1070     unsigned char *s = (unsigned char *)alpn;
1071     unsigned char slen;
1072     for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
1073       slen = s[0];
1074       if(slen >= alen)
1075         return CURLE_FAILED_INIT;
1076       alpns[i].data = s + 1;
1077       alpns[i].size = slen;
1078       s += slen + 1;
1079       alen -= (size_t)slen + 1;
1080     }
1081     if(alen) /* not all alpn chars used, wrong format or too many */
1082         return CURLE_FAILED_INIT;
1083     if(i && gnutls_alpn_set_protocols(gctx->session,
1084                                       alpns, (unsigned int)i,
1085                                       GNUTLS_ALPN_MANDATORY)) {
1086       failf(data, "failed setting ALPN");
1087       return CURLE_SSL_CONNECT_ERROR;
1088     }
1089   }
1090 
1091   /* This might be a reconnect, so we check for a session ID in the cache
1092      to speed up things */
1093   if(conn_config->cache_session) {
1094     void *ssl_sessionid;
1095     size_t ssl_idsize;
1096 
1097     Curl_ssl_sessionid_lock(data);
1098     if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, &ssl_idsize)) {
1099       /* we got a session id, use it! */
1100       int rc;
1101 
1102       rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
1103       if(rc < 0)
1104         infof(data, "SSL failed to set session ID");
1105       else
1106         infof(data, "SSL reusing session ID (size=%zu)", ssl_idsize);
1107     }
1108     Curl_ssl_sessionid_unlock(data);
1109   }
1110   return CURLE_OK;
1111 }
1112 
1113 static CURLcode
gtls_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)1114 gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
1115 {
1116   struct ssl_connect_data *connssl = cf->ctx;
1117   struct gtls_ssl_backend_data *backend =
1118     (struct gtls_ssl_backend_data *)connssl->backend;
1119   struct alpn_proto_buf proto;
1120   CURLcode result;
1121 
1122   DEBUGASSERT(backend);
1123   DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
1124 
1125   if(connssl->state == ssl_connection_complete)
1126     /* to make us tolerant against being called more than once for the
1127        same connection */
1128     return CURLE_OK;
1129 
1130   memset(&proto, 0, sizeof(proto));
1131   if(connssl->alpn) {
1132     result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
1133     if(result) {
1134       failf(data, "Error determining ALPN");
1135       return CURLE_SSL_CONNECT_ERROR;
1136     }
1137   }
1138 
1139   result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
1140                               proto.data, proto.len, NULL, NULL, cf);
1141   if(result)
1142     return result;
1143 
1144   gnutls_handshake_set_hook_function(backend->gtls.session,
1145                                      GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
1146                                      gtls_handshake_cb);
1147 
1148   /* register callback functions and handle to send and receive data. */
1149   gnutls_transport_set_ptr(backend->gtls.session, cf);
1150   gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
1151   gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
1152 
1153   return CURLE_OK;
1154 }
1155 
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)1156 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
1157                                     gnutls_x509_crt_t cert,
1158                                     const char *pinnedpubkey)
1159 {
1160   /* Scratch */
1161   size_t len1 = 0, len2 = 0;
1162   unsigned char *buff1 = NULL;
1163 
1164   gnutls_pubkey_t key = NULL;
1165 
1166   /* Result is returned to caller */
1167   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1168 
1169   /* if a path was not specified, do not pin */
1170   if(!pinnedpubkey)
1171     return CURLE_OK;
1172 
1173   if(!cert)
1174     return result;
1175 
1176   do {
1177     int ret;
1178 
1179     /* Begin Gyrations to get the public key     */
1180     gnutls_pubkey_init(&key);
1181 
1182     ret = gnutls_pubkey_import_x509(key, cert, 0);
1183     if(ret < 0)
1184       break; /* failed */
1185 
1186     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
1187     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
1188       break; /* failed */
1189 
1190     buff1 = malloc(len1);
1191     if(!buff1)
1192       break; /* failed */
1193 
1194     len2 = len1;
1195 
1196     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
1197     if(ret < 0 || len1 != len2)
1198       break; /* failed */
1199 
1200     /* End Gyrations */
1201 
1202     /* The one good exit point */
1203     result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
1204   } while(0);
1205 
1206   if(key)
1207     gnutls_pubkey_deinit(key);
1208 
1209   Curl_safefree(buff1);
1210 
1211   return result;
1212 }
1213 
1214 CURLcode
Curl_gtls_verifyserver(struct Curl_easy * data,gnutls_session_t session,struct ssl_primary_config * config,struct ssl_config_data * ssl_config,struct ssl_peer * peer,const char * pinned_key)1215 Curl_gtls_verifyserver(struct Curl_easy *data,
1216                        gnutls_session_t session,
1217                        struct ssl_primary_config *config,
1218                        struct ssl_config_data *ssl_config,
1219                        struct ssl_peer *peer,
1220                        const char *pinned_key)
1221 {
1222   unsigned int cert_list_size;
1223   const gnutls_datum_t *chainp;
1224   unsigned int verify_status = 0;
1225   gnutls_x509_crt_t x509_cert, x509_issuer;
1226   gnutls_datum_t issuerp;
1227   gnutls_datum_t certfields;
1228   char certname[65] = ""; /* limited to 64 chars by ASN.1 */
1229   size_t size;
1230   time_t certclock;
1231   int rc;
1232   CURLcode result = CURLE_OK;
1233 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1234   const char *ptr;
1235   int algo;
1236   unsigned int bits;
1237   gnutls_protocol_t version = gnutls_protocol_get_version(session);
1238 #endif
1239   long * const certverifyresult = &ssl_config->certverifyresult;
1240 
1241 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1242   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
1243   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
1244                                      gnutls_cipher_get(session),
1245                                      gnutls_mac_get(session));
1246 
1247   infof(data, "SSL connection using %s / %s",
1248         gnutls_protocol_get_name(version), ptr);
1249 #endif
1250 
1251   /* This function will return the peer's raw certificate (chain) as sent by
1252      the peer. These certificates are in raw format (DER encoded for
1253      X.509). In case of a X.509 then a certificate list may be present. The
1254      first certificate in the list is the peer's certificate, following the
1255      issuer's certificate, then the issuer's issuer etc. */
1256 
1257   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1258   if(!chainp) {
1259     if(config->verifypeer ||
1260        config->verifyhost ||
1261        config->issuercert) {
1262 #ifdef USE_GNUTLS_SRP
1263       if(ssl_config->primary.username && !config->verifypeer &&
1264          gnutls_cipher_get(session)) {
1265         /* no peer cert, but auth is ok if we have SRP user and cipher and no
1266            peer verify */
1267       }
1268       else {
1269 #endif
1270         failf(data, "failed to get server cert");
1271         *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
1272         return CURLE_PEER_FAILED_VERIFICATION;
1273 #ifdef USE_GNUTLS_SRP
1274       }
1275 #endif
1276     }
1277     infof(data, " common name: WARNING could not obtain");
1278   }
1279 
1280   if(data->set.ssl.certinfo && chainp) {
1281     unsigned int i;
1282 
1283     result = Curl_ssl_init_certinfo(data, (int)cert_list_size);
1284     if(result)
1285       return result;
1286 
1287     for(i = 0; i < cert_list_size; i++) {
1288       const char *beg = (const char *) chainp[i].data;
1289       const char *end = beg + chainp[i].size;
1290 
1291       result = Curl_extract_certinfo(data, (int)i, beg, end);
1292       if(result)
1293         return result;
1294     }
1295   }
1296 
1297   if(config->verifypeer) {
1298     /* This function will try to verify the peer's certificate and return its
1299        status (trusted, invalid etc.). The value of status should be one or
1300        more of the gnutls_certificate_status_t enumerated elements bitwise
1301        or'd. To avoid denial of service attacks some default upper limits
1302        regarding the certificate key size and chain size are set. To override
1303        them use gnutls_certificate_set_verify_limits(). */
1304 
1305     rc = gnutls_certificate_verify_peers2(session, &verify_status);
1306     if(rc < 0) {
1307       failf(data, "server cert verify failed: %d", rc);
1308       *certverifyresult = rc;
1309       return CURLE_SSL_CONNECT_ERROR;
1310     }
1311 
1312     *certverifyresult = verify_status;
1313 
1314     /* verify_status is a bitmask of gnutls_certificate_status bits */
1315     if(verify_status & GNUTLS_CERT_INVALID) {
1316       if(config->verifypeer) {
1317         const char *cause = "certificate error, no details available";
1318         if(verify_status & GNUTLS_CERT_EXPIRED)
1319           cause = "certificate has expired";
1320         else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1321           cause = "certificate signer not trusted";
1322         else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
1323           cause = "certificate uses insecure algorithm";
1324         else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
1325           cause = "attached OCSP status response is invalid";
1326         failf(data, "server verification failed: %s. (CAfile: %s "
1327               "CRLfile: %s)", cause,
1328               config->CAfile ? config->CAfile : "none",
1329               ssl_config->primary.CRLfile ?
1330               ssl_config->primary.CRLfile : "none");
1331         return CURLE_PEER_FAILED_VERIFICATION;
1332       }
1333       else
1334         infof(data, "  server certificate verification FAILED");
1335     }
1336     else
1337       infof(data, "  server certificate verification OK");
1338   }
1339   else
1340     infof(data, "  server certificate verification SKIPPED");
1341 
1342   if(config->verifystatus) {
1343     gnutls_datum_t status_request;
1344     gnutls_ocsp_resp_t ocsp_resp;
1345     gnutls_ocsp_cert_status_t status;
1346     gnutls_x509_crl_reason_t reason;
1347 
1348     rc = gnutls_ocsp_status_request_get(session, &status_request);
1349 
1350     if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1351       failf(data, "No OCSP response received");
1352       return CURLE_SSL_INVALIDCERTSTATUS;
1353     }
1354 
1355     if(rc < 0) {
1356       failf(data, "Invalid OCSP response received");
1357       return CURLE_SSL_INVALIDCERTSTATUS;
1358     }
1359 
1360     gnutls_ocsp_resp_init(&ocsp_resp);
1361 
1362     rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1363     if(rc < 0) {
1364       failf(data, "Invalid OCSP response received");
1365       return CURLE_SSL_INVALIDCERTSTATUS;
1366     }
1367 
1368     (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1369                                       &status, NULL, NULL, NULL, &reason);
1370 
1371     switch(status) {
1372     case GNUTLS_OCSP_CERT_GOOD:
1373       break;
1374 
1375     case GNUTLS_OCSP_CERT_REVOKED: {
1376       const char *crl_reason;
1377 
1378       switch(reason) {
1379       default:
1380       case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1381         crl_reason = "unspecified reason";
1382         break;
1383 
1384       case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1385         crl_reason = "private key compromised";
1386         break;
1387 
1388       case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1389         crl_reason = "CA compromised";
1390         break;
1391 
1392       case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1393         crl_reason = "affiliation has changed";
1394         break;
1395 
1396       case GNUTLS_X509_CRLREASON_SUPERSEDED:
1397         crl_reason = "certificate superseded";
1398         break;
1399 
1400       case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1401         crl_reason = "operation has ceased";
1402         break;
1403 
1404       case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1405         crl_reason = "certificate is on hold";
1406         break;
1407 
1408       case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1409         crl_reason = "will be removed from delta CRL";
1410         break;
1411 
1412       case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1413         crl_reason = "privilege withdrawn";
1414         break;
1415 
1416       case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1417         crl_reason = "AA compromised";
1418         break;
1419       }
1420 
1421       failf(data, "Server certificate was revoked: %s", crl_reason);
1422       break;
1423     }
1424 
1425     default:
1426     case GNUTLS_OCSP_CERT_UNKNOWN:
1427       failf(data, "Server certificate status is unknown");
1428       break;
1429     }
1430 
1431     gnutls_ocsp_resp_deinit(ocsp_resp);
1432     if(status != GNUTLS_OCSP_CERT_GOOD)
1433       return CURLE_SSL_INVALIDCERTSTATUS;
1434   }
1435   else
1436     infof(data, "  server certificate status verification SKIPPED");
1437 
1438   /* initialize an X.509 certificate structure. */
1439   gnutls_x509_crt_init(&x509_cert);
1440 
1441   if(chainp)
1442     /* convert the given DER or PEM encoded Certificate to the native
1443        gnutls_x509_crt_t format */
1444     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1445 
1446   if(config->issuercert) {
1447     gnutls_x509_crt_init(&x509_issuer);
1448     issuerp = load_file(config->issuercert);
1449     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1450     rc = (int)gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1451     gnutls_x509_crt_deinit(x509_issuer);
1452     unload_file(issuerp);
1453     if(rc <= 0) {
1454       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1455             config->issuercert ? config->issuercert : "none");
1456       gnutls_x509_crt_deinit(x509_cert);
1457       return CURLE_SSL_ISSUER_ERROR;
1458     }
1459     infof(data, "  server certificate issuer check OK (Issuer Cert: %s)",
1460           config->issuercert ? config->issuercert : "none");
1461   }
1462 
1463   size = sizeof(certname);
1464   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1465                                      0, /* the first and only one */
1466                                      FALSE,
1467                                      certname,
1468                                      &size);
1469   if(rc) {
1470     infof(data, "error fetching CN from cert:%s",
1471           gnutls_strerror(rc));
1472   }
1473 
1474   /* This function will check if the given certificate's subject matches the
1475      given hostname. This is a basic implementation of the matching described
1476      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1477      alternative name PKIX extension. Returns non zero on success, and zero on
1478      failure. */
1479 
1480   /* This function does not handle trailing dots, so if we have an SNI name
1481      use that and fallback to the hostname only if there is no SNI (like for
1482      IP addresses) */
1483   rc = (int)gnutls_x509_crt_check_hostname(x509_cert,
1484                                            peer->sni ? peer->sni :
1485                                            peer->hostname);
1486 #if GNUTLS_VERSION_NUMBER < 0x030306
1487   /* Before 3.3.6, gnutls_x509_crt_check_hostname() did not check IP
1488      addresses. */
1489   if(!rc) {
1490 #ifdef USE_IPV6
1491     #define use_addr in6_addr
1492 #else
1493     #define use_addr in_addr
1494 #endif
1495     unsigned char addrbuf[sizeof(struct use_addr)];
1496     size_t addrlen = 0;
1497 
1498     if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
1499       addrlen = 4;
1500 #ifdef USE_IPV6
1501     else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
1502       addrlen = 16;
1503 #endif
1504 
1505     if(addrlen) {
1506       unsigned char certaddr[sizeof(struct use_addr)];
1507       int i;
1508 
1509       for(i = 0; ; i++) {
1510         size_t certaddrlen = sizeof(certaddr);
1511         int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1512                                                        &certaddrlen, NULL);
1513         /* If this happens, it was not an IP address. */
1514         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1515           continue;
1516         if(ret < 0)
1517           break;
1518         if(ret != GNUTLS_SAN_IPADDRESS)
1519           continue;
1520         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1521           rc = 1;
1522           break;
1523         }
1524       }
1525     }
1526   }
1527 #endif
1528   if(!rc) {
1529     if(config->verifyhost) {
1530       failf(data, "SSL: certificate subject name (%s) does not match "
1531             "target hostname '%s'", certname, peer->dispname);
1532       gnutls_x509_crt_deinit(x509_cert);
1533       return CURLE_PEER_FAILED_VERIFICATION;
1534     }
1535     else
1536       infof(data, "  common name: %s (does not match '%s')",
1537             certname, peer->dispname);
1538   }
1539   else
1540     infof(data, "  common name: %s (matched)", certname);
1541 
1542   /* Check for time-based validity */
1543   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1544 
1545   if(certclock == (time_t)-1) {
1546     if(config->verifypeer) {
1547       failf(data, "server cert expiration date verify failed");
1548       *certverifyresult = GNUTLS_CERT_EXPIRED;
1549       gnutls_x509_crt_deinit(x509_cert);
1550       return CURLE_SSL_CONNECT_ERROR;
1551     }
1552     else
1553       infof(data, "  server certificate expiration date verify FAILED");
1554   }
1555   else {
1556     if(certclock < time(NULL)) {
1557       if(config->verifypeer) {
1558         failf(data, "server certificate expiration date has passed.");
1559         *certverifyresult = GNUTLS_CERT_EXPIRED;
1560         gnutls_x509_crt_deinit(x509_cert);
1561         return CURLE_PEER_FAILED_VERIFICATION;
1562       }
1563       else
1564         infof(data, "  server certificate expiration date FAILED");
1565     }
1566     else
1567       infof(data, "  server certificate expiration date OK");
1568   }
1569 
1570   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1571 
1572   if(certclock == (time_t)-1) {
1573     if(config->verifypeer) {
1574       failf(data, "server cert activation date verify failed");
1575       *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1576       gnutls_x509_crt_deinit(x509_cert);
1577       return CURLE_SSL_CONNECT_ERROR;
1578     }
1579     else
1580       infof(data, "  server certificate activation date verify FAILED");
1581   }
1582   else {
1583     if(certclock > time(NULL)) {
1584       if(config->verifypeer) {
1585         failf(data, "server certificate not activated yet.");
1586         *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1587         gnutls_x509_crt_deinit(x509_cert);
1588         return CURLE_PEER_FAILED_VERIFICATION;
1589       }
1590       else
1591         infof(data, "  server certificate activation date FAILED");
1592     }
1593     else
1594       infof(data, "  server certificate activation date OK");
1595   }
1596 
1597   if(pinned_key) {
1598     result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
1599     if(result != CURLE_OK) {
1600       failf(data, "SSL: public key does not match pinned public key");
1601       gnutls_x509_crt_deinit(x509_cert);
1602       return result;
1603     }
1604   }
1605 
1606   /* Show:
1607 
1608   - subject
1609   - start date
1610   - expire date
1611   - common name
1612   - issuer
1613 
1614   */
1615 
1616 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1617   /* public key algorithm's parameters */
1618   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1619   infof(data, "  certificate public key: %s",
1620         gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo));
1621 
1622   /* version of the X.509 certificate. */
1623   infof(data, "  certificate version: #%d",
1624         gnutls_x509_crt_get_version(x509_cert));
1625 
1626 
1627   rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1628   if(rc)
1629     infof(data, "Failed to get certificate name");
1630   else {
1631     infof(data, "  subject: %s", certfields.data);
1632 
1633     certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1634     showtime(data, "start date", certclock);
1635 
1636     certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1637     showtime(data, "expire date", certclock);
1638 
1639     gnutls_free(certfields.data);
1640   }
1641 
1642   rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1643   if(rc)
1644     infof(data, "Failed to get certificate issuer");
1645   else {
1646     infof(data, "  issuer: %s", certfields.data);
1647 
1648     gnutls_free(certfields.data);
1649   }
1650 #endif
1651 
1652   gnutls_x509_crt_deinit(x509_cert);
1653 
1654   return result;
1655 }
1656 
gtls_verifyserver(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)1657 static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
1658                                   struct Curl_easy *data,
1659                                   gnutls_session_t session)
1660 {
1661   struct ssl_connect_data *connssl = cf->ctx;
1662   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1663   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1664 #ifndef CURL_DISABLE_PROXY
1665   const char *pinned_key = Curl_ssl_cf_is_proxy(cf) ?
1666     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1667     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1668 #else
1669   const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1670 #endif
1671   CURLcode result;
1672 
1673   result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
1674                                   &connssl->peer, pinned_key);
1675   if(result)
1676     goto out;
1677 
1678   if(connssl->alpn) {
1679     gnutls_datum_t proto;
1680     int rc;
1681 
1682     rc = gnutls_alpn_get_selected_protocol(session, &proto);
1683     if(rc == 0)
1684       Curl_alpn_set_negotiated(cf, data, proto.data, proto.size);
1685     else
1686       Curl_alpn_set_negotiated(cf, data, NULL, 0);
1687   }
1688 
1689   /* Only on TLSv1.2 or lower do we have the session id now. For
1690    * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
1691   if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
1692     result = gtls_update_session_id(cf, data, session);
1693 
1694 out:
1695   return result;
1696 }
1697 
1698 /*
1699  * This function is called after the TCP connect has completed. Setup the TLS
1700  * layer and do all necessary magic.
1701  */
1702 /* We use connssl->connecting_state to keep track of the connection status;
1703    there are three states: 'ssl_connect_1' (not started yet or complete),
1704    'ssl_connect_2' (doing handshake with the server), and
1705    'ssl_connect_3' (verifying and getting stats).
1706  */
1707 static CURLcode
gtls_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1708 gtls_connect_common(struct Curl_cfilter *cf,
1709                     struct Curl_easy *data,
1710                     bool nonblocking,
1711                     bool *done)
1712 {
1713   struct ssl_connect_data *connssl = cf->ctx;
1714   CURLcode rc;
1715   CURLcode result = CURLE_OK;
1716 
1717   /* Initiate the connection, if not already done */
1718   if(ssl_connect_1 == connssl->connecting_state) {
1719     rc = gtls_connect_step1(cf, data);
1720     if(rc) {
1721       result = rc;
1722       goto out;
1723     }
1724   }
1725 
1726   rc = handshake(cf, data, TRUE, nonblocking);
1727   if(rc) {
1728     /* handshake() sets its own error message with failf() */
1729     result = rc;
1730     goto out;
1731   }
1732 
1733   /* Finish connecting once the handshake is done */
1734   if(ssl_connect_1 == connssl->connecting_state) {
1735     struct gtls_ssl_backend_data *backend =
1736       (struct gtls_ssl_backend_data *)connssl->backend;
1737     gnutls_session_t session;
1738     DEBUGASSERT(backend);
1739     session = backend->gtls.session;
1740     rc = gtls_verifyserver(cf, data, session);
1741     if(rc) {
1742       result = rc;
1743       goto out;
1744     }
1745     connssl->state = ssl_connection_complete;
1746   }
1747 
1748 out:
1749   *done = ssl_connect_1 == connssl->connecting_state;
1750 
1751   return result;
1752 }
1753 
gtls_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1754 static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
1755                                          struct Curl_easy *data,
1756                                          bool *done)
1757 {
1758   return gtls_connect_common(cf, data, TRUE, done);
1759 }
1760 
gtls_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1761 static CURLcode gtls_connect(struct Curl_cfilter *cf,
1762                              struct Curl_easy *data)
1763 {
1764   CURLcode result;
1765   bool done = FALSE;
1766 
1767   result = gtls_connect_common(cf, data, FALSE, &done);
1768   if(result)
1769     return result;
1770 
1771   DEBUGASSERT(done);
1772 
1773   return CURLE_OK;
1774 }
1775 
gtls_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1776 static bool gtls_data_pending(struct Curl_cfilter *cf,
1777                               const struct Curl_easy *data)
1778 {
1779   struct ssl_connect_data *ctx = cf->ctx;
1780   struct gtls_ssl_backend_data *backend;
1781 
1782   (void)data;
1783   DEBUGASSERT(ctx && ctx->backend);
1784   backend = (struct gtls_ssl_backend_data *)ctx->backend;
1785   if(backend->gtls.session &&
1786      0 != gnutls_record_check_pending(backend->gtls.session))
1787     return TRUE;
1788   return FALSE;
1789 }
1790 
gtls_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t blen,CURLcode * curlcode)1791 static ssize_t gtls_send(struct Curl_cfilter *cf,
1792                          struct Curl_easy *data,
1793                          const void *buf,
1794                          size_t blen,
1795                          CURLcode *curlcode)
1796 {
1797   struct ssl_connect_data *connssl = cf->ctx;
1798   struct gtls_ssl_backend_data *backend =
1799     (struct gtls_ssl_backend_data *)connssl->backend;
1800   ssize_t rc;
1801   size_t nwritten, total_written = 0;
1802 
1803   (void)data;
1804   DEBUGASSERT(backend);
1805   while(blen) {
1806     backend->gtls.io_result = CURLE_OK;
1807     rc = gnutls_record_send(backend->gtls.session, buf, blen);
1808 
1809     if(rc < 0) {
1810       if(total_written && (rc == GNUTLS_E_AGAIN)) {
1811         *curlcode = CURLE_OK;
1812         rc = (ssize_t)total_written;
1813         goto out;
1814       }
1815       *curlcode = (rc == GNUTLS_E_AGAIN) ?
1816         CURLE_AGAIN :
1817         (backend->gtls.io_result ? backend->gtls.io_result : CURLE_SEND_ERROR);
1818 
1819       rc = -1;
1820       goto out;
1821     }
1822     nwritten = (size_t)rc;
1823     total_written += nwritten;
1824     DEBUGASSERT(nwritten <= blen);
1825     buf = (char *)buf + nwritten;
1826     blen -= nwritten;
1827   }
1828   rc = total_written;
1829 
1830 out:
1831   return rc;
1832 }
1833 
1834 /*
1835  * This function is called to shut down the SSL layer but keep the
1836  * socket open (CCC - Clear Command Channel)
1837  */
gtls_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)1838 static CURLcode gtls_shutdown(struct Curl_cfilter *cf,
1839                               struct Curl_easy *data,
1840                               bool send_shutdown, bool *done)
1841 {
1842   struct ssl_connect_data *connssl = cf->ctx;
1843   struct gtls_ssl_backend_data *backend =
1844     (struct gtls_ssl_backend_data *)connssl->backend;
1845   char buf[1024];
1846   CURLcode result = CURLE_OK;
1847   ssize_t nread;
1848   size_t i;
1849 
1850   DEBUGASSERT(backend);
1851   if(!backend->gtls.session || cf->shutdown) {
1852     *done = TRUE;
1853     goto out;
1854   }
1855 
1856   connssl->io_need = CURL_SSL_IO_NEED_NONE;
1857   *done = FALSE;
1858 
1859   if(!backend->gtls.sent_shutdown) {
1860     /* do this only once */
1861     backend->gtls.sent_shutdown = TRUE;
1862     if(send_shutdown) {
1863       int ret = gnutls_bye(backend->gtls.session, GNUTLS_SHUT_RDWR);
1864       if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1865         CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye EAGAIN");
1866         connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
1867           CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
1868         backend->gtls.sent_shutdown = FALSE;
1869         result = CURLE_OK;
1870         goto out;
1871       }
1872       if(ret != GNUTLS_E_SUCCESS) {
1873         CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye error: '%s'(%d)",
1874                     gnutls_strerror((int)ret), (int)ret);
1875         result = CURLE_RECV_ERROR;
1876         goto out;
1877       }
1878     }
1879   }
1880 
1881   /* SSL should now have started the shutdown from our side. Since it
1882    * was not complete, we are lacking the close notify from the server. */
1883   for(i = 0; i < 10; ++i) {
1884     nread = gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
1885     if(nread <= 0)
1886       break;
1887   }
1888   if(nread > 0) {
1889     /* still data coming in? */
1890   }
1891   else if(nread == 0) {
1892     /* We got the close notify alert and are done. */
1893     *done = TRUE;
1894   }
1895   else if((nread == GNUTLS_E_AGAIN) || (nread == GNUTLS_E_INTERRUPTED)) {
1896     connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
1897       CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
1898   }
1899   else {
1900     CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)",
1901                 gnutls_strerror((int)nread), (int)nread);
1902     result = CURLE_RECV_ERROR;
1903   }
1904 
1905 out:
1906   cf->shutdown = (result || *done);
1907   return result;
1908 }
1909 
gtls_close(struct Curl_cfilter * cf,struct Curl_easy * data)1910 static void gtls_close(struct Curl_cfilter *cf,
1911                        struct Curl_easy *data)
1912 {
1913   struct ssl_connect_data *connssl = cf->ctx;
1914   struct gtls_ssl_backend_data *backend =
1915     (struct gtls_ssl_backend_data *)connssl->backend;
1916 
1917   (void) data;
1918   DEBUGASSERT(backend);
1919   CURL_TRC_CF(data, cf, "close");
1920   if(backend->gtls.session) {
1921     gnutls_deinit(backend->gtls.session);
1922     backend->gtls.session = NULL;
1923   }
1924   if(backend->gtls.shared_creds) {
1925     Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
1926   }
1927 #ifdef USE_GNUTLS_SRP
1928   if(backend->gtls.srp_client_cred) {
1929     gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1930     backend->gtls.srp_client_cred = NULL;
1931   }
1932 #endif
1933 }
1934 
gtls_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t buffersize,CURLcode * curlcode)1935 static ssize_t gtls_recv(struct Curl_cfilter *cf,
1936                          struct Curl_easy *data,
1937                          char *buf,
1938                          size_t buffersize,
1939                          CURLcode *curlcode)
1940 {
1941   struct ssl_connect_data *connssl = cf->ctx;
1942   struct gtls_ssl_backend_data *backend =
1943     (struct gtls_ssl_backend_data *)connssl->backend;
1944   ssize_t ret;
1945 
1946   (void)data;
1947   DEBUGASSERT(backend);
1948 
1949   backend->gtls.io_result = CURLE_OK;
1950   ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
1951   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1952     *curlcode = CURLE_AGAIN;
1953     ret = -1;
1954     goto out;
1955   }
1956 
1957   if(ret == GNUTLS_E_REHANDSHAKE) {
1958     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1959        proper way" takes a whole lot of work. */
1960     CURLcode result = handshake(cf, data, FALSE, FALSE);
1961     if(result)
1962       /* handshake() writes error message on its own */
1963       *curlcode = result;
1964     else
1965       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1966     ret = -1;
1967     goto out;
1968   }
1969 
1970   if(ret < 0) {
1971     failf(data, "GnuTLS recv error (%d): %s",
1972           (int)ret, gnutls_strerror((int)ret));
1973     *curlcode = backend->gtls.io_result ?
1974       backend->gtls.io_result : CURLE_RECV_ERROR;
1975     ret = -1;
1976     goto out;
1977   }
1978 
1979 out:
1980   return ret;
1981 }
1982 
gtls_version(char * buffer,size_t size)1983 static size_t gtls_version(char *buffer, size_t size)
1984 {
1985   return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1986 }
1987 
1988 /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1989 static CURLcode gtls_random(struct Curl_easy *data,
1990                             unsigned char *entropy, size_t length)
1991 {
1992   int rc;
1993   (void)data;
1994   rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1995   return rc ? CURLE_FAILED_INIT : CURLE_OK;
1996 }
1997 
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)1998 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1999                                size_t tmplen,
2000                                unsigned char *sha256sum, /* output */
2001                                size_t sha256len)
2002 {
2003   struct sha256_ctx SHA256pw;
2004   sha256_init(&SHA256pw);
2005   sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
2006   sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
2007   return CURLE_OK;
2008 }
2009 
gtls_cert_status_request(void)2010 static bool gtls_cert_status_request(void)
2011 {
2012   return TRUE;
2013 }
2014 
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)2015 static void *gtls_get_internals(struct ssl_connect_data *connssl,
2016                                 CURLINFO info UNUSED_PARAM)
2017 {
2018   struct gtls_ssl_backend_data *backend =
2019     (struct gtls_ssl_backend_data *)connssl->backend;
2020   (void)info;
2021   DEBUGASSERT(backend);
2022   return backend->gtls.session;
2023 }
2024 
2025 const struct Curl_ssl Curl_ssl_gnutls = {
2026   { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
2027 
2028   SSLSUPP_CA_PATH  |
2029   SSLSUPP_CERTINFO |
2030   SSLSUPP_PINNEDPUBKEY |
2031   SSLSUPP_HTTPS_PROXY |
2032   SSLSUPP_CA_CACHE,
2033 
2034   sizeof(struct gtls_ssl_backend_data),
2035 
2036   gtls_init,                     /* init */
2037   gtls_cleanup,                  /* cleanup */
2038   gtls_version,                  /* version */
2039   Curl_none_check_cxn,           /* check_cxn */
2040   gtls_shutdown,                 /* shutdown */
2041   gtls_data_pending,             /* data_pending */
2042   gtls_random,                   /* random */
2043   gtls_cert_status_request,      /* cert_status_request */
2044   gtls_connect,                  /* connect */
2045   gtls_connect_nonblocking,      /* connect_nonblocking */
2046   Curl_ssl_adjust_pollset,       /* adjust_pollset */
2047   gtls_get_internals,            /* get_internals */
2048   gtls_close,                    /* close_one */
2049   Curl_none_close_all,           /* close_all */
2050   Curl_none_set_engine,          /* set_engine */
2051   Curl_none_set_engine_default,  /* set_engine_default */
2052   Curl_none_engines_list,        /* engines_list */
2053   Curl_none_false_start,         /* false_start */
2054   gtls_sha256sum,                /* sha256sum */
2055   NULL,                          /* associate_connection */
2056   NULL,                          /* disassociate_connection */
2057   gtls_recv,                     /* recv decrypted data */
2058   gtls_send,                     /* send data to encrypt */
2059   NULL,                          /* get_channel_binding */
2060 };
2061 
2062 #endif /* USE_GNUTLS */
2063