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