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