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