xref: /curl/lib/vtls/gtls.c (revision 937ba94e)
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 
25 /*
26  * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
27  * but vtls.c should ever call or use these functions.
28  *
29  * Note: don't use the GnuTLS' *_t variable type names in this source code,
30  * since they were not present in 1.0.X.
31  */
32 
33 #include "curl_setup.h"
34 
35 #ifdef USE_GNUTLS
36 
37 #include <gnutls/abstract.h>
38 #include <gnutls/gnutls.h>
39 #include <gnutls/x509.h>
40 #include <gnutls/crypto.h>
41 #include <nettle/sha2.h>
42 
43 #include "urldata.h"
44 #include "sendf.h"
45 #include "inet_pton.h"
46 #include "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, &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's 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 
do_file_type(const char * type)353 static gnutls_x509_crt_fmt_t 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
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 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 doesn't 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.sessionid) {
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       bool incache;
746       void *ssl_sessionid;
747 
748       /* extract session ID to the allocated buffer */
749       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
750 
751       CURL_TRC_CF(data, cf, "get session id (len=%zu) and store in cache",
752                   connect_idsize);
753       Curl_ssl_sessionid_lock(data);
754       incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
755                                         &ssl_sessionid, NULL));
756       if(incache) {
757         /* there was one before in the cache, so instead of risking that the
758            previous one was rejected, we just kill that and store the new */
759         Curl_ssl_delsessionid(data, ssl_sessionid);
760       }
761 
762       /* store this session id, takes ownership */
763       result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
764                                      connect_sessionid, connect_idsize,
765                                      gtls_sessionid_free);
766       Curl_ssl_sessionid_unlock(data);
767     }
768   }
769   return result;
770 }
771 
gtls_handshake_cb(gnutls_session_t session,unsigned int htype,unsigned when,unsigned int incoming,const gnutls_datum_t * msg)772 static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
773                              unsigned when, unsigned int incoming,
774                              const gnutls_datum_t *msg)
775 {
776   struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
777 
778   (void)msg;
779   (void)incoming;
780   if(when) { /* after message has been processed */
781     struct Curl_easy *data = CF_DATA_CURRENT(cf);
782     if(data) {
783       CURL_TRC_CF(data, cf, "handshake: %s message type %d",
784                   incoming? "incoming" : "outgoing", htype);
785       switch(htype) {
786       case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
787         gtls_update_session_id(cf, data, session);
788         break;
789       }
790       default:
791         break;
792       }
793     }
794   }
795   return 0;
796 }
797 
gtls_client_init(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,struct gtls_ctx * gtls)798 static CURLcode gtls_client_init(struct Curl_cfilter *cf,
799                                  struct Curl_easy *data,
800                                  struct ssl_peer *peer,
801                                  struct gtls_ctx *gtls)
802 {
803   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
804   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
805   unsigned int init_flags;
806   int rc;
807   bool sni = TRUE; /* default is SNI enabled */
808   const char *prioritylist;
809   const char *err = NULL;
810   const char *tls13support;
811   CURLcode result;
812 
813   if(!gtls_inited)
814     gtls_init();
815 
816   if(config->version == CURL_SSLVERSION_SSLv2) {
817     failf(data, "GnuTLS does not support SSLv2");
818     return CURLE_SSL_CONNECT_ERROR;
819   }
820   else if(config->version == CURL_SSLVERSION_SSLv3)
821     sni = FALSE; /* SSLv3 has no SNI */
822 
823   /* allocate a shared creds struct */
824   result = Curl_gtls_shared_creds_create(data, &gtls->shared_creds);
825   if(result)
826     return result;
827 
828 #ifdef USE_GNUTLS_SRP
829   if(config->username && Curl_auth_allowed_to_host(data)) {
830     infof(data, "Using TLS-SRP username: %s", config->username);
831 
832     rc = gnutls_srp_allocate_client_credentials(&gtls->srp_client_cred);
833     if(rc != GNUTLS_E_SUCCESS) {
834       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
835             gnutls_strerror(rc));
836       return CURLE_OUT_OF_MEMORY;
837     }
838 
839     rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
840                                            config->username,
841                                            config->password);
842     if(rc != GNUTLS_E_SUCCESS) {
843       failf(data, "gnutls_srp_set_client_cred() failed: %s",
844             gnutls_strerror(rc));
845       return CURLE_BAD_FUNCTION_ARGUMENT;
846     }
847   }
848 #endif
849 
850   ssl_config->certverifyresult = 0;
851 
852   /* Initialize TLS session as a client */
853   init_flags = GNUTLS_CLIENT;
854 
855 #if defined(GNUTLS_FORCE_CLIENT_CERT)
856   init_flags |= GNUTLS_FORCE_CLIENT_CERT;
857 #endif
858 
859 #if defined(GNUTLS_NO_TICKETS)
860   /* Disable TLS session tickets */
861   init_flags |= GNUTLS_NO_TICKETS;
862 #endif
863 
864   rc = gnutls_init(&gtls->session, init_flags);
865   if(rc != GNUTLS_E_SUCCESS) {
866     failf(data, "gnutls_init() failed: %d", rc);
867     return CURLE_SSL_CONNECT_ERROR;
868   }
869 
870   if(sni && peer->sni) {
871     if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
872                               peer->sni, strlen(peer->sni)) < 0) {
873       failf(data, "Failed to set SNI");
874       return CURLE_SSL_CONNECT_ERROR;
875     }
876   }
877 
878   /* Use default priorities */
879   rc = gnutls_set_default_priority(gtls->session);
880   if(rc != GNUTLS_E_SUCCESS)
881     return CURLE_SSL_CONNECT_ERROR;
882 
883   /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
884   tls13support = gnutls_check_version("3.6.5");
885 
886   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
887    * removed if a run-time error indicates that SRP is not supported by this
888    * GnuTLS version */
889 
890   if(config->version == CURL_SSLVERSION_SSLv2 ||
891      config->version == CURL_SSLVERSION_SSLv3) {
892     failf(data, "GnuTLS does not support SSLv2 or SSLv3");
893     return CURLE_SSL_CONNECT_ERROR;
894   }
895 
896   if(config->version == CURL_SSLVERSION_TLSv1_3) {
897     if(!tls13support) {
898       failf(data, "This GnuTLS installation does not support TLS 1.3");
899       return CURLE_SSL_CONNECT_ERROR;
900     }
901   }
902 
903   /* At this point we know we have a supported TLS version, so set it */
904   result = set_ssl_version_min_max(data, peer,
905                                    config, &prioritylist, tls13support);
906   if(result)
907     return result;
908 
909 #ifdef USE_GNUTLS_SRP
910   /* Only add SRP to the cipher list if SRP is requested. Otherwise
911    * GnuTLS will disable TLS 1.3 support. */
912   if(config->username) {
913     char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
914     if(!prioritysrp)
915       return CURLE_OUT_OF_MEMORY;
916     rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
917     free(prioritysrp);
918 
919     if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
920       infof(data, "This GnuTLS does not support SRP");
921     }
922   }
923   else {
924 #endif
925     infof(data, "GnuTLS ciphers: %s", prioritylist);
926     rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
927 #ifdef USE_GNUTLS_SRP
928   }
929 #endif
930 
931   if(rc != GNUTLS_E_SUCCESS) {
932     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
933           rc, err);
934     return CURLE_SSL_CONNECT_ERROR;
935   }
936 
937   if(config->clientcert) {
938     if(!gtls->shared_creds->trust_setup) {
939       result = Curl_gtls_client_trust_setup(cf, data, gtls);
940       if(result)
941         return result;
942     }
943     if(ssl_config->key_passwd) {
944       const unsigned int supported_key_encryption_algorithms =
945         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
946         GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
947         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
948         GNUTLS_PKCS_USE_PBES2_AES_256;
949       rc = gnutls_certificate_set_x509_key_file2(
950            gtls->shared_creds->creds,
951            config->clientcert,
952            ssl_config->key ? ssl_config->key : config->clientcert,
953            do_file_type(ssl_config->cert_type),
954            ssl_config->key_passwd,
955            supported_key_encryption_algorithms);
956       if(rc != GNUTLS_E_SUCCESS) {
957         failf(data,
958               "error reading X.509 potentially-encrypted key file: %s",
959               gnutls_strerror(rc));
960         return CURLE_SSL_CONNECT_ERROR;
961       }
962     }
963     else {
964       if(gnutls_certificate_set_x509_key_file(
965            gtls->shared_creds->creds,
966            config->clientcert,
967            ssl_config->key ? ssl_config->key : config->clientcert,
968            do_file_type(ssl_config->cert_type) ) !=
969          GNUTLS_E_SUCCESS) {
970         failf(data, "error reading X.509 key or certificate file");
971         return CURLE_SSL_CONNECT_ERROR;
972       }
973     }
974   }
975 
976 #ifdef USE_GNUTLS_SRP
977   /* put the credentials to the current session */
978   if(config->username) {
979     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
980                                 gtls->srp_client_cred);
981     if(rc != GNUTLS_E_SUCCESS) {
982       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
983       return CURLE_SSL_CONNECT_ERROR;
984     }
985   }
986   else
987 #endif
988   {
989     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
990                                 gtls->shared_creds->creds);
991     if(rc != GNUTLS_E_SUCCESS) {
992       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
993       return CURLE_SSL_CONNECT_ERROR;
994     }
995   }
996 
997   if(config->verifystatus) {
998     rc = gnutls_ocsp_status_request_enable_client(gtls->session,
999                                                   NULL, 0, NULL);
1000     if(rc != GNUTLS_E_SUCCESS) {
1001       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
1002       return CURLE_SSL_CONNECT_ERROR;
1003     }
1004   }
1005 
1006   return CURLE_OK;
1007 }
1008 
keylog_callback(gnutls_session_t session,const char * label,const gnutls_datum_t * secret)1009 static int keylog_callback(gnutls_session_t session, const char *label,
1010                            const gnutls_datum_t *secret)
1011 {
1012   gnutls_datum_t crandom;
1013   gnutls_datum_t srandom;
1014 
1015   gnutls_session_get_random(session, &crandom, &srandom);
1016   if(crandom.size != 32) {
1017     return -1;
1018   }
1019 
1020   Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
1021   return 0;
1022 }
1023 
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)1024 CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
1025                             struct Curl_cfilter *cf,
1026                             struct Curl_easy *data,
1027                             struct ssl_peer *peer,
1028                             const unsigned char *alpn, size_t alpn_len,
1029                             Curl_gtls_ctx_setup_cb *cb_setup,
1030                             void *cb_user_data,
1031                             void *ssl_user_data)
1032 {
1033   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1034   CURLcode result;
1035 
1036   DEBUGASSERT(gctx);
1037 
1038   result = gtls_client_init(cf, data, peer, gctx);
1039   if(result)
1040     return result;
1041 
1042   gnutls_session_set_ptr(gctx->session, ssl_user_data);
1043 
1044   if(cb_setup) {
1045     result = cb_setup(cf, data, cb_user_data);
1046     if(result)
1047       return result;
1048   }
1049 
1050   /* Open the file if a TLS or QUIC backend has not done this before. */
1051   Curl_tls_keylog_open();
1052   if(Curl_tls_keylog_enabled()) {
1053     gnutls_session_set_keylog_function(gctx->session, keylog_callback);
1054   }
1055 
1056   /* convert the ALPN string from our arguments to a list of strings
1057    * that gnutls wants and will convert internally back to this very
1058    * string for sending to the server. nice. */
1059   if(alpn && alpn_len) {
1060     gnutls_datum_t alpns[5];
1061     size_t i, alen = alpn_len;
1062     unsigned char *s = (unsigned char *)alpn;
1063     unsigned char slen;
1064     for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
1065       slen = s[0];
1066       if(slen >= alen)
1067         return CURLE_FAILED_INIT;
1068       alpns[i].data = s + 1;
1069       alpns[i].size = slen;
1070       s += slen + 1;
1071       alen -= (size_t)slen + 1;
1072     }
1073     if(alen) /* not all alpn chars used, wrong format or too many */
1074         return CURLE_FAILED_INIT;
1075     if(i && gnutls_alpn_set_protocols(gctx->session,
1076                                       alpns, (unsigned int)i,
1077                                       GNUTLS_ALPN_MANDATORY)) {
1078       failf(data, "failed setting ALPN");
1079       return CURLE_SSL_CONNECT_ERROR;
1080     }
1081   }
1082 
1083   /* This might be a reconnect, so we check for a session ID in the cache
1084      to speed up things */
1085   if(conn_config->sessionid) {
1086     void *ssl_sessionid;
1087     size_t ssl_idsize;
1088 
1089     Curl_ssl_sessionid_lock(data);
1090     if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, &ssl_idsize)) {
1091       /* we got a session id, use it! */
1092       int rc;
1093 
1094       rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
1095       if(rc < 0)
1096         infof(data, "SSL failed to set session ID");
1097       else
1098         infof(data, "SSL reusing session ID (size=%zu)", ssl_idsize);
1099     }
1100     Curl_ssl_sessionid_unlock(data);
1101   }
1102   return CURLE_OK;
1103 }
1104 
1105 static CURLcode
gtls_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)1106 gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
1107 {
1108   struct ssl_connect_data *connssl = cf->ctx;
1109   struct gtls_ssl_backend_data *backend =
1110     (struct gtls_ssl_backend_data *)connssl->backend;
1111   struct alpn_proto_buf proto;
1112   CURLcode result;
1113 
1114   DEBUGASSERT(backend);
1115   DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
1116 
1117   if(connssl->state == ssl_connection_complete)
1118     /* to make us tolerant against being called more than once for the
1119        same connection */
1120     return CURLE_OK;
1121 
1122   memset(&proto, 0, sizeof(proto));
1123   if(connssl->alpn) {
1124     result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
1125     if(result) {
1126       failf(data, "Error determining ALPN");
1127       return CURLE_SSL_CONNECT_ERROR;
1128     }
1129   }
1130 
1131   result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
1132                               proto.data, proto.len, NULL, NULL, cf);
1133   if(result)
1134     return result;
1135 
1136   gnutls_handshake_set_hook_function(backend->gtls.session,
1137                                      GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
1138                                      gtls_handshake_cb);
1139 
1140   /* register callback functions and handle to send and receive data. */
1141   gnutls_transport_set_ptr(backend->gtls.session, cf);
1142   gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
1143   gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
1144 
1145   return CURLE_OK;
1146 }
1147 
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)1148 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
1149                                     gnutls_x509_crt_t cert,
1150                                     const char *pinnedpubkey)
1151 {
1152   /* Scratch */
1153   size_t len1 = 0, len2 = 0;
1154   unsigned char *buff1 = NULL;
1155 
1156   gnutls_pubkey_t key = NULL;
1157 
1158   /* Result is returned to caller */
1159   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1160 
1161   /* if a path wasn't specified, don't pin */
1162   if(!pinnedpubkey)
1163     return CURLE_OK;
1164 
1165   if(!cert)
1166     return result;
1167 
1168   do {
1169     int ret;
1170 
1171     /* Begin Gyrations to get the public key     */
1172     gnutls_pubkey_init(&key);
1173 
1174     ret = gnutls_pubkey_import_x509(key, cert, 0);
1175     if(ret < 0)
1176       break; /* failed */
1177 
1178     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
1179     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
1180       break; /* failed */
1181 
1182     buff1 = malloc(len1);
1183     if(!buff1)
1184       break; /* failed */
1185 
1186     len2 = len1;
1187 
1188     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
1189     if(ret < 0 || len1 != len2)
1190       break; /* failed */
1191 
1192     /* End Gyrations */
1193 
1194     /* The one good exit point */
1195     result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
1196   } while(0);
1197 
1198   if(key)
1199     gnutls_pubkey_deinit(key);
1200 
1201   Curl_safefree(buff1);
1202 
1203   return result;
1204 }
1205 
1206 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)1207 Curl_gtls_verifyserver(struct Curl_easy *data,
1208                        gnutls_session_t session,
1209                        struct ssl_primary_config *config,
1210                        struct ssl_config_data *ssl_config,
1211                        struct ssl_peer *peer,
1212                        const char *pinned_key)
1213 {
1214   unsigned int cert_list_size;
1215   const gnutls_datum_t *chainp;
1216   unsigned int verify_status = 0;
1217   gnutls_x509_crt_t x509_cert, x509_issuer;
1218   gnutls_datum_t issuerp;
1219   gnutls_datum_t certfields;
1220   char certname[65] = ""; /* limited to 64 chars by ASN.1 */
1221   size_t size;
1222   time_t certclock;
1223   int rc;
1224   CURLcode result = CURLE_OK;
1225 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1226   const char *ptr;
1227   int algo;
1228   unsigned int bits;
1229   gnutls_protocol_t version = gnutls_protocol_get_version(session);
1230 #endif
1231   long * const certverifyresult = &ssl_config->certverifyresult;
1232 
1233 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1234   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
1235   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
1236                                      gnutls_cipher_get(session),
1237                                      gnutls_mac_get(session));
1238 
1239   infof(data, "SSL connection using %s / %s",
1240         gnutls_protocol_get_name(version), ptr);
1241 #endif
1242 
1243   /* This function will return the peer's raw certificate (chain) as sent by
1244      the peer. These certificates are in raw format (DER encoded for
1245      X.509). In case of a X.509 then a certificate list may be present. The
1246      first certificate in the list is the peer's certificate, following the
1247      issuer's certificate, then the issuer's issuer etc. */
1248 
1249   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1250   if(!chainp) {
1251     if(config->verifypeer ||
1252        config->verifyhost ||
1253        config->issuercert) {
1254 #ifdef USE_GNUTLS_SRP
1255       if(ssl_config->primary.username && !config->verifypeer &&
1256          gnutls_cipher_get(session)) {
1257         /* no peer cert, but auth is ok if we have SRP user and cipher and no
1258            peer verify */
1259       }
1260       else {
1261 #endif
1262         failf(data, "failed to get server cert");
1263         *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
1264         return CURLE_PEER_FAILED_VERIFICATION;
1265 #ifdef USE_GNUTLS_SRP
1266       }
1267 #endif
1268     }
1269     infof(data, " common name: WARNING couldn't obtain");
1270   }
1271 
1272   if(data->set.ssl.certinfo && chainp) {
1273     unsigned int i;
1274 
1275     result = Curl_ssl_init_certinfo(data, (int)cert_list_size);
1276     if(result)
1277       return result;
1278 
1279     for(i = 0; i < cert_list_size; i++) {
1280       const char *beg = (const char *) chainp[i].data;
1281       const char *end = beg + chainp[i].size;
1282 
1283       result = Curl_extract_certinfo(data, (int)i, beg, end);
1284       if(result)
1285         return result;
1286     }
1287   }
1288 
1289   if(config->verifypeer) {
1290     /* This function will try to verify the peer's certificate and return its
1291        status (trusted, invalid etc.). The value of status should be one or
1292        more of the gnutls_certificate_status_t enumerated elements bitwise
1293        or'd. To avoid denial of service attacks some default upper limits
1294        regarding the certificate key size and chain size are set. To override
1295        them use gnutls_certificate_set_verify_limits(). */
1296 
1297     rc = gnutls_certificate_verify_peers2(session, &verify_status);
1298     if(rc < 0) {
1299       failf(data, "server cert verify failed: %d", rc);
1300       *certverifyresult = rc;
1301       return CURLE_SSL_CONNECT_ERROR;
1302     }
1303 
1304     *certverifyresult = verify_status;
1305 
1306     /* verify_status is a bitmask of gnutls_certificate_status bits */
1307     if(verify_status & GNUTLS_CERT_INVALID) {
1308       if(config->verifypeer) {
1309         failf(data, "server certificate verification failed. CAfile: %s "
1310               "CRLfile: %s", config->CAfile ? config->CAfile:
1311               "none",
1312               ssl_config->primary.CRLfile ?
1313               ssl_config->primary.CRLfile : "none");
1314         return CURLE_PEER_FAILED_VERIFICATION;
1315       }
1316       else
1317         infof(data, "  server certificate verification FAILED");
1318     }
1319     else
1320       infof(data, "  server certificate verification OK");
1321   }
1322   else
1323     infof(data, "  server certificate verification SKIPPED");
1324 
1325   if(config->verifystatus) {
1326     if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
1327       gnutls_datum_t status_request;
1328       gnutls_ocsp_resp_t ocsp_resp;
1329 
1330       gnutls_ocsp_cert_status_t status;
1331       gnutls_x509_crl_reason_t reason;
1332 
1333       rc = gnutls_ocsp_status_request_get(session, &status_request);
1334 
1335       infof(data, " server certificate status verification FAILED");
1336 
1337       if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1338         failf(data, "No OCSP response received");
1339         return CURLE_SSL_INVALIDCERTSTATUS;
1340       }
1341 
1342       if(rc < 0) {
1343         failf(data, "Invalid OCSP response received");
1344         return CURLE_SSL_INVALIDCERTSTATUS;
1345       }
1346 
1347       gnutls_ocsp_resp_init(&ocsp_resp);
1348 
1349       rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1350       if(rc < 0) {
1351         failf(data, "Invalid OCSP response received");
1352         return CURLE_SSL_INVALIDCERTSTATUS;
1353       }
1354 
1355       (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1356                                         &status, NULL, NULL, NULL, &reason);
1357 
1358       switch(status) {
1359       case GNUTLS_OCSP_CERT_GOOD:
1360         break;
1361 
1362       case GNUTLS_OCSP_CERT_REVOKED: {
1363         const char *crl_reason;
1364 
1365         switch(reason) {
1366           default:
1367           case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1368             crl_reason = "unspecified reason";
1369             break;
1370 
1371           case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1372             crl_reason = "private key compromised";
1373             break;
1374 
1375           case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1376             crl_reason = "CA compromised";
1377             break;
1378 
1379           case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1380             crl_reason = "affiliation has changed";
1381             break;
1382 
1383           case GNUTLS_X509_CRLREASON_SUPERSEDED:
1384             crl_reason = "certificate superseded";
1385             break;
1386 
1387           case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1388             crl_reason = "operation has ceased";
1389             break;
1390 
1391           case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1392             crl_reason = "certificate is on hold";
1393             break;
1394 
1395           case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1396             crl_reason = "will be removed from delta CRL";
1397             break;
1398 
1399           case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1400             crl_reason = "privilege withdrawn";
1401             break;
1402 
1403           case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1404             crl_reason = "AA compromised";
1405             break;
1406         }
1407 
1408         failf(data, "Server certificate was revoked: %s", crl_reason);
1409         break;
1410       }
1411 
1412       default:
1413       case GNUTLS_OCSP_CERT_UNKNOWN:
1414         failf(data, "Server certificate status is unknown");
1415         break;
1416       }
1417 
1418       gnutls_ocsp_resp_deinit(ocsp_resp);
1419 
1420       return CURLE_SSL_INVALIDCERTSTATUS;
1421     }
1422     else
1423       infof(data, "  server certificate status verification OK");
1424   }
1425   else
1426     infof(data, "  server certificate status verification SKIPPED");
1427 
1428   /* initialize an X.509 certificate structure. */
1429   gnutls_x509_crt_init(&x509_cert);
1430 
1431   if(chainp)
1432     /* convert the given DER or PEM encoded Certificate to the native
1433        gnutls_x509_crt_t format */
1434     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1435 
1436   if(config->issuercert) {
1437     gnutls_x509_crt_init(&x509_issuer);
1438     issuerp = load_file(config->issuercert);
1439     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1440     rc = (int)gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1441     gnutls_x509_crt_deinit(x509_issuer);
1442     unload_file(issuerp);
1443     if(rc <= 0) {
1444       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1445             config->issuercert?config->issuercert:"none");
1446       gnutls_x509_crt_deinit(x509_cert);
1447       return CURLE_SSL_ISSUER_ERROR;
1448     }
1449     infof(data, "  server certificate issuer check OK (Issuer Cert: %s)",
1450           config->issuercert?config->issuercert:"none");
1451   }
1452 
1453   size = sizeof(certname);
1454   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1455                                      0, /* the first and only one */
1456                                      FALSE,
1457                                      certname,
1458                                      &size);
1459   if(rc) {
1460     infof(data, "error fetching CN from cert:%s",
1461           gnutls_strerror(rc));
1462   }
1463 
1464   /* This function will check if the given certificate's subject matches the
1465      given hostname. This is a basic implementation of the matching described
1466      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1467      alternative name PKIX extension. Returns non zero on success, and zero on
1468      failure. */
1469   rc = (int)gnutls_x509_crt_check_hostname(x509_cert, peer->hostname);
1470 #if GNUTLS_VERSION_NUMBER < 0x030306
1471   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1472      addresses. */
1473   if(!rc) {
1474 #ifdef USE_IPV6
1475     #define use_addr in6_addr
1476 #else
1477     #define use_addr in_addr
1478 #endif
1479     unsigned char addrbuf[sizeof(struct use_addr)];
1480     size_t addrlen = 0;
1481 
1482     if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
1483       addrlen = 4;
1484 #ifdef USE_IPV6
1485     else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
1486       addrlen = 16;
1487 #endif
1488 
1489     if(addrlen) {
1490       unsigned char certaddr[sizeof(struct use_addr)];
1491       int i;
1492 
1493       for(i = 0; ; i++) {
1494         size_t certaddrlen = sizeof(certaddr);
1495         int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1496                                                        &certaddrlen, NULL);
1497         /* If this happens, it wasn't an IP address. */
1498         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1499           continue;
1500         if(ret < 0)
1501           break;
1502         if(ret != GNUTLS_SAN_IPADDRESS)
1503           continue;
1504         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1505           rc = 1;
1506           break;
1507         }
1508       }
1509     }
1510   }
1511 #endif
1512   if(!rc) {
1513     if(config->verifyhost) {
1514       failf(data, "SSL: certificate subject name (%s) does not match "
1515             "target host name '%s'", certname, peer->dispname);
1516       gnutls_x509_crt_deinit(x509_cert);
1517       return CURLE_PEER_FAILED_VERIFICATION;
1518     }
1519     else
1520       infof(data, "  common name: %s (does not match '%s')",
1521             certname, peer->dispname);
1522   }
1523   else
1524     infof(data, "  common name: %s (matched)", certname);
1525 
1526   /* Check for time-based validity */
1527   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1528 
1529   if(certclock == (time_t)-1) {
1530     if(config->verifypeer) {
1531       failf(data, "server cert expiration date verify failed");
1532       *certverifyresult = GNUTLS_CERT_EXPIRED;
1533       gnutls_x509_crt_deinit(x509_cert);
1534       return CURLE_SSL_CONNECT_ERROR;
1535     }
1536     else
1537       infof(data, "  server certificate expiration date verify FAILED");
1538   }
1539   else {
1540     if(certclock < time(NULL)) {
1541       if(config->verifypeer) {
1542         failf(data, "server certificate expiration date has passed.");
1543         *certverifyresult = GNUTLS_CERT_EXPIRED;
1544         gnutls_x509_crt_deinit(x509_cert);
1545         return CURLE_PEER_FAILED_VERIFICATION;
1546       }
1547       else
1548         infof(data, "  server certificate expiration date FAILED");
1549     }
1550     else
1551       infof(data, "  server certificate expiration date OK");
1552   }
1553 
1554   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1555 
1556   if(certclock == (time_t)-1) {
1557     if(config->verifypeer) {
1558       failf(data, "server cert activation date verify failed");
1559       *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1560       gnutls_x509_crt_deinit(x509_cert);
1561       return CURLE_SSL_CONNECT_ERROR;
1562     }
1563     else
1564       infof(data, "  server certificate activation date verify FAILED");
1565   }
1566   else {
1567     if(certclock > time(NULL)) {
1568       if(config->verifypeer) {
1569         failf(data, "server certificate not activated yet.");
1570         *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1571         gnutls_x509_crt_deinit(x509_cert);
1572         return CURLE_PEER_FAILED_VERIFICATION;
1573       }
1574       else
1575         infof(data, "  server certificate activation date FAILED");
1576     }
1577     else
1578       infof(data, "  server certificate activation date OK");
1579   }
1580 
1581   if(pinned_key) {
1582     result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
1583     if(result != CURLE_OK) {
1584       failf(data, "SSL: public key does not match pinned public key");
1585       gnutls_x509_crt_deinit(x509_cert);
1586       return result;
1587     }
1588   }
1589 
1590   /* Show:
1591 
1592   - subject
1593   - start date
1594   - expire date
1595   - common name
1596   - issuer
1597 
1598   */
1599 
1600 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1601   /* public key algorithm's parameters */
1602   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1603   infof(data, "  certificate public key: %s",
1604         gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo));
1605 
1606   /* version of the X.509 certificate. */
1607   infof(data, "  certificate version: #%d",
1608         gnutls_x509_crt_get_version(x509_cert));
1609 
1610 
1611   rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1612   if(rc)
1613     infof(data, "Failed to get certificate name");
1614   else {
1615     infof(data, "  subject: %s", certfields.data);
1616 
1617     certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1618     showtime(data, "start date", certclock);
1619 
1620     certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1621     showtime(data, "expire date", certclock);
1622 
1623     gnutls_free(certfields.data);
1624   }
1625 
1626   rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1627   if(rc)
1628     infof(data, "Failed to get certificate issuer");
1629   else {
1630     infof(data, "  issuer: %s", certfields.data);
1631 
1632     gnutls_free(certfields.data);
1633   }
1634 #endif
1635 
1636   gnutls_x509_crt_deinit(x509_cert);
1637 
1638   return result;
1639 }
1640 
gtls_verifyserver(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)1641 static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
1642                                   struct Curl_easy *data,
1643                                   gnutls_session_t session)
1644 {
1645   struct ssl_connect_data *connssl = cf->ctx;
1646   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1647   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1648 #ifndef CURL_DISABLE_PROXY
1649   const char *pinned_key = Curl_ssl_cf_is_proxy(cf)?
1650     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
1651     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1652 #else
1653   const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1654 #endif
1655   CURLcode result;
1656 
1657   result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
1658                                   &connssl->peer, pinned_key);
1659   if(result)
1660     goto out;
1661 
1662   if(connssl->alpn) {
1663     gnutls_datum_t proto;
1664     int rc;
1665 
1666     rc = gnutls_alpn_get_selected_protocol(session, &proto);
1667     if(rc == 0)
1668       Curl_alpn_set_negotiated(cf, data, proto.data, proto.size);
1669     else
1670       Curl_alpn_set_negotiated(cf, data, NULL, 0);
1671   }
1672 
1673   /* Only on TLSv1.2 or lower do we have the session id now. For
1674    * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
1675   if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
1676     result = gtls_update_session_id(cf, data, session);
1677 
1678 out:
1679   return result;
1680 }
1681 
1682 /*
1683  * This function is called after the TCP connect has completed. Setup the TLS
1684  * layer and do all necessary magic.
1685  */
1686 /* We use connssl->connecting_state to keep track of the connection status;
1687    there are three states: 'ssl_connect_1' (not started yet or complete),
1688    'ssl_connect_2' (doing handshake with the server), and
1689    'ssl_connect_3' (verifying and getting stats).
1690  */
1691 static CURLcode
gtls_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1692 gtls_connect_common(struct Curl_cfilter *cf,
1693                     struct Curl_easy *data,
1694                     bool nonblocking,
1695                     bool *done)
1696 {
1697   struct ssl_connect_data *connssl = cf->ctx;
1698   CURLcode rc;
1699   CURLcode result = CURLE_OK;
1700 
1701   /* Initiate the connection, if not already done */
1702   if(ssl_connect_1 == connssl->connecting_state) {
1703     rc = gtls_connect_step1(cf, data);
1704     if(rc) {
1705       result = rc;
1706       goto out;
1707     }
1708   }
1709 
1710   rc = handshake(cf, data, TRUE, nonblocking);
1711   if(rc) {
1712     /* handshake() sets its own error message with failf() */
1713     result = rc;
1714     goto out;
1715   }
1716 
1717   /* Finish connecting once the handshake is done */
1718   if(ssl_connect_1 == connssl->connecting_state) {
1719     struct gtls_ssl_backend_data *backend =
1720       (struct gtls_ssl_backend_data *)connssl->backend;
1721     gnutls_session_t session;
1722     DEBUGASSERT(backend);
1723     session = backend->gtls.session;
1724     rc = gtls_verifyserver(cf, data, session);
1725     if(rc) {
1726       result = rc;
1727       goto out;
1728     }
1729     connssl->state = ssl_connection_complete;
1730   }
1731 
1732 out:
1733   *done = ssl_connect_1 == connssl->connecting_state;
1734 
1735   return result;
1736 }
1737 
gtls_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1738 static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
1739                                          struct Curl_easy *data,
1740                                          bool *done)
1741 {
1742   return gtls_connect_common(cf, data, TRUE, done);
1743 }
1744 
gtls_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1745 static CURLcode gtls_connect(struct Curl_cfilter *cf,
1746                              struct Curl_easy *data)
1747 {
1748   CURLcode result;
1749   bool done = FALSE;
1750 
1751   result = gtls_connect_common(cf, data, FALSE, &done);
1752   if(result)
1753     return result;
1754 
1755   DEBUGASSERT(done);
1756 
1757   return CURLE_OK;
1758 }
1759 
gtls_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1760 static bool gtls_data_pending(struct Curl_cfilter *cf,
1761                               const struct Curl_easy *data)
1762 {
1763   struct ssl_connect_data *ctx = cf->ctx;
1764   struct gtls_ssl_backend_data *backend;
1765 
1766   (void)data;
1767   DEBUGASSERT(ctx && ctx->backend);
1768   backend = (struct gtls_ssl_backend_data *)ctx->backend;
1769   if(backend->gtls.session &&
1770      0 != gnutls_record_check_pending(backend->gtls.session))
1771     return TRUE;
1772   return FALSE;
1773 }
1774 
gtls_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * mem,size_t len,CURLcode * curlcode)1775 static ssize_t gtls_send(struct Curl_cfilter *cf,
1776                          struct Curl_easy *data,
1777                          const void *mem,
1778                          size_t len,
1779                          CURLcode *curlcode)
1780 {
1781   struct ssl_connect_data *connssl = cf->ctx;
1782   struct gtls_ssl_backend_data *backend =
1783     (struct gtls_ssl_backend_data *)connssl->backend;
1784   ssize_t rc;
1785 
1786   (void)data;
1787   DEBUGASSERT(backend);
1788   backend->gtls.io_result = CURLE_OK;
1789   rc = gnutls_record_send(backend->gtls.session, mem, len);
1790 
1791   if(rc < 0) {
1792     *curlcode = (rc == GNUTLS_E_AGAIN)?
1793       CURLE_AGAIN :
1794       (backend->gtls.io_result? backend->gtls.io_result : CURLE_SEND_ERROR);
1795 
1796     rc = -1;
1797   }
1798 
1799   return rc;
1800 }
1801 
gtls_close(struct Curl_cfilter * cf,struct Curl_easy * data)1802 static void gtls_close(struct Curl_cfilter *cf,
1803                        struct Curl_easy *data)
1804 {
1805   struct ssl_connect_data *connssl = cf->ctx;
1806   struct gtls_ssl_backend_data *backend =
1807     (struct gtls_ssl_backend_data *)connssl->backend;
1808 
1809   (void) data;
1810   DEBUGASSERT(backend);
1811   CURL_TRC_CF(data, cf, "close");
1812   if(backend->gtls.session) {
1813     char buf[32];
1814     /* Maybe the server has already sent a close notify alert.
1815        Read it to avoid an RST on the TCP connection. */
1816     CURL_TRC_CF(data, cf, "close, try receive before bye");
1817     (void)gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
1818     CURL_TRC_CF(data, cf, "close, send bye");
1819     gnutls_bye(backend->gtls.session, GNUTLS_SHUT_RDWR);
1820     /* try one last receive */
1821     CURL_TRC_CF(data, cf, "close, receive after bye");
1822     (void)gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
1823     gnutls_deinit(backend->gtls.session);
1824     backend->gtls.session = NULL;
1825   }
1826   if(backend->gtls.shared_creds) {
1827     Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
1828   }
1829 #ifdef USE_GNUTLS_SRP
1830   if(backend->gtls.srp_client_cred) {
1831     gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1832     backend->gtls.srp_client_cred = NULL;
1833   }
1834 #endif
1835 }
1836 
1837 /*
1838  * This function is called to shut down the SSL layer but keep the
1839  * socket open (CCC - Clear Command Channel)
1840  */
gtls_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data)1841 static int gtls_shutdown(struct Curl_cfilter *cf,
1842                          struct Curl_easy *data)
1843 {
1844   struct ssl_connect_data *connssl = cf->ctx;
1845   struct gtls_ssl_backend_data *backend =
1846     (struct gtls_ssl_backend_data *)connssl->backend;
1847   int retval = 0;
1848 
1849   DEBUGASSERT(backend);
1850 
1851 #ifndef CURL_DISABLE_FTP
1852   /* This has only been tested on the proftpd server, and the mod_tls code
1853      sends a close notify alert without waiting for a close notify alert in
1854      response. Thus we wait for a close notify alert from the server, but
1855      we do not send one. Let's hope other servers do the same... */
1856 
1857   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1858     gnutls_bye(backend->gtls.session, GNUTLS_SHUT_WR);
1859 #endif
1860 
1861   if(backend->gtls.session) {
1862     ssize_t result;
1863     bool done = FALSE;
1864     char buf[120];
1865 
1866     while(!done && !connssl->peer_closed) {
1867       int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
1868                                  SSL_SHUTDOWN_TIMEOUT);
1869       if(what > 0) {
1870         /* Something to read, let's do it and hope that it is the close
1871            notify alert from the server */
1872         result = gnutls_record_recv(backend->gtls.session,
1873                                     buf, sizeof(buf));
1874         switch(result) {
1875         case 0:
1876           /* This is the expected response. There was no data but only
1877              the close notify alert */
1878           done = TRUE;
1879           break;
1880         case GNUTLS_E_AGAIN:
1881         case GNUTLS_E_INTERRUPTED:
1882           infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED");
1883           break;
1884         default:
1885           retval = -1;
1886           done = TRUE;
1887           break;
1888         }
1889       }
1890       else if(0 == what) {
1891         /* timeout */
1892         failf(data, "SSL shutdown timeout");
1893         done = TRUE;
1894       }
1895       else {
1896         /* anything that gets here is fatally bad */
1897         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1898         retval = -1;
1899         done = TRUE;
1900       }
1901     }
1902     gnutls_deinit(backend->gtls.session);
1903   }
1904 
1905 #ifdef USE_GNUTLS_SRP
1906   {
1907     struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1908     if(ssl_config->primary.username)
1909       gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1910   }
1911 #endif
1912 
1913   backend->gtls.session = NULL;
1914   Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
1915 
1916   return retval;
1917 }
1918 
gtls_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t buffersize,CURLcode * curlcode)1919 static ssize_t gtls_recv(struct Curl_cfilter *cf,
1920                          struct Curl_easy *data,
1921                          char *buf,
1922                          size_t buffersize,
1923                          CURLcode *curlcode)
1924 {
1925   struct ssl_connect_data *connssl = cf->ctx;
1926   struct gtls_ssl_backend_data *backend =
1927     (struct gtls_ssl_backend_data *)connssl->backend;
1928   ssize_t ret;
1929 
1930   (void)data;
1931   DEBUGASSERT(backend);
1932 
1933   backend->gtls.io_result = CURLE_OK;
1934   ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
1935   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1936     *curlcode = CURLE_AGAIN;
1937     ret = -1;
1938     goto out;
1939   }
1940 
1941   if(ret == GNUTLS_E_REHANDSHAKE) {
1942     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1943        proper way" takes a whole lot of work. */
1944     CURLcode result = handshake(cf, data, FALSE, FALSE);
1945     if(result)
1946       /* handshake() writes error message on its own */
1947       *curlcode = result;
1948     else
1949       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1950     ret = -1;
1951     goto out;
1952   }
1953 
1954   if(ret < 0) {
1955     failf(data, "GnuTLS recv error (%d): %s",
1956 
1957           (int)ret, gnutls_strerror((int)ret));
1958     *curlcode = backend->gtls.io_result?
1959                 backend->gtls.io_result : CURLE_RECV_ERROR;
1960     ret = -1;
1961     goto out;
1962   }
1963 
1964 out:
1965   return ret;
1966 }
1967 
gtls_version(char * buffer,size_t size)1968 static size_t gtls_version(char *buffer, size_t size)
1969 {
1970   return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1971 }
1972 
1973 /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1974 static CURLcode gtls_random(struct Curl_easy *data,
1975                             unsigned char *entropy, size_t length)
1976 {
1977   int rc;
1978   (void)data;
1979   rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1980   return rc?CURLE_FAILED_INIT:CURLE_OK;
1981 }
1982 
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)1983 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1984                                size_t tmplen,
1985                                unsigned char *sha256sum, /* output */
1986                                size_t sha256len)
1987 {
1988   struct sha256_ctx SHA256pw;
1989   sha256_init(&SHA256pw);
1990   sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1991   sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1992   return CURLE_OK;
1993 }
1994 
gtls_cert_status_request(void)1995 static bool gtls_cert_status_request(void)
1996 {
1997   return TRUE;
1998 }
1999 
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)2000 static void *gtls_get_internals(struct ssl_connect_data *connssl,
2001                                 CURLINFO info UNUSED_PARAM)
2002 {
2003   struct gtls_ssl_backend_data *backend =
2004     (struct gtls_ssl_backend_data *)connssl->backend;
2005   (void)info;
2006   DEBUGASSERT(backend);
2007   return backend->gtls.session;
2008 }
2009 
2010 const struct Curl_ssl Curl_ssl_gnutls = {
2011   { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
2012 
2013   SSLSUPP_CA_PATH  |
2014   SSLSUPP_CERTINFO |
2015   SSLSUPP_PINNEDPUBKEY |
2016   SSLSUPP_HTTPS_PROXY |
2017   SSLSUPP_CA_CACHE,
2018 
2019   sizeof(struct gtls_ssl_backend_data),
2020 
2021   gtls_init,                     /* init */
2022   gtls_cleanup,                  /* cleanup */
2023   gtls_version,                  /* version */
2024   Curl_none_check_cxn,           /* check_cxn */
2025   gtls_shutdown,                 /* shutdown */
2026   gtls_data_pending,             /* data_pending */
2027   gtls_random,                   /* random */
2028   gtls_cert_status_request,      /* cert_status_request */
2029   gtls_connect,                  /* connect */
2030   gtls_connect_nonblocking,      /* connect_nonblocking */
2031   Curl_ssl_adjust_pollset,       /* adjust_pollset */
2032   gtls_get_internals,            /* get_internals */
2033   gtls_close,                    /* close_one */
2034   Curl_none_close_all,           /* close_all */
2035   Curl_none_set_engine,          /* set_engine */
2036   Curl_none_set_engine_default,  /* set_engine_default */
2037   Curl_none_engines_list,        /* engines_list */
2038   Curl_none_false_start,         /* false_start */
2039   gtls_sha256sum,                /* sha256sum */
2040   NULL,                          /* associate_connection */
2041   NULL,                          /* disassociate_connection */
2042   gtls_recv,                     /* recv decrypted data */
2043   gtls_send,                     /* send data to encrypt */
2044 };
2045 
2046 #endif /* USE_GNUTLS */
2047