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