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