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