1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, 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 sslgen.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 "setup.h"
32
33#ifdef USE_GNUTLS
34
35#include <gnutls/gnutls.h>
36#include <gnutls/x509.h>
37#include <gcrypt.h>
38
39#ifdef HAVE_SYS_SOCKET_H
40#include <sys/socket.h>
41#endif
42
43#include "urldata.h"
44#include "sendf.h"
45#include "inet_pton.h"
46#include "gtls.h"
47#include "sslgen.h"
48#include "parsedate.h"
49#include "connect.h" /* for the connect timeout */
50#include "select.h"
51#include "rawstr.h"
52
53#define _MPRINTF_REPLACE /* use our functions only */
54#include <curl/mprintf.h>
55#include "curl_memory.h"
56/* The last #include file should be: */
57#include "memdebug.h"
58
59/*
60 Some hackish cast macros based on:
61 http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html
62*/
63#ifndef GNUTLS_POINTER_TO_INT_CAST
64#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
65#endif
66#ifndef GNUTLS_INT_TO_POINTER_CAST
67#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
68#endif
69
70/* Enable GnuTLS debugging by defining GTLSDEBUG */
71/*#define GTLSDEBUG */
72
73#ifdef GTLSDEBUG
74static void tls_log_func(int level, const char *str)
75{
76    fprintf(stderr, "|<%d>| %s", level, str);
77}
78#endif
79static bool gtls_inited = FALSE;
80
81#if defined(GNUTLS_VERSION_NUMBER)
82#  if (GNUTLS_VERSION_NUMBER >= 0x020c00)
83#    undef gnutls_transport_set_lowat
84#    define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
85#    define USE_GNUTLS_PRIORITY_SET_DIRECT 1
86#  endif
87#  if (GNUTLS_VERSION_NUMBER >= 0x020c03)
88#    undef gnutls_transport_set_global_errno
89#    define gnutls_transport_set_global_errno(A) SET_ERRNO((A))
90#  endif
91#endif
92
93/*
94 * Custom push and pull callback functions used by GNU TLS to read and write
95 * to the socket.  These functions are simple wrappers to send() and recv()
96 * (although here using the sread/swrite macros as defined by setup_once.h).
97 * We use custom functions rather than the GNU TLS defaults because it allows
98 * us to get specific about the fourth "flags" argument, and to use arbitrary
99 * private data with gnutls_transport_set_ptr if we wish.
100 *
101 * When these custom push and pull callbacks fail, GNU TLS checks its own
102 * session-specific error variable, and when not set also its own global
103 * errno variable, in order to take appropriate action. GNU TLS does not
104 * require that the transport is actually a socket. This implies that for
105 * Windows builds these callbacks should ideally set the session-specific
106 * error variable using function gnutls_transport_set_errno or as a last
107 * resort global errno variable using gnutls_transport_set_global_errno,
108 * with a transport agnostic error value. This implies that some winsock
109 * error translation must take place in these callbacks.
110 */
111
112#ifdef USE_WINSOCK
113#  define gtls_EINTR  4
114#  define gtls_EIO    5
115#  define gtls_EAGAIN 11
116static int gtls_mapped_sockerrno(void)
117{
118  switch(SOCKERRNO) {
119  case WSAEWOULDBLOCK:
120    return gtls_EAGAIN;
121  case WSAEINTR:
122    return gtls_EINTR;
123  default:
124    break;
125  }
126  return gtls_EIO;
127}
128#endif
129
130static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
131{
132  ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
133#ifdef USE_WINSOCK
134  if(ret < 0)
135    gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
136#endif
137  return ret;
138}
139
140static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
141{
142  ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
143#ifdef USE_WINSOCK
144  if(ret < 0)
145    gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
146#endif
147  return ret;
148}
149
150/* Curl_gtls_init()
151 *
152 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
153 * are not thread-safe and thus this function itself is not thread-safe and
154 * must only be called from within curl_global_init() to keep the thread
155 * situation under control!
156 */
157int Curl_gtls_init(void)
158{
159  int ret = 1;
160  if(!gtls_inited) {
161    ret = gnutls_global_init()?0:1;
162#ifdef GTLSDEBUG
163    gnutls_global_set_log_function(tls_log_func);
164    gnutls_global_set_log_level(2);
165#endif
166    gtls_inited = TRUE;
167  }
168  return ret;
169}
170
171int Curl_gtls_cleanup(void)
172{
173  if(gtls_inited) {
174    gnutls_global_deinit();
175    gtls_inited = FALSE;
176  }
177  return 1;
178}
179
180static void showtime(struct SessionHandle *data,
181                     const char *text,
182                     time_t stamp)
183{
184  struct tm buffer;
185  const struct tm *tm = &buffer;
186  CURLcode result = Curl_gmtime(stamp, &buffer);
187  if(result)
188    return;
189
190  snprintf(data->state.buffer,
191           BUFSIZE,
192           "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n",
193           text,
194           Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
195           tm->tm_mday,
196           Curl_month[tm->tm_mon],
197           tm->tm_year + 1900,
198           tm->tm_hour,
199           tm->tm_min,
200           tm->tm_sec);
201  infof(data, "%s", data->state.buffer);
202}
203
204static gnutls_datum load_file (const char *file)
205{
206  FILE *f;
207  gnutls_datum loaded_file = { NULL, 0 };
208  long filelen;
209  void *ptr;
210
211  if(!(f = fopen(file, "r")))
212    return loaded_file;
213  if(fseek(f, 0, SEEK_END) != 0
214     || (filelen = ftell(f)) < 0
215     || fseek(f, 0, SEEK_SET) != 0
216     || !(ptr = malloc((size_t)filelen)))
217    goto out;
218  if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
219    free(ptr);
220    goto out;
221  }
222
223  loaded_file.data = ptr;
224  loaded_file.size = (unsigned int)filelen;
225out:
226  fclose(f);
227  return loaded_file;
228}
229
230static void unload_file(gnutls_datum data) {
231  free(data.data);
232}
233
234
235/* this function does a SSL/TLS (re-)handshake */
236static CURLcode handshake(struct connectdata *conn,
237                          int sockindex,
238                          bool duringconnect,
239                          bool nonblocking)
240{
241  struct SessionHandle *data = conn->data;
242  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
243  gnutls_session session = conn->ssl[sockindex].session;
244  curl_socket_t sockfd = conn->sock[sockindex];
245  long timeout_ms;
246  int rc;
247  int what;
248
249  for(;;) {
250    /* check allowed time left */
251    timeout_ms = Curl_timeleft(data, NULL, duringconnect);
252
253    if(timeout_ms < 0) {
254      /* no need to continue if time already is up */
255      failf(data, "SSL connection timeout");
256      return CURLE_OPERATION_TIMEDOUT;
257    }
258
259    /* if ssl is expecting something, check if it's available. */
260    if(connssl->connecting_state == ssl_connect_2_reading
261       || connssl->connecting_state == ssl_connect_2_writing) {
262
263      curl_socket_t writefd = ssl_connect_2_writing==
264        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
265      curl_socket_t readfd = ssl_connect_2_reading==
266        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
267
268      what = Curl_socket_ready(readfd, writefd,
269                               nonblocking?0:
270                               timeout_ms?timeout_ms:1000);
271      if(what < 0) {
272        /* fatal error */
273        failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
274        return CURLE_SSL_CONNECT_ERROR;
275      }
276      else if(0 == what) {
277        if(nonblocking)
278          return CURLE_OK;
279        else if(timeout_ms) {
280          /* timeout */
281          failf(data, "SSL connection timeout at %ld", timeout_ms);
282          return CURLE_OPERATION_TIMEDOUT;
283        }
284      }
285      /* socket is readable or writable */
286    }
287
288    rc = gnutls_handshake(session);
289
290    if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
291      connssl->connecting_state =
292        gnutls_record_get_direction(session)?
293        ssl_connect_2_writing:ssl_connect_2_reading;
294      if(nonblocking)
295        return CURLE_OK;
296    }
297    else if(rc < 0) {
298      failf(data, "gnutls_handshake() failed: %s", gnutls_strerror(rc));
299      return CURLE_SSL_CONNECT_ERROR;
300    }
301    else {
302      /* Reset our connect state machine */
303      connssl->connecting_state = ssl_connect_1;
304      return CURLE_OK;
305    }
306  }
307}
308
309static gnutls_x509_crt_fmt do_file_type(const char *type)
310{
311  if(!type || !type[0])
312    return GNUTLS_X509_FMT_PEM;
313  if(Curl_raw_equal(type, "PEM"))
314    return GNUTLS_X509_FMT_PEM;
315  if(Curl_raw_equal(type, "DER"))
316    return GNUTLS_X509_FMT_DER;
317  return -1;
318}
319
320static CURLcode
321gtls_connect_step1(struct connectdata *conn,
322                   int sockindex)
323{
324#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
325  static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
326#endif
327  struct SessionHandle *data = conn->data;
328  gnutls_session session;
329  int rc;
330  void *ssl_sessionid;
331  size_t ssl_idsize;
332  bool sni = TRUE; /* default is SNI enabled */
333#ifdef ENABLE_IPV6
334  struct in6_addr addr;
335#else
336  struct in_addr addr;
337#endif
338
339  if(conn->ssl[sockindex].state == ssl_connection_complete)
340    /* to make us tolerant against being called more than once for the
341       same connection */
342    return CURLE_OK;
343
344  if(!gtls_inited)
345    Curl_gtls_init();
346
347  /* GnuTLS only supports SSLv3 and TLSv1 */
348  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
349    failf(data, "GnuTLS does not support SSLv2");
350    return CURLE_SSL_CONNECT_ERROR;
351  }
352  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
353    sni = FALSE; /* SSLv3 has no SNI */
354
355  /* allocate a cred struct */
356  rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
357  if(rc != GNUTLS_E_SUCCESS) {
358    failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
359    return CURLE_SSL_CONNECT_ERROR;
360  }
361
362#ifdef USE_TLS_SRP
363  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
364    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
365
366    rc = gnutls_srp_allocate_client_credentials(
367           &conn->ssl[sockindex].srp_client_cred);
368    if(rc != GNUTLS_E_SUCCESS) {
369      failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
370            gnutls_strerror(rc));
371      return CURLE_OUT_OF_MEMORY;
372    }
373
374    rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
375                                           srp_client_cred,
376                                           data->set.ssl.username,
377                                           data->set.ssl.password);
378    if(rc != GNUTLS_E_SUCCESS) {
379      failf(data, "gnutls_srp_set_client_cred() failed: %s",
380            gnutls_strerror(rc));
381      return CURLE_BAD_FUNCTION_ARGUMENT;
382    }
383  }
384#endif
385
386  if(data->set.ssl.CAfile) {
387    /* set the trusted CA cert bundle file */
388    gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
389                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
390
391    rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
392                                                data->set.ssl.CAfile,
393                                                GNUTLS_X509_FMT_PEM);
394    if(rc < 0) {
395      infof(data, "error reading ca cert file %s (%s)\n",
396            data->set.ssl.CAfile, gnutls_strerror(rc));
397      if(data->set.ssl.verifypeer)
398        return CURLE_SSL_CACERT_BADFILE;
399    }
400    else
401      infof(data, "found %d certificates in %s\n",
402            rc, data->set.ssl.CAfile);
403  }
404
405  if(data->set.ssl.CRLfile) {
406    /* set the CRL list file */
407    rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
408                                              data->set.ssl.CRLfile,
409                                              GNUTLS_X509_FMT_PEM);
410    if(rc < 0) {
411      failf(data, "error reading crl file %s (%s)\n",
412            data->set.ssl.CRLfile, gnutls_strerror(rc));
413      return CURLE_SSL_CRL_BADFILE;
414    }
415    else
416      infof(data, "found %d CRL in %s\n",
417            rc, data->set.ssl.CRLfile);
418  }
419
420  /* Initialize TLS session as a client */
421  rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
422  if(rc != GNUTLS_E_SUCCESS) {
423    failf(data, "gnutls_init() failed: %d", rc);
424    return CURLE_SSL_CONNECT_ERROR;
425  }
426
427  /* convenient assign */
428  session = conn->ssl[sockindex].session;
429
430  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
431#ifdef ENABLE_IPV6
432     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
433#endif
434     sni &&
435     (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
436                             strlen(conn->host.name)) < 0))
437    infof(data, "WARNING: failed to configure server name indication (SNI) "
438          "TLS extension\n");
439
440  /* Use default priorities */
441  rc = gnutls_set_default_priority(session);
442  if(rc != GNUTLS_E_SUCCESS)
443    return CURLE_SSL_CONNECT_ERROR;
444
445  if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) {
446#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
447    static const int protocol_priority[] = { GNUTLS_SSL3, 0 };
448    rc = gnutls_protocol_set_priority(session, protocol_priority);
449#else
450    const char *err;
451    rc = gnutls_priority_set_direct(session, "-VERS-TLS-ALL:+VERS-SSL3.0",
452                                    &err);
453#endif
454    if(rc != GNUTLS_E_SUCCESS)
455      return CURLE_SSL_CONNECT_ERROR;
456  }
457
458#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
459  /* Sets the priority on the certificate types supported by gnutls. Priority
460     is higher for types specified before others. After specifying the types
461     you want, you must append a 0. */
462  rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
463  if(rc != GNUTLS_E_SUCCESS)
464    return CURLE_SSL_CONNECT_ERROR;
465#endif
466
467  if(data->set.str[STRING_CERT]) {
468    if(gnutls_certificate_set_x509_key_file(
469         conn->ssl[sockindex].cred,
470         data->set.str[STRING_CERT],
471         data->set.str[STRING_KEY] ?
472         data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
473         do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
474       GNUTLS_E_SUCCESS) {
475      failf(data, "error reading X.509 key or certificate file");
476      return CURLE_SSL_CONNECT_ERROR;
477    }
478  }
479
480#ifdef USE_TLS_SRP
481  /* put the credentials to the current session */
482  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
483    rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
484                                conn->ssl[sockindex].srp_client_cred);
485    if(rc != GNUTLS_E_SUCCESS)
486      failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
487  }
488  else
489#endif
490    rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
491                                conn->ssl[sockindex].cred);
492
493  /* set the connection handle (file descriptor for the socket) */
494  gnutls_transport_set_ptr(session,
495                           GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
496
497  /* register callback functions to send and receive data. */
498  gnutls_transport_set_push_function(session, Curl_gtls_push);
499  gnutls_transport_set_pull_function(session, Curl_gtls_pull);
500
501  /* lowat must be set to zero when using custom push and pull functions. */
502  gnutls_transport_set_lowat(session, 0);
503
504  /* This might be a reconnect, so we check for a session ID in the cache
505     to speed up things */
506
507  if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
508    /* we got a session id, use it! */
509    gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
510
511    /* Informational message */
512    infof (data, "SSL re-using session ID\n");
513  }
514
515  return CURLE_OK;
516}
517
518static Curl_recv gtls_recv;
519static Curl_send gtls_send;
520
521static CURLcode
522gtls_connect_step3(struct connectdata *conn,
523                   int sockindex)
524{
525  unsigned int cert_list_size;
526  const gnutls_datum *chainp;
527  unsigned int verify_status;
528  gnutls_x509_crt x509_cert,x509_issuer;
529  gnutls_datum issuerp;
530  char certbuf[256]; /* big enough? */
531  size_t size;
532  unsigned int algo;
533  unsigned int bits;
534  time_t certclock;
535  const char *ptr;
536  struct SessionHandle *data = conn->data;
537  gnutls_session session = conn->ssl[sockindex].session;
538  int rc;
539  int incache;
540  void *ssl_sessionid;
541  CURLcode result = CURLE_OK;
542
543  /* This function will return the peer's raw certificate (chain) as sent by
544     the peer. These certificates are in raw format (DER encoded for
545     X.509). In case of a X.509 then a certificate list may be present. The
546     first certificate in the list is the peer's certificate, following the
547     issuer's certificate, then the issuer's issuer etc. */
548
549  chainp = gnutls_certificate_get_peers(session, &cert_list_size);
550  if(!chainp) {
551    if(data->set.ssl.verifypeer ||
552       data->set.ssl.verifyhost ||
553       data->set.ssl.issuercert) {
554#ifdef USE_TLS_SRP
555      if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
556         && data->set.ssl.username != NULL
557         && !data->set.ssl.verifypeer
558         && gnutls_cipher_get(session)) {
559        /* no peer cert, but auth is ok if we have SRP user and cipher and no
560           peer verify */
561      }
562      else {
563#endif
564        failf(data, "failed to get server cert");
565        return CURLE_PEER_FAILED_VERIFICATION;
566#ifdef USE_TLS_SRP
567      }
568#endif
569    }
570    infof(data, "\t common name: WARNING couldn't obtain\n");
571  }
572
573  if(data->set.ssl.verifypeer) {
574    /* This function will try to verify the peer's certificate and return its
575       status (trusted, invalid etc.). The value of status should be one or
576       more of the gnutls_certificate_status_t enumerated elements bitwise
577       or'd. To avoid denial of service attacks some default upper limits
578       regarding the certificate key size and chain size are set. To override
579       them use gnutls_certificate_set_verify_limits(). */
580
581    rc = gnutls_certificate_verify_peers2(session, &verify_status);
582    if(rc < 0) {
583      failf(data, "server cert verify failed: %d", rc);
584      return CURLE_SSL_CONNECT_ERROR;
585    }
586
587    /* verify_status is a bitmask of gnutls_certificate_status bits */
588    if(verify_status & GNUTLS_CERT_INVALID) {
589      if(data->set.ssl.verifypeer) {
590        failf(data, "server certificate verification failed. CAfile: %s "
591              "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
592              data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
593        return CURLE_SSL_CACERT;
594      }
595      else
596        infof(data, "\t server certificate verification FAILED\n");
597    }
598    else
599      infof(data, "\t server certificate verification OK\n");
600  }
601  else {
602    infof(data, "\t server certificate verification SKIPPED\n");
603    goto after_server_cert_verification;
604  }
605
606  /* initialize an X.509 certificate structure. */
607  gnutls_x509_crt_init(&x509_cert);
608
609  /* convert the given DER or PEM encoded Certificate to the native
610     gnutls_x509_crt_t format */
611  gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
612
613  if(data->set.ssl.issuercert) {
614    gnutls_x509_crt_init(&x509_issuer);
615    issuerp = load_file(data->set.ssl.issuercert);
616    gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
617    rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer);
618    unload_file(issuerp);
619    if(rc <= 0) {
620      failf(data, "server certificate issuer check failed (IssuerCert: %s)",
621            data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
622      return CURLE_SSL_ISSUER_ERROR;
623    }
624    infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
625          data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
626  }
627
628  size=sizeof(certbuf);
629  rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
630                                     0, /* the first and only one */
631                                     FALSE,
632                                     certbuf,
633                                     &size);
634  if(rc) {
635    infof(data, "error fetching CN from cert:%s\n",
636          gnutls_strerror(rc));
637  }
638
639  /* This function will check if the given certificate's subject matches the
640     given hostname. This is a basic implementation of the matching described
641     in RFC2818 (HTTPS), which takes into account wildcards, and the subject
642     alternative name PKIX extension. Returns non zero on success, and zero on
643     failure. */
644  rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
645
646  if(!rc) {
647    if(data->set.ssl.verifyhost > 1) {
648      failf(data, "SSL: certificate subject name (%s) does not match "
649            "target host name '%s'", certbuf, conn->host.dispname);
650      gnutls_x509_crt_deinit(x509_cert);
651      return CURLE_PEER_FAILED_VERIFICATION;
652    }
653    else
654      infof(data, "\t common name: %s (does not match '%s')\n",
655            certbuf, conn->host.dispname);
656  }
657  else
658    infof(data, "\t common name: %s (matched)\n", certbuf);
659
660  /* Check for time-based validity */
661  certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
662
663  if(certclock == (time_t)-1) {
664    failf(data, "server cert expiration date verify failed");
665    return CURLE_SSL_CONNECT_ERROR;
666  }
667
668  if(certclock < time(NULL)) {
669    if(data->set.ssl.verifypeer) {
670      failf(data, "server certificate expiration date has passed.");
671      return CURLE_PEER_FAILED_VERIFICATION;
672    }
673    else
674      infof(data, "\t server certificate expiration date FAILED\n");
675  }
676  else
677    infof(data, "\t server certificate expiration date OK\n");
678
679  certclock = gnutls_x509_crt_get_activation_time(x509_cert);
680
681  if(certclock == (time_t)-1) {
682    failf(data, "server cert activation date verify failed");
683    return CURLE_SSL_CONNECT_ERROR;
684  }
685
686  if(certclock > time(NULL)) {
687    if(data->set.ssl.verifypeer) {
688      failf(data, "server certificate not activated yet.");
689      return CURLE_PEER_FAILED_VERIFICATION;
690    }
691    else
692      infof(data, "\t server certificate activation date FAILED\n");
693  }
694  else
695    infof(data, "\t server certificate activation date OK\n");
696
697  /* Show:
698
699  - ciphers used
700  - subject
701  - start date
702  - expire date
703  - common name
704  - issuer
705
706  */
707
708  /* public key algorithm's parameters */
709  algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
710  infof(data, "\t certificate public key: %s\n",
711        gnutls_pk_algorithm_get_name(algo));
712
713  /* version of the X.509 certificate. */
714  infof(data, "\t certificate version: #%d\n",
715        gnutls_x509_crt_get_version(x509_cert));
716
717
718  size = sizeof(certbuf);
719  gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
720  infof(data, "\t subject: %s\n", certbuf);
721
722  certclock = gnutls_x509_crt_get_activation_time(x509_cert);
723  showtime(data, "start date", certclock);
724
725  certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
726  showtime(data, "expire date", certclock);
727
728  size = sizeof(certbuf);
729  gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
730  infof(data, "\t issuer: %s\n", certbuf);
731
732  gnutls_x509_crt_deinit(x509_cert);
733
734after_server_cert_verification:
735
736  /* compression algorithm (if any) */
737  ptr = gnutls_compression_get_name(gnutls_compression_get(session));
738  /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
739  infof(data, "\t compression: %s\n", ptr);
740
741  /* the name of the cipher used. ie 3DES. */
742  ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
743  infof(data, "\t cipher: %s\n", ptr);
744
745  /* the MAC algorithms name. ie SHA1 */
746  ptr = gnutls_mac_get_name(gnutls_mac_get(session));
747  infof(data, "\t MAC: %s\n", ptr);
748
749  conn->ssl[sockindex].state = ssl_connection_complete;
750  conn->recv[sockindex] = gtls_recv;
751  conn->send[sockindex] = gtls_send;
752
753  {
754    /* we always unconditionally get the session id here, as even if we
755       already got it from the cache and asked to use it in the connection, it
756       might've been rejected and then a new one is in use now and we need to
757       detect that. */
758    void *connect_sessionid;
759    size_t connect_idsize;
760
761    /* get the session ID data size */
762    gnutls_session_get_data(session, NULL, &connect_idsize);
763    connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
764
765    if(connect_sessionid) {
766      /* extract session ID to the allocated buffer */
767      gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
768
769      incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
770      if(incache) {
771        /* there was one before in the cache, so instead of risking that the
772           previous one was rejected, we just kill that and store the new */
773        Curl_ssl_delsessionid(conn, ssl_sessionid);
774      }
775
776      /* store this session id */
777      result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
778      if(result) {
779        free(connect_sessionid);
780        result = CURLE_OUT_OF_MEMORY;
781      }
782    }
783    else
784      result = CURLE_OUT_OF_MEMORY;
785  }
786
787  return result;
788}
789
790
791/*
792 * This function is called after the TCP connect has completed. Setup the TLS
793 * layer and do all necessary magic.
794 */
795/* We use connssl->connecting_state to keep track of the connection status;
796   there are three states: 'ssl_connect_1' (not started yet or complete),
797   'ssl_connect_2_reading' (waiting for data from server), and
798   'ssl_connect_2_writing' (waiting to be able to write).
799 */
800static CURLcode
801gtls_connect_common(struct connectdata *conn,
802                    int sockindex,
803                    bool nonblocking,
804                    bool *done)
805{
806  int rc;
807  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
808
809  /* Initiate the connection, if not already done */
810  if(ssl_connect_1==connssl->connecting_state) {
811    rc = gtls_connect_step1 (conn, sockindex);
812    if(rc)
813      return rc;
814  }
815
816  rc = handshake(conn, sockindex, TRUE, nonblocking);
817  if(rc)
818    /* handshake() sets its own error message with failf() */
819    return rc;
820
821  /* Finish connecting once the handshake is done */
822  if(ssl_connect_1==connssl->connecting_state) {
823    rc = gtls_connect_step3(conn, sockindex);
824    if(rc)
825      return rc;
826  }
827
828  *done = ssl_connect_1==connssl->connecting_state;
829
830  return CURLE_OK;
831}
832
833CURLcode
834Curl_gtls_connect_nonblocking(struct connectdata *conn,
835                              int sockindex,
836                              bool *done)
837{
838  return gtls_connect_common(conn, sockindex, TRUE, done);
839}
840
841CURLcode
842Curl_gtls_connect(struct connectdata *conn,
843                  int sockindex)
844
845{
846  CURLcode retcode;
847  bool done = FALSE;
848
849  retcode = gtls_connect_common(conn, sockindex, FALSE, &done);
850  if(retcode)
851    return retcode;
852
853  DEBUGASSERT(done);
854
855  return CURLE_OK;
856}
857
858static ssize_t gtls_send(struct connectdata *conn,
859                         int sockindex,
860                         const void *mem,
861                         size_t len,
862                         CURLcode *curlcode)
863{
864  ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
865
866  if(rc < 0 ) {
867    *curlcode = (rc == GNUTLS_E_AGAIN)
868      ? CURLE_AGAIN
869      : CURLE_SEND_ERROR;
870
871    rc = -1;
872  }
873
874  return rc;
875}
876
877void Curl_gtls_close_all(struct SessionHandle *data)
878{
879  /* FIX: make the OpenSSL code more generic and use parts of it here */
880  (void)data;
881}
882
883static void close_one(struct connectdata *conn,
884                      int idx)
885{
886  if(conn->ssl[idx].session) {
887    gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
888    gnutls_deinit(conn->ssl[idx].session);
889    conn->ssl[idx].session = NULL;
890  }
891  if(conn->ssl[idx].cred) {
892    gnutls_certificate_free_credentials(conn->ssl[idx].cred);
893    conn->ssl[idx].cred = NULL;
894  }
895#ifdef USE_TLS_SRP
896  if(conn->ssl[idx].srp_client_cred) {
897    gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
898    conn->ssl[idx].srp_client_cred = NULL;
899  }
900#endif
901}
902
903void Curl_gtls_close(struct connectdata *conn, int sockindex)
904{
905  close_one(conn, sockindex);
906}
907
908/*
909 * This function is called to shut down the SSL layer but keep the
910 * socket open (CCC - Clear Command Channel)
911 */
912int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
913{
914  ssize_t result;
915  int retval = 0;
916  struct SessionHandle *data = conn->data;
917  int done = 0;
918  char buf[120];
919
920  /* This has only been tested on the proftpd server, and the mod_tls code
921     sends a close notify alert without waiting for a close notify alert in
922     response. Thus we wait for a close notify alert from the server, but
923     we do not send one. Let's hope other servers do the same... */
924
925  if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
926      gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
927
928  if(conn->ssl[sockindex].session) {
929    while(!done) {
930      int what = Curl_socket_ready(conn->sock[sockindex],
931                                   CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
932      if(what > 0) {
933        /* Something to read, let's do it and hope that it is the close
934           notify alert from the server */
935        result = gnutls_record_recv(conn->ssl[sockindex].session,
936                                    buf, sizeof(buf));
937        switch(result) {
938        case 0:
939          /* This is the expected response. There was no data but only
940             the close notify alert */
941          done = 1;
942          break;
943        case GNUTLS_E_AGAIN:
944        case GNUTLS_E_INTERRUPTED:
945          infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
946          break;
947        default:
948          retval = -1;
949          done = 1;
950          break;
951        }
952      }
953      else if(0 == what) {
954        /* timeout */
955        failf(data, "SSL shutdown timeout");
956        done = 1;
957        break;
958      }
959      else {
960        /* anything that gets here is fatally bad */
961        failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
962        retval = -1;
963        done = 1;
964      }
965    }
966    gnutls_deinit(conn->ssl[sockindex].session);
967  }
968  gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
969
970#ifdef USE_TLS_SRP
971  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
972     && data->set.ssl.username != NULL)
973    gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
974#endif
975
976  conn->ssl[sockindex].cred = NULL;
977  conn->ssl[sockindex].session = NULL;
978
979  return retval;
980}
981
982static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
983                         int num,                  /* socketindex */
984                         char *buf,                /* store read data here */
985                         size_t buffersize,        /* max amount to read */
986                         CURLcode *curlcode)
987{
988  ssize_t ret;
989
990  ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
991  if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
992    *curlcode = CURLE_AGAIN;
993    return -1;
994  }
995
996  if(ret == GNUTLS_E_REHANDSHAKE) {
997    /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
998       proper way" takes a whole lot of work. */
999    CURLcode rc = handshake(conn, num, FALSE, FALSE);
1000    if(rc)
1001      /* handshake() writes error message on its own */
1002      *curlcode = rc;
1003    else
1004      *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1005    return -1;
1006  }
1007
1008  if(ret < 0) {
1009    failf(conn->data, "GnuTLS recv error (%d): %s",
1010          (int)ret, gnutls_strerror((int)ret));
1011    *curlcode = CURLE_RECV_ERROR;
1012    return -1;
1013  }
1014
1015  return ret;
1016}
1017
1018void Curl_gtls_session_free(void *ptr)
1019{
1020  free(ptr);
1021}
1022
1023size_t Curl_gtls_version(char *buffer, size_t size)
1024{
1025  return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1026}
1027
1028int Curl_gtls_seed(struct SessionHandle *data)
1029{
1030  /* we have the "SSL is seeded" boolean static to prevent multiple
1031     time-consuming seedings in vain */
1032  static bool ssl_seeded = FALSE;
1033
1034  /* Quickly add a bit of entropy */
1035  gcry_fast_random_poll();
1036
1037  if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1038     data->set.str[STRING_SSL_EGDSOCKET]) {
1039
1040    /* TODO: to a good job seeding the RNG
1041       This may involve the gcry_control function and these options:
1042       GCRYCTL_SET_RANDOM_SEED_FILE
1043       GCRYCTL_SET_RNDEGD_SOCKET
1044    */
1045    ssl_seeded = TRUE;
1046  }
1047  return 0;
1048}
1049
1050#endif /* USE_GNUTLS */
1051