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