• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.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 
255   for(;;) {
256     timediff_t timeout_ms;
257     int rc;
258 
259     /* check allowed time left */
260     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
261 
262     if(timeout_ms < 0) {
263       /* no need to continue if time already is up */
264       failf(data, "SSL connection timeout");
265       return CURLE_OPERATION_TIMEDOUT;
266     }
267 
268     /* if ssl is expecting something, check if it's available. */
269     if(connssl->connecting_state == ssl_connect_2_reading
270        || connssl->connecting_state == ssl_connect_2_writing) {
271       int what;
272       curl_socket_t writefd = ssl_connect_2_writing ==
273         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
274       curl_socket_t readfd = ssl_connect_2_reading ==
275         connssl->connecting_state?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     backend->gtls.io_result = CURLE_OK;
298     rc = gnutls_handshake(session);
299 
300     if(!backend->gtls.trust_setup) {
301       /* After having send off the ClientHello, we prepare the trust
302        * store to verify the coming certificate from the server */
303       CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
304       if(result)
305         return result;
306     }
307 
308     if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
309       connssl->connecting_state =
310         gnutls_record_get_direction(session)?
311         ssl_connect_2_writing:ssl_connect_2_reading;
312       continue;
313     }
314     else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
315       const char *strerr = NULL;
316 
317       if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
318         int alert = gnutls_alert_get(session);
319         strerr = gnutls_alert_get_name(alert);
320       }
321 
322       if(!strerr)
323         strerr = gnutls_strerror(rc);
324 
325       infof(data, "gnutls_handshake() warning: %s", strerr);
326       continue;
327     }
328     else if((rc < 0) && backend->gtls.io_result) {
329       return backend->gtls.io_result;
330     }
331     else if(rc < 0) {
332       const char *strerr = NULL;
333 
334       if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
335         int alert = gnutls_alert_get(session);
336         strerr = gnutls_alert_get_name(alert);
337       }
338 
339       if(!strerr)
340         strerr = gnutls_strerror(rc);
341 
342       failf(data, "gnutls_handshake() failed: %s", strerr);
343       return CURLE_SSL_CONNECT_ERROR;
344     }
345 
346     /* Reset our connect state machine */
347     connssl->connecting_state = ssl_connect_1;
348     return CURLE_OK;
349   }
350 }
351 
do_file_type(const char * type)352 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
353 {
354   if(!type || !type[0])
355     return GNUTLS_X509_FMT_PEM;
356   if(strcasecompare(type, "PEM"))
357     return GNUTLS_X509_FMT_PEM;
358   if(strcasecompare(type, "DER"))
359     return GNUTLS_X509_FMT_DER;
360   return GNUTLS_X509_FMT_PEM; /* default to PEM */
361 }
362 
363 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
364 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
365    requested in the priority string, so treat it specially
366  */
367 #define GNUTLS_SRP "+SRP"
368 
369 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)370 set_ssl_version_min_max(struct Curl_easy *data,
371                         struct ssl_peer *peer,
372                         struct ssl_primary_config *conn_config,
373                         const char **prioritylist,
374                         const char *tls13support)
375 {
376   long ssl_version = conn_config->version;
377   long ssl_version_max = conn_config->version_max;
378 
379   if(peer->transport == TRNSPRT_QUIC) {
380     if((ssl_version != CURL_SSLVERSION_DEFAULT) &&
381        (ssl_version < CURL_SSLVERSION_TLSv1_3)) {
382       failf(data, "QUIC needs at least TLS version 1.3");
383       return CURLE_SSL_CONNECT_ERROR;
384      }
385     *prioritylist = QUIC_PRIORITY;
386     return CURLE_OK;
387   }
388 
389   if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
390      (ssl_version == CURL_SSLVERSION_TLSv1))
391     ssl_version = CURL_SSLVERSION_TLSv1_0;
392   if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
393     ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
394   if(!tls13support) {
395     /* If the running GnuTLS doesn't support TLS 1.3, we must not specify a
396        prioritylist involving that since it will make GnuTLS return an en
397        error back at us */
398     if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
399        (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
400       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
401     }
402   }
403   else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
404     ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
405   }
406 
407   switch(ssl_version | ssl_version_max) {
408   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
409     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
410       "+VERS-TLS1.0";
411     return CURLE_OK;
412   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
413     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
414       "+VERS-TLS1.1:+VERS-TLS1.0";
415     return CURLE_OK;
416   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
417     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
418       "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
419     return CURLE_OK;
420   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
421     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
422       "+VERS-TLS1.1";
423     return CURLE_OK;
424   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
425     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
426       "+VERS-TLS1.2:+VERS-TLS1.1";
427     return CURLE_OK;
428   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
429     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
430       "+VERS-TLS1.2";
431     return CURLE_OK;
432   case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
433     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
434       "+VERS-TLS1.3";
435     return CURLE_OK;
436   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
437     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
438     return CURLE_OK;
439   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
440     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
441       "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
442     return CURLE_OK;
443   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
444     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
445       "+VERS-TLS1.3:+VERS-TLS1.2";
446     return CURLE_OK;
447   }
448 
449   failf(data, "GnuTLS: cannot set ssl protocol");
450   return CURLE_SSL_CONNECT_ERROR;
451 }
452 
Curl_gtls_client_trust_setup(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_ctx * gtls)453 CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
454                                       struct Curl_easy *data,
455                                       struct gtls_ctx *gtls)
456 {
457   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
458   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
459   int rc;
460 
461   CURL_TRC_CF(data, cf, "setup trust anchors and CRLs");
462   if(config->verifypeer) {
463     bool imported_native_ca = false;
464 
465     if(ssl_config->native_ca_store) {
466       rc = gnutls_certificate_set_x509_system_trust(gtls->cred);
467       if(rc < 0)
468         infof(data, "error reading native ca store (%s), continuing anyway",
469               gnutls_strerror(rc));
470       else {
471         infof(data, "found %d certificates in native ca store", rc);
472         if(rc > 0)
473           imported_native_ca = true;
474       }
475     }
476 
477     if(config->CAfile) {
478       /* set the trusted CA cert bundle file */
479       gnutls_certificate_set_verify_flags(gtls->cred,
480                                           GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
481 
482       rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
483                                                   config->CAfile,
484                                                   GNUTLS_X509_FMT_PEM);
485       if(rc < 0) {
486         infof(data, "error reading ca cert file %s (%s)%s",
487               config->CAfile, gnutls_strerror(rc),
488               (imported_native_ca ? ", continuing anyway" : ""));
489         if(!imported_native_ca) {
490           ssl_config->certverifyresult = rc;
491           return CURLE_SSL_CACERT_BADFILE;
492         }
493       }
494       else
495         infof(data, "found %d certificates in %s", rc, config->CAfile);
496     }
497 
498     if(config->CApath) {
499       /* set the trusted CA cert directory */
500       rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
501                                                  config->CApath,
502                                                  GNUTLS_X509_FMT_PEM);
503       if(rc < 0) {
504         infof(data, "error reading ca cert file %s (%s)%s",
505               config->CApath, gnutls_strerror(rc),
506               (imported_native_ca ? ", continuing anyway" : ""));
507         if(!imported_native_ca) {
508           ssl_config->certverifyresult = rc;
509           return CURLE_SSL_CACERT_BADFILE;
510         }
511       }
512       else
513         infof(data, "found %d certificates in %s", rc, config->CApath);
514     }
515   }
516 
517   if(config->CRLfile) {
518     /* set the CRL list file */
519     rc = gnutls_certificate_set_x509_crl_file(gtls->cred,
520                                               config->CRLfile,
521                                               GNUTLS_X509_FMT_PEM);
522     if(rc < 0) {
523       failf(data, "error reading crl file %s (%s)",
524             config->CRLfile, gnutls_strerror(rc));
525       return CURLE_SSL_CRL_BADFILE;
526     }
527     else
528       infof(data, "found %d CRL in %s", rc, config->CRLfile);
529   }
530 
531   gtls->trust_setup = TRUE;
532   return CURLE_OK;
533 }
534 
gtls_sessionid_free(void * sessionid,size_t idsize)535 static void gtls_sessionid_free(void *sessionid, size_t idsize)
536 {
537   (void)idsize;
538   free(sessionid);
539 }
540 
gtls_update_session_id(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)541 static CURLcode gtls_update_session_id(struct Curl_cfilter *cf,
542                                        struct Curl_easy *data,
543                                        gnutls_session_t session)
544 {
545   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
546   struct ssl_connect_data *connssl = cf->ctx;
547   CURLcode result = CURLE_OK;
548 
549   if(ssl_config->primary.sessionid) {
550     /* we always unconditionally get the session id here, as even if we
551        already got it from the cache and asked to use it in the connection, it
552        might've been rejected and then a new one is in use now and we need to
553        detect that. */
554     void *connect_sessionid;
555     size_t connect_idsize = 0;
556 
557     /* get the session ID data size */
558     gnutls_session_get_data(session, NULL, &connect_idsize);
559     connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
560     if(!connect_sessionid) {
561       return CURLE_OUT_OF_MEMORY;
562     }
563     else {
564       bool incache;
565       void *ssl_sessionid;
566 
567       /* extract session ID to the allocated buffer */
568       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
569 
570       DEBUGF(infof(data, "get session id (len=%zu) and store in cache",
571                    connect_idsize));
572       Curl_ssl_sessionid_lock(data);
573       incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
574                                         &ssl_sessionid, NULL));
575       if(incache) {
576         /* there was one before in the cache, so instead of risking that the
577            previous one was rejected, we just kill that and store the new */
578         Curl_ssl_delsessionid(data, ssl_sessionid);
579       }
580 
581       /* store this session id, takes ownership */
582       result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
583                                      connect_sessionid, connect_idsize,
584                                      gtls_sessionid_free);
585       Curl_ssl_sessionid_unlock(data);
586     }
587   }
588   return result;
589 }
590 
gtls_handshake_cb(gnutls_session_t session,unsigned int htype,unsigned when,unsigned int incoming,const gnutls_datum_t * msg)591 static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
592                              unsigned when, unsigned int incoming,
593                              const gnutls_datum_t *msg)
594 {
595   struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
596 
597   (void)msg;
598   (void)incoming;
599   if(when) { /* after message has been processed */
600     struct Curl_easy *data = CF_DATA_CURRENT(cf);
601     if(data) {
602       DEBUGF(infof(data, "handshake: %s message type %d",
603              incoming? "incoming" : "outgoing", htype));
604       switch(htype) {
605       case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
606         gtls_update_session_id(cf, data, session);
607         break;
608       }
609       default:
610         break;
611       }
612     }
613   }
614   return 0;
615 }
616 
gtls_client_init(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,struct gtls_ctx * gtls)617 static CURLcode gtls_client_init(struct Curl_cfilter *cf,
618                                  struct Curl_easy *data,
619                                  struct ssl_peer *peer,
620                                  struct gtls_ctx *gtls)
621 {
622   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
623   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
624   unsigned int init_flags;
625   int rc;
626   bool sni = TRUE; /* default is SNI enabled */
627   const char *prioritylist;
628   const char *err = NULL;
629   const char *tls13support;
630   CURLcode result;
631 
632   if(!gtls_inited)
633     gtls_init();
634 
635   if(config->version == CURL_SSLVERSION_SSLv2) {
636     failf(data, "GnuTLS does not support SSLv2");
637     return CURLE_SSL_CONNECT_ERROR;
638   }
639   else if(config->version == CURL_SSLVERSION_SSLv3)
640     sni = FALSE; /* SSLv3 has no SNI */
641 
642   /* allocate a cred struct */
643   rc = gnutls_certificate_allocate_credentials(&gtls->cred);
644   if(rc != GNUTLS_E_SUCCESS) {
645     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
646     return CURLE_SSL_CONNECT_ERROR;
647   }
648 
649 #ifdef USE_GNUTLS_SRP
650   if(config->username && Curl_auth_allowed_to_host(data)) {
651     infof(data, "Using TLS-SRP username: %s", config->username);
652 
653     rc = gnutls_srp_allocate_client_credentials(&gtls->srp_client_cred);
654     if(rc != GNUTLS_E_SUCCESS) {
655       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
656             gnutls_strerror(rc));
657       return CURLE_OUT_OF_MEMORY;
658     }
659 
660     rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
661                                            config->username,
662                                            config->password);
663     if(rc != GNUTLS_E_SUCCESS) {
664       failf(data, "gnutls_srp_set_client_cred() failed: %s",
665             gnutls_strerror(rc));
666       return CURLE_BAD_FUNCTION_ARGUMENT;
667     }
668   }
669 #endif
670 
671   ssl_config->certverifyresult = 0;
672 
673   /* Initialize TLS session as a client */
674   init_flags = GNUTLS_CLIENT;
675 
676 #if defined(GNUTLS_FORCE_CLIENT_CERT)
677   init_flags |= GNUTLS_FORCE_CLIENT_CERT;
678 #endif
679 
680 #if defined(GNUTLS_NO_TICKETS)
681   /* Disable TLS session tickets */
682   init_flags |= GNUTLS_NO_TICKETS;
683 #endif
684 
685 #if defined(GNUTLS_NO_STATUS_REQUEST)
686   if(!config->verifystatus)
687     /* Disable the "status_request" TLS extension, enabled by default since
688        GnuTLS 3.8.0. */
689     init_flags |= GNUTLS_NO_STATUS_REQUEST;
690 #endif
691 
692   rc = gnutls_init(&gtls->session, init_flags);
693   if(rc != GNUTLS_E_SUCCESS) {
694     failf(data, "gnutls_init() failed: %d", rc);
695     return CURLE_SSL_CONNECT_ERROR;
696   }
697 
698   if(sni && peer->sni) {
699     if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
700                               peer->sni, strlen(peer->sni)) < 0) {
701       failf(data, "Failed to set SNI");
702       return CURLE_SSL_CONNECT_ERROR;
703     }
704   }
705 
706   /* Use default priorities */
707   rc = gnutls_set_default_priority(gtls->session);
708   if(rc != GNUTLS_E_SUCCESS)
709     return CURLE_SSL_CONNECT_ERROR;
710 
711   /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
712   tls13support = gnutls_check_version("3.6.5");
713 
714   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
715    * removed if a run-time error indicates that SRP is not supported by this
716    * GnuTLS version */
717 
718   if(config->version == CURL_SSLVERSION_SSLv2 ||
719      config->version == CURL_SSLVERSION_SSLv3) {
720     failf(data, "GnuTLS does not support SSLv2 or SSLv3");
721     return CURLE_SSL_CONNECT_ERROR;
722   }
723 
724   if(config->version == CURL_SSLVERSION_TLSv1_3) {
725     if(!tls13support) {
726       failf(data, "This GnuTLS installation does not support TLS 1.3");
727       return CURLE_SSL_CONNECT_ERROR;
728     }
729   }
730 
731   /* At this point we know we have a supported TLS version, so set it */
732   result = set_ssl_version_min_max(data, peer,
733                                    config, &prioritylist, tls13support);
734   if(result)
735     return result;
736 
737 #ifdef USE_GNUTLS_SRP
738   /* Only add SRP to the cipher list if SRP is requested. Otherwise
739    * GnuTLS will disable TLS 1.3 support. */
740   if(config->username) {
741     char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
742     if(!prioritysrp)
743       return CURLE_OUT_OF_MEMORY;
744     rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
745     free(prioritysrp);
746 
747     if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
748       infof(data, "This GnuTLS does not support SRP");
749     }
750   }
751   else {
752 #endif
753     infof(data, "GnuTLS ciphers: %s", prioritylist);
754     rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
755 #ifdef USE_GNUTLS_SRP
756   }
757 #endif
758 
759   if(rc != GNUTLS_E_SUCCESS) {
760     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
761           rc, err);
762     return CURLE_SSL_CONNECT_ERROR;
763   }
764 
765   if(config->clientcert) {
766     if(!gtls->trust_setup) {
767       result = Curl_gtls_client_trust_setup(cf, data, gtls);
768       if(result)
769         return result;
770     }
771     if(ssl_config->key_passwd) {
772       const unsigned int supported_key_encryption_algorithms =
773         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
774         GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
775         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
776         GNUTLS_PKCS_USE_PBES2_AES_256;
777       rc = gnutls_certificate_set_x509_key_file2(
778            gtls->cred,
779            config->clientcert,
780            ssl_config->key ? ssl_config->key : config->clientcert,
781            do_file_type(ssl_config->cert_type),
782            ssl_config->key_passwd,
783            supported_key_encryption_algorithms);
784       if(rc != GNUTLS_E_SUCCESS) {
785         failf(data,
786               "error reading X.509 potentially-encrypted key file: %s",
787               gnutls_strerror(rc));
788         return CURLE_SSL_CONNECT_ERROR;
789       }
790     }
791     else {
792       if(gnutls_certificate_set_x509_key_file(
793            gtls->cred,
794            config->clientcert,
795            ssl_config->key ? ssl_config->key : config->clientcert,
796            do_file_type(ssl_config->cert_type) ) !=
797          GNUTLS_E_SUCCESS) {
798         failf(data, "error reading X.509 key or certificate file");
799         return CURLE_SSL_CONNECT_ERROR;
800       }
801     }
802   }
803 
804 #ifdef USE_GNUTLS_SRP
805   /* put the credentials to the current session */
806   if(config->username) {
807     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
808                                 gtls->srp_client_cred);
809     if(rc != GNUTLS_E_SUCCESS) {
810       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
811       return CURLE_SSL_CONNECT_ERROR;
812     }
813   }
814   else
815 #endif
816   {
817     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
818                                 gtls->cred);
819     if(rc != GNUTLS_E_SUCCESS) {
820       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
821       return CURLE_SSL_CONNECT_ERROR;
822     }
823   }
824 
825   if(config->verifystatus) {
826     rc = gnutls_ocsp_status_request_enable_client(gtls->session,
827                                                   NULL, 0, NULL);
828     if(rc != GNUTLS_E_SUCCESS) {
829       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
830       return CURLE_SSL_CONNECT_ERROR;
831     }
832   }
833 
834   return CURLE_OK;
835 }
836 
keylog_callback(gnutls_session_t session,const char * label,const gnutls_datum_t * secret)837 static int keylog_callback(gnutls_session_t session, const char *label,
838                            const gnutls_datum_t *secret)
839 {
840   gnutls_datum_t crandom;
841   gnutls_datum_t srandom;
842 
843   gnutls_session_get_random(session, &crandom, &srandom);
844   if(crandom.size != 32) {
845     return -1;
846   }
847 
848   Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
849   return 0;
850 }
851 
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)852 CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
853                             struct Curl_cfilter *cf,
854                             struct Curl_easy *data,
855                             struct ssl_peer *peer,
856                             const unsigned char *alpn, size_t alpn_len,
857                             Curl_gtls_ctx_setup_cb *cb_setup,
858                             void *cb_user_data,
859                             void *ssl_user_data)
860 {
861   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
862   CURLcode result;
863 
864   DEBUGASSERT(gctx);
865 
866   result = gtls_client_init(cf, data, peer, gctx);
867   if(result)
868     return result;
869 
870   gnutls_session_set_ptr(gctx->session, ssl_user_data);
871 
872   if(cb_setup) {
873     result = cb_setup(cf, data, cb_user_data);
874     if(result)
875       return result;
876   }
877 
878   /* Open the file if a TLS or QUIC backend has not done this before. */
879   Curl_tls_keylog_open();
880   if(Curl_tls_keylog_enabled()) {
881     gnutls_session_set_keylog_function(gctx->session, keylog_callback);
882   }
883 
884   /* convert the ALPN string from our arguments to a list of strings
885    * that gnutls wants and will convert internally back to this very
886    * string for sending to the server. nice. */
887   if(alpn && alpn_len) {
888     gnutls_datum_t alpns[5];
889     size_t i, alen = alpn_len;
890     unsigned char *s = (unsigned char *)alpn;
891     unsigned char slen;
892     for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
893       slen = s[0];
894       if(slen >= alen)
895         return CURLE_FAILED_INIT;
896       alpns[i].data = s + 1;
897       alpns[i].size = slen;
898       s += slen + 1;
899       alen -= (size_t)slen + 1;
900     }
901     if(alen) /* not all alpn chars used, wrong format or too many */
902         return CURLE_FAILED_INIT;
903     if(i && gnutls_alpn_set_protocols(gctx->session,
904                                       alpns, (unsigned int)i,
905                                       GNUTLS_ALPN_MANDATORY)) {
906       failf(data, "failed setting ALPN");
907       return CURLE_SSL_CONNECT_ERROR;
908     }
909   }
910 
911   /* This might be a reconnect, so we check for a session ID in the cache
912      to speed up things */
913   if(conn_config->sessionid) {
914     void *ssl_sessionid;
915     size_t ssl_idsize;
916 
917     Curl_ssl_sessionid_lock(data);
918     if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, &ssl_idsize)) {
919       /* we got a session id, use it! */
920       int rc;
921 
922       rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
923       if(rc < 0)
924         infof(data, "SSL failed to set session ID");
925       else
926         infof(data, "SSL reusing session ID (size=%zu)", ssl_idsize);
927     }
928     Curl_ssl_sessionid_unlock(data);
929   }
930   return CURLE_OK;
931 }
932 
933 static CURLcode
gtls_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)934 gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
935 {
936   struct ssl_connect_data *connssl = cf->ctx;
937   struct gtls_ssl_backend_data *backend =
938     (struct gtls_ssl_backend_data *)connssl->backend;
939   struct alpn_proto_buf proto;
940   CURLcode result;
941 
942   DEBUGASSERT(backend);
943   DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
944 
945   if(connssl->state == ssl_connection_complete)
946     /* to make us tolerant against being called more than once for the
947        same connection */
948     return CURLE_OK;
949 
950   memset(&proto, 0, sizeof(proto));
951   if(connssl->alpn) {
952     result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
953     if(result) {
954       failf(data, "Error determining ALPN");
955       return CURLE_SSL_CONNECT_ERROR;
956     }
957   }
958 
959   result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
960                               proto.data, proto.len, NULL, NULL, cf);
961   if(result)
962     return result;
963 
964   gnutls_handshake_set_hook_function(backend->gtls.session,
965                                      GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
966                                      gtls_handshake_cb);
967 
968   /* register callback functions and handle to send and receive data. */
969   gnutls_transport_set_ptr(backend->gtls.session, cf);
970   gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
971   gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
972 
973   return CURLE_OK;
974 }
975 
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)976 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
977                                     gnutls_x509_crt_t cert,
978                                     const char *pinnedpubkey)
979 {
980   /* Scratch */
981   size_t len1 = 0, len2 = 0;
982   unsigned char *buff1 = NULL;
983 
984   gnutls_pubkey_t key = NULL;
985 
986   /* Result is returned to caller */
987   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
988 
989   /* if a path wasn't specified, don't pin */
990   if(!pinnedpubkey)
991     return CURLE_OK;
992 
993   if(!cert)
994     return result;
995 
996   do {
997     int ret;
998 
999     /* Begin Gyrations to get the public key     */
1000     gnutls_pubkey_init(&key);
1001 
1002     ret = gnutls_pubkey_import_x509(key, cert, 0);
1003     if(ret < 0)
1004       break; /* failed */
1005 
1006     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
1007     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
1008       break; /* failed */
1009 
1010     buff1 = malloc(len1);
1011     if(!buff1)
1012       break; /* failed */
1013 
1014     len2 = len1;
1015 
1016     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
1017     if(ret < 0 || len1 != len2)
1018       break; /* failed */
1019 
1020     /* End Gyrations */
1021 
1022     /* The one good exit point */
1023     result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
1024   } while(0);
1025 
1026   if(key)
1027     gnutls_pubkey_deinit(key);
1028 
1029   Curl_safefree(buff1);
1030 
1031   return result;
1032 }
1033 
1034 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)1035 Curl_gtls_verifyserver(struct Curl_easy *data,
1036                        gnutls_session_t session,
1037                        struct ssl_primary_config *config,
1038                        struct ssl_config_data *ssl_config,
1039                        struct ssl_peer *peer,
1040                        const char *pinned_key)
1041 {
1042   unsigned int cert_list_size;
1043   const gnutls_datum_t *chainp;
1044   unsigned int verify_status = 0;
1045   gnutls_x509_crt_t x509_cert, x509_issuer;
1046   gnutls_datum_t issuerp;
1047   gnutls_datum_t certfields;
1048   char certname[65] = ""; /* limited to 64 chars by ASN.1 */
1049   size_t size;
1050   time_t certclock;
1051   int rc;
1052   CURLcode result = CURLE_OK;
1053 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1054   const char *ptr;
1055   unsigned int algo;
1056   unsigned int bits;
1057   gnutls_protocol_t version = gnutls_protocol_get_version(session);
1058 #endif
1059   long * const certverifyresult = &ssl_config->certverifyresult;
1060 
1061 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1062   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
1063   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
1064                                      gnutls_cipher_get(session),
1065                                      gnutls_mac_get(session));
1066 
1067   infof(data, "SSL connection using %s / %s",
1068         gnutls_protocol_get_name(version), ptr);
1069 #endif
1070 
1071   /* This function will return the peer's raw certificate (chain) as sent by
1072      the peer. These certificates are in raw format (DER encoded for
1073      X.509). In case of a X.509 then a certificate list may be present. The
1074      first certificate in the list is the peer's certificate, following the
1075      issuer's certificate, then the issuer's issuer etc. */
1076 
1077   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1078   if(!chainp) {
1079     if(config->verifypeer ||
1080        config->verifyhost ||
1081        config->issuercert) {
1082 #ifdef USE_GNUTLS_SRP
1083       if(ssl_config->primary.username && !config->verifypeer &&
1084          gnutls_cipher_get(session)) {
1085         /* no peer cert, but auth is ok if we have SRP user and cipher and no
1086            peer verify */
1087       }
1088       else {
1089 #endif
1090         failf(data, "failed to get server cert");
1091         *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
1092         return CURLE_PEER_FAILED_VERIFICATION;
1093 #ifdef USE_GNUTLS_SRP
1094       }
1095 #endif
1096     }
1097     infof(data, " common name: WARNING couldn't obtain");
1098   }
1099 
1100   if(data->set.ssl.certinfo && chainp) {
1101     unsigned int i;
1102 
1103     result = Curl_ssl_init_certinfo(data, cert_list_size);
1104     if(result)
1105       return result;
1106 
1107     for(i = 0; i < cert_list_size; i++) {
1108       const char *beg = (const char *) chainp[i].data;
1109       const char *end = beg + chainp[i].size;
1110 
1111       result = Curl_extract_certinfo(data, i, beg, end);
1112       if(result)
1113         return result;
1114     }
1115   }
1116 
1117   if(config->verifypeer) {
1118     /* This function will try to verify the peer's certificate and return its
1119        status (trusted, invalid etc.). The value of status should be one or
1120        more of the gnutls_certificate_status_t enumerated elements bitwise
1121        or'd. To avoid denial of service attacks some default upper limits
1122        regarding the certificate key size and chain size are set. To override
1123        them use gnutls_certificate_set_verify_limits(). */
1124 
1125     rc = gnutls_certificate_verify_peers2(session, &verify_status);
1126     if(rc < 0) {
1127       failf(data, "server cert verify failed: %d", rc);
1128       *certverifyresult = rc;
1129       return CURLE_SSL_CONNECT_ERROR;
1130     }
1131 
1132     *certverifyresult = verify_status;
1133 
1134     /* verify_status is a bitmask of gnutls_certificate_status bits */
1135     if(verify_status & GNUTLS_CERT_INVALID) {
1136       if(config->verifypeer) {
1137         failf(data, "server certificate verification failed. CAfile: %s "
1138               "CRLfile: %s", config->CAfile ? config->CAfile:
1139               "none",
1140               ssl_config->primary.CRLfile ?
1141               ssl_config->primary.CRLfile : "none");
1142         return CURLE_PEER_FAILED_VERIFICATION;
1143       }
1144       else
1145         infof(data, "  server certificate verification FAILED");
1146     }
1147     else
1148       infof(data, "  server certificate verification OK");
1149   }
1150   else
1151     infof(data, "  server certificate verification SKIPPED");
1152 
1153   if(config->verifystatus) {
1154     gnutls_datum_t status_request;
1155     gnutls_ocsp_resp_t ocsp_resp;
1156 
1157     gnutls_ocsp_cert_status_t status;
1158     gnutls_x509_crl_reason_t reason;
1159 
1160     rc = gnutls_ocsp_status_request_get(session, &status_request);
1161 
1162     infof(data, " server certificate status verification FAILED");
1163 
1164     if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1165       failf(data, "No OCSP response received");
1166       return CURLE_SSL_INVALIDCERTSTATUS;
1167     }
1168 
1169     if(rc < 0) {
1170       failf(data, "Invalid OCSP response received");
1171       return CURLE_SSL_INVALIDCERTSTATUS;
1172     }
1173 
1174     gnutls_ocsp_resp_init(&ocsp_resp);
1175 
1176     rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1177     if(rc < 0) {
1178       failf(data, "Invalid OCSP response received");
1179       return CURLE_SSL_INVALIDCERTSTATUS;
1180     }
1181 
1182     (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1183                                       &status, NULL, NULL, NULL, &reason);
1184 
1185     switch(status) {
1186     case GNUTLS_OCSP_CERT_GOOD:
1187       break;
1188 
1189     case GNUTLS_OCSP_CERT_REVOKED: {
1190       const char *crl_reason;
1191 
1192       switch(reason) {
1193         default:
1194         case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1195           crl_reason = "unspecified reason";
1196           break;
1197 
1198         case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1199           crl_reason = "private key compromised";
1200           break;
1201 
1202         case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1203           crl_reason = "CA compromised";
1204           break;
1205 
1206         case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1207           crl_reason = "affiliation has changed";
1208           break;
1209 
1210         case GNUTLS_X509_CRLREASON_SUPERSEDED:
1211           crl_reason = "certificate superseded";
1212           break;
1213 
1214         case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1215           crl_reason = "operation has ceased";
1216           break;
1217 
1218         case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1219           crl_reason = "certificate is on hold";
1220           break;
1221 
1222         case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1223           crl_reason = "will be removed from delta CRL";
1224           break;
1225 
1226         case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1227           crl_reason = "privilege withdrawn";
1228           break;
1229 
1230         case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1231           crl_reason = "AA compromised";
1232           break;
1233       }
1234 
1235       failf(data, "Server certificate was revoked: %s", crl_reason);
1236       break;
1237     }
1238 
1239     default:
1240     case GNUTLS_OCSP_CERT_UNKNOWN:
1241       failf(data, "Server certificate status is unknown");
1242       break;
1243     }
1244 
1245     gnutls_ocsp_resp_deinit(ocsp_resp);
1246     if(status != GNUTLS_OCSP_CERT_GOOD)
1247       return CURLE_SSL_INVALIDCERTSTATUS;
1248   }
1249   else
1250     infof(data, "  server certificate status verification SKIPPED");
1251 
1252   /* initialize an X.509 certificate structure. */
1253   gnutls_x509_crt_init(&x509_cert);
1254 
1255   if(chainp)
1256     /* convert the given DER or PEM encoded Certificate to the native
1257        gnutls_x509_crt_t format */
1258     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1259 
1260   if(config->issuercert) {
1261     gnutls_x509_crt_init(&x509_issuer);
1262     issuerp = load_file(config->issuercert);
1263     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1264     rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1265     gnutls_x509_crt_deinit(x509_issuer);
1266     unload_file(issuerp);
1267     if(rc <= 0) {
1268       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1269             config->issuercert?config->issuercert:"none");
1270       gnutls_x509_crt_deinit(x509_cert);
1271       return CURLE_SSL_ISSUER_ERROR;
1272     }
1273     infof(data, "  server certificate issuer check OK (Issuer Cert: %s)",
1274           config->issuercert?config->issuercert:"none");
1275   }
1276 
1277   size = sizeof(certname);
1278   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1279                                      0, /* the first and only one */
1280                                      FALSE,
1281                                      certname,
1282                                      &size);
1283   if(rc) {
1284     infof(data, "error fetching CN from cert:%s",
1285           gnutls_strerror(rc));
1286   }
1287 
1288   /* This function will check if the given certificate's subject matches the
1289      given hostname. This is a basic implementation of the matching described
1290      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1291      alternative name PKIX extension. Returns non zero on success, and zero on
1292      failure. */
1293   rc = gnutls_x509_crt_check_hostname(x509_cert, peer->hostname);
1294 #if GNUTLS_VERSION_NUMBER < 0x030306
1295   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1296      addresses. */
1297   if(!rc) {
1298 #ifdef USE_IPV6
1299     #define use_addr in6_addr
1300 #else
1301     #define use_addr in_addr
1302 #endif
1303     unsigned char addrbuf[sizeof(struct use_addr)];
1304     size_t addrlen = 0;
1305 
1306     if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
1307       addrlen = 4;
1308 #ifdef USE_IPV6
1309     else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
1310       addrlen = 16;
1311 #endif
1312 
1313     if(addrlen) {
1314       unsigned char certaddr[sizeof(struct use_addr)];
1315       int i;
1316 
1317       for(i = 0; ; i++) {
1318         size_t certaddrlen = sizeof(certaddr);
1319         int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1320                                                        &certaddrlen, NULL);
1321         /* If this happens, it wasn't an IP address. */
1322         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1323           continue;
1324         if(ret < 0)
1325           break;
1326         if(ret != GNUTLS_SAN_IPADDRESS)
1327           continue;
1328         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1329           rc = 1;
1330           break;
1331         }
1332       }
1333     }
1334   }
1335 #endif
1336   if(!rc) {
1337     if(config->verifyhost) {
1338       failf(data, "SSL: certificate subject name (%s) does not match "
1339             "target host name '%s'", certname, peer->dispname);
1340       gnutls_x509_crt_deinit(x509_cert);
1341       return CURLE_PEER_FAILED_VERIFICATION;
1342     }
1343     else
1344       infof(data, "  common name: %s (does not match '%s')",
1345             certname, peer->dispname);
1346   }
1347   else
1348     infof(data, "  common name: %s (matched)", certname);
1349 
1350   /* Check for time-based validity */
1351   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1352 
1353   if(certclock == (time_t)-1) {
1354     if(config->verifypeer) {
1355       failf(data, "server cert expiration date verify failed");
1356       *certverifyresult = GNUTLS_CERT_EXPIRED;
1357       gnutls_x509_crt_deinit(x509_cert);
1358       return CURLE_SSL_CONNECT_ERROR;
1359     }
1360     else
1361       infof(data, "  server certificate expiration date verify FAILED");
1362   }
1363   else {
1364     if(certclock < time(NULL)) {
1365       if(config->verifypeer) {
1366         failf(data, "server certificate expiration date has passed.");
1367         *certverifyresult = GNUTLS_CERT_EXPIRED;
1368         gnutls_x509_crt_deinit(x509_cert);
1369         return CURLE_PEER_FAILED_VERIFICATION;
1370       }
1371       else
1372         infof(data, "  server certificate expiration date FAILED");
1373     }
1374     else
1375       infof(data, "  server certificate expiration date OK");
1376   }
1377 
1378   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1379 
1380   if(certclock == (time_t)-1) {
1381     if(config->verifypeer) {
1382       failf(data, "server cert activation date verify failed");
1383       *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1384       gnutls_x509_crt_deinit(x509_cert);
1385       return CURLE_SSL_CONNECT_ERROR;
1386     }
1387     else
1388       infof(data, "  server certificate activation date verify FAILED");
1389   }
1390   else {
1391     if(certclock > time(NULL)) {
1392       if(config->verifypeer) {
1393         failf(data, "server certificate not activated yet.");
1394         *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1395         gnutls_x509_crt_deinit(x509_cert);
1396         return CURLE_PEER_FAILED_VERIFICATION;
1397       }
1398       else
1399         infof(data, "  server certificate activation date FAILED");
1400     }
1401     else
1402       infof(data, "  server certificate activation date OK");
1403   }
1404 
1405   if(pinned_key) {
1406     result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
1407     if(result != CURLE_OK) {
1408       failf(data, "SSL: public key does not match pinned public key");
1409       gnutls_x509_crt_deinit(x509_cert);
1410       return result;
1411     }
1412   }
1413 
1414   /* Show:
1415 
1416   - subject
1417   - start date
1418   - expire date
1419   - common name
1420   - issuer
1421 
1422   */
1423 
1424 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1425   /* public key algorithm's parameters */
1426   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1427   infof(data, "  certificate public key: %s",
1428         gnutls_pk_algorithm_get_name(algo));
1429 
1430   /* version of the X.509 certificate. */
1431   infof(data, "  certificate version: #%d",
1432         gnutls_x509_crt_get_version(x509_cert));
1433 
1434 
1435   rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1436   if(rc)
1437     infof(data, "Failed to get certificate name");
1438   else {
1439     infof(data, "  subject: %s", certfields.data);
1440 
1441     certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1442     showtime(data, "start date", certclock);
1443 
1444     certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1445     showtime(data, "expire date", certclock);
1446 
1447     gnutls_free(certfields.data);
1448   }
1449 
1450   rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1451   if(rc)
1452     infof(data, "Failed to get certificate issuer");
1453   else {
1454     infof(data, "  issuer: %s", certfields.data);
1455 
1456     gnutls_free(certfields.data);
1457   }
1458 #endif
1459 
1460   gnutls_x509_crt_deinit(x509_cert);
1461 
1462   return result;
1463 }
1464 
gtls_verifyserver(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)1465 static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
1466                                   struct Curl_easy *data,
1467                                   gnutls_session_t session)
1468 {
1469   struct ssl_connect_data *connssl = cf->ctx;
1470   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1471   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1472 #ifndef CURL_DISABLE_PROXY
1473   const char *pinned_key = Curl_ssl_cf_is_proxy(cf)?
1474     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
1475     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1476 #else
1477   const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1478 #endif
1479   CURLcode result;
1480 
1481   result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
1482                                   &connssl->peer, pinned_key);
1483   if(result)
1484     goto out;
1485 
1486   if(connssl->alpn) {
1487     gnutls_datum_t proto;
1488     int rc;
1489 
1490     rc = gnutls_alpn_get_selected_protocol(session, &proto);
1491     if(rc == 0)
1492       Curl_alpn_set_negotiated(cf, data, proto.data, proto.size);
1493     else
1494       Curl_alpn_set_negotiated(cf, data, NULL, 0);
1495   }
1496 
1497   /* Only on TLSv1.2 or lower do we have the session id now. For
1498    * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
1499   if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
1500     result = gtls_update_session_id(cf, data, session);
1501 
1502 out:
1503   return result;
1504 }
1505 
1506 /*
1507  * This function is called after the TCP connect has completed. Setup the TLS
1508  * layer and do all necessary magic.
1509  */
1510 /* We use connssl->connecting_state to keep track of the connection status;
1511    there are three states: 'ssl_connect_1' (not started yet or complete),
1512    'ssl_connect_2_reading' (waiting for data from server), and
1513    'ssl_connect_2_writing' (waiting to be able to write).
1514  */
1515 static CURLcode
gtls_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1516 gtls_connect_common(struct Curl_cfilter *cf,
1517                     struct Curl_easy *data,
1518                     bool nonblocking,
1519                     bool *done)
1520 {
1521   struct ssl_connect_data *connssl = cf->ctx;
1522   int rc;
1523   CURLcode result = CURLE_OK;
1524 
1525   /* Initiate the connection, if not already done */
1526   if(ssl_connect_1 == connssl->connecting_state) {
1527     rc = gtls_connect_step1(cf, data);
1528     if(rc) {
1529       result = rc;
1530       goto out;
1531     }
1532   }
1533 
1534   rc = handshake(cf, data, TRUE, nonblocking);
1535   if(rc) {
1536     /* handshake() sets its own error message with failf() */
1537     result = rc;
1538     goto out;
1539   }
1540 
1541   /* Finish connecting once the handshake is done */
1542   if(ssl_connect_1 == connssl->connecting_state) {
1543     struct gtls_ssl_backend_data *backend =
1544       (struct gtls_ssl_backend_data *)connssl->backend;
1545     gnutls_session_t session;
1546     DEBUGASSERT(backend);
1547     session = backend->gtls.session;
1548     rc = gtls_verifyserver(cf, data, session);
1549     if(rc) {
1550       result = rc;
1551       goto out;
1552     }
1553     connssl->state = ssl_connection_complete;
1554   }
1555 
1556 out:
1557   *done = ssl_connect_1 == connssl->connecting_state;
1558 
1559   return result;
1560 }
1561 
gtls_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1562 static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
1563                                          struct Curl_easy *data,
1564                                          bool *done)
1565 {
1566   return gtls_connect_common(cf, data, TRUE, done);
1567 }
1568 
gtls_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1569 static CURLcode gtls_connect(struct Curl_cfilter *cf,
1570                              struct Curl_easy *data)
1571 {
1572   CURLcode result;
1573   bool done = FALSE;
1574 
1575   result = gtls_connect_common(cf, data, FALSE, &done);
1576   if(result)
1577     return result;
1578 
1579   DEBUGASSERT(done);
1580 
1581   return CURLE_OK;
1582 }
1583 
gtls_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1584 static bool gtls_data_pending(struct Curl_cfilter *cf,
1585                               const struct Curl_easy *data)
1586 {
1587   struct ssl_connect_data *ctx = cf->ctx;
1588   struct gtls_ssl_backend_data *backend;
1589 
1590   (void)data;
1591   DEBUGASSERT(ctx && ctx->backend);
1592   backend = (struct gtls_ssl_backend_data *)ctx->backend;
1593   if(backend->gtls.session &&
1594      0 != gnutls_record_check_pending(backend->gtls.session))
1595     return TRUE;
1596   return FALSE;
1597 }
1598 
gtls_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * mem,size_t len,CURLcode * curlcode)1599 static ssize_t gtls_send(struct Curl_cfilter *cf,
1600                          struct Curl_easy *data,
1601                          const void *mem,
1602                          size_t len,
1603                          CURLcode *curlcode)
1604 {
1605   struct ssl_connect_data *connssl = cf->ctx;
1606   struct gtls_ssl_backend_data *backend =
1607     (struct gtls_ssl_backend_data *)connssl->backend;
1608   ssize_t rc;
1609 
1610   (void)data;
1611   DEBUGASSERT(backend);
1612   backend->gtls.io_result = CURLE_OK;
1613   rc = gnutls_record_send(backend->gtls.session, mem, len);
1614 
1615   if(rc < 0) {
1616     *curlcode = (rc == GNUTLS_E_AGAIN)?
1617       CURLE_AGAIN :
1618       (backend->gtls.io_result? backend->gtls.io_result : CURLE_SEND_ERROR);
1619 
1620     rc = -1;
1621   }
1622 
1623   return rc;
1624 }
1625 
gtls_close(struct Curl_cfilter * cf,struct Curl_easy * data)1626 static void gtls_close(struct Curl_cfilter *cf,
1627                        struct Curl_easy *data)
1628 {
1629   struct ssl_connect_data *connssl = cf->ctx;
1630   struct gtls_ssl_backend_data *backend =
1631     (struct gtls_ssl_backend_data *)connssl->backend;
1632 
1633   (void) data;
1634   DEBUGASSERT(backend);
1635 
1636   if(backend->gtls.session) {
1637     char buf[32];
1638     /* Maybe the server has already sent a close notify alert.
1639        Read it to avoid an RST on the TCP connection. */
1640     (void)gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
1641     gnutls_bye(backend->gtls.session, GNUTLS_SHUT_WR);
1642     gnutls_deinit(backend->gtls.session);
1643     backend->gtls.session = NULL;
1644   }
1645   if(backend->gtls.cred) {
1646     gnutls_certificate_free_credentials(backend->gtls.cred);
1647     backend->gtls.cred = NULL;
1648   }
1649 #ifdef USE_GNUTLS_SRP
1650   if(backend->gtls.srp_client_cred) {
1651     gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1652     backend->gtls.srp_client_cred = NULL;
1653   }
1654 #endif
1655 }
1656 
1657 /*
1658  * This function is called to shut down the SSL layer but keep the
1659  * socket open (CCC - Clear Command Channel)
1660  */
gtls_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data)1661 static int gtls_shutdown(struct Curl_cfilter *cf,
1662                          struct Curl_easy *data)
1663 {
1664   struct ssl_connect_data *connssl = cf->ctx;
1665   struct gtls_ssl_backend_data *backend =
1666     (struct gtls_ssl_backend_data *)connssl->backend;
1667   int retval = 0;
1668 
1669   DEBUGASSERT(backend);
1670 
1671 #ifndef CURL_DISABLE_FTP
1672   /* This has only been tested on the proftpd server, and the mod_tls code
1673      sends a close notify alert without waiting for a close notify alert in
1674      response. Thus we wait for a close notify alert from the server, but
1675      we do not send one. Let's hope other servers do the same... */
1676 
1677   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1678     gnutls_bye(backend->gtls.session, GNUTLS_SHUT_WR);
1679 #endif
1680 
1681   if(backend->gtls.session) {
1682     ssize_t result;
1683     bool done = FALSE;
1684     char buf[120];
1685 
1686     while(!done && !connssl->peer_closed) {
1687       int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
1688                                  SSL_SHUTDOWN_TIMEOUT);
1689       if(what > 0) {
1690         /* Something to read, let's do it and hope that it is the close
1691            notify alert from the server */
1692         result = gnutls_record_recv(backend->gtls.session,
1693                                     buf, sizeof(buf));
1694         switch(result) {
1695         case 0:
1696           /* This is the expected response. There was no data but only
1697              the close notify alert */
1698           done = TRUE;
1699           break;
1700         case GNUTLS_E_AGAIN:
1701         case GNUTLS_E_INTERRUPTED:
1702           infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED");
1703           break;
1704         default:
1705           retval = -1;
1706           done = TRUE;
1707           break;
1708         }
1709       }
1710       else if(0 == what) {
1711         /* timeout */
1712         failf(data, "SSL shutdown timeout");
1713         done = TRUE;
1714       }
1715       else {
1716         /* anything that gets here is fatally bad */
1717         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1718         retval = -1;
1719         done = TRUE;
1720       }
1721     }
1722     gnutls_deinit(backend->gtls.session);
1723   }
1724   gnutls_certificate_free_credentials(backend->gtls.cred);
1725 
1726 #ifdef USE_GNUTLS_SRP
1727   {
1728     struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1729     if(ssl_config->primary.username)
1730       gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
1731   }
1732 #endif
1733 
1734   backend->gtls.cred = NULL;
1735   backend->gtls.session = NULL;
1736 
1737   return retval;
1738 }
1739 
gtls_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t buffersize,CURLcode * curlcode)1740 static ssize_t gtls_recv(struct Curl_cfilter *cf,
1741                          struct Curl_easy *data,
1742                          char *buf,
1743                          size_t buffersize,
1744                          CURLcode *curlcode)
1745 {
1746   struct ssl_connect_data *connssl = cf->ctx;
1747   struct gtls_ssl_backend_data *backend =
1748     (struct gtls_ssl_backend_data *)connssl->backend;
1749   ssize_t ret;
1750 
1751   (void)data;
1752   DEBUGASSERT(backend);
1753 
1754   backend->gtls.io_result = CURLE_OK;
1755   ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
1756   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1757     *curlcode = CURLE_AGAIN;
1758     ret = -1;
1759     goto out;
1760   }
1761 
1762   if(ret == GNUTLS_E_REHANDSHAKE) {
1763     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1764        proper way" takes a whole lot of work. */
1765     CURLcode result = handshake(cf, data, FALSE, FALSE);
1766     if(result)
1767       /* handshake() writes error message on its own */
1768       *curlcode = result;
1769     else
1770       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1771     ret = -1;
1772     goto out;
1773   }
1774 
1775   if(ret < 0) {
1776     failf(data, "GnuTLS recv error (%d): %s",
1777 
1778           (int)ret, gnutls_strerror((int)ret));
1779     *curlcode = backend->gtls.io_result?
1780                 backend->gtls.io_result : CURLE_RECV_ERROR;
1781     ret = -1;
1782     goto out;
1783   }
1784 
1785 out:
1786   return ret;
1787 }
1788 
gtls_version(char * buffer,size_t size)1789 static size_t gtls_version(char *buffer, size_t size)
1790 {
1791   return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1792 }
1793 
1794 /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1795 static CURLcode gtls_random(struct Curl_easy *data,
1796                             unsigned char *entropy, size_t length)
1797 {
1798   int rc;
1799   (void)data;
1800   rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1801   return rc?CURLE_FAILED_INIT:CURLE_OK;
1802 }
1803 
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)1804 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
1805                                size_t tmplen,
1806                                unsigned char *sha256sum, /* output */
1807                                size_t sha256len)
1808 {
1809   struct sha256_ctx SHA256pw;
1810   sha256_init(&SHA256pw);
1811   sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1812   sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1813   return CURLE_OK;
1814 }
1815 
gtls_cert_status_request(void)1816 static bool gtls_cert_status_request(void)
1817 {
1818   return TRUE;
1819 }
1820 
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1821 static void *gtls_get_internals(struct ssl_connect_data *connssl,
1822                                 CURLINFO info UNUSED_PARAM)
1823 {
1824   struct gtls_ssl_backend_data *backend =
1825     (struct gtls_ssl_backend_data *)connssl->backend;
1826   (void)info;
1827   DEBUGASSERT(backend);
1828   return backend->gtls.session;
1829 }
1830 
1831 const struct Curl_ssl Curl_ssl_gnutls = {
1832   { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
1833 
1834   SSLSUPP_CA_PATH  |
1835   SSLSUPP_CERTINFO |
1836   SSLSUPP_PINNEDPUBKEY |
1837   SSLSUPP_HTTPS_PROXY,
1838 
1839   sizeof(struct gtls_ssl_backend_data),
1840 
1841   gtls_init,                     /* init */
1842   gtls_cleanup,                  /* cleanup */
1843   gtls_version,                  /* version */
1844   Curl_none_check_cxn,           /* check_cxn */
1845   gtls_shutdown,                 /* shutdown */
1846   gtls_data_pending,             /* data_pending */
1847   gtls_random,                   /* random */
1848   gtls_cert_status_request,      /* cert_status_request */
1849   gtls_connect,                  /* connect */
1850   gtls_connect_nonblocking,      /* connect_nonblocking */
1851   Curl_ssl_adjust_pollset,       /* adjust_pollset */
1852   gtls_get_internals,            /* get_internals */
1853   gtls_close,                    /* close_one */
1854   Curl_none_close_all,           /* close_all */
1855   Curl_none_set_engine,          /* set_engine */
1856   Curl_none_set_engine_default,  /* set_engine_default */
1857   Curl_none_engines_list,        /* engines_list */
1858   Curl_none_false_start,         /* false_start */
1859   gtls_sha256sum,                /* sha256sum */
1860   NULL,                          /* associate_connection */
1861   NULL,                          /* disassociate_connection */
1862   NULL,                          /* free_multi_ssl_backend_data */
1863   gtls_recv,                     /* recv decrypted data */
1864   gtls_send,                     /* send data to encrypt */
1865 };
1866 
1867 #endif /* USE_GNUTLS */
1868