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