/* SSL support via GnuTLS library.
- Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
#include <assert.h>
#include <errno.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
+#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
+#include <sys/ioctl.h>
#include "utils.h"
#include "connect.h"
gnutls_global_init ();
gnutls_certificate_allocate_credentials (&credentials);
+ gnutls_certificate_set_verify_flags(credentials,
+ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
ca_directory = opt.ca_directory ? opt.ca_directory : "/etc/ssl/certs";
return true;
}
-struct wgnutls_transport_context {
+struct wgnutls_transport_context
+{
gnutls_session session; /* GnuTLS session handle */
int last_error; /* last error returned by read/write/... */
do
ret = gnutls_record_recv (ctx->session, buf, bufsize);
- while (ret == GNUTLS_E_INTERRUPTED);
+ while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
if (ret < 0)
ctx->last_error = ret;
+
return ret;
}
struct wgnutls_transport_context *ctx = arg;
do
ret = gnutls_record_send (ctx->session, buf, bufsize);
- while (ret == GNUTLS_E_INTERRUPTED);
+ while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
if (ret < 0)
ctx->last_error = ret;
return ret;
static int
wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
{
- int ret = 0;
+ int read = 0;
struct wgnutls_transport_context *ctx = arg;
int offset = MIN (bufsize, ctx->peeklen);
if (bufsize > sizeof ctx->peekbuf)
if (bufsize > offset)
{
- do
+ if (gnutls_record_check_pending (ctx->session) <= 0
+ && select_fd (fd, 0.0, WAIT_FOR_READ) <= 0)
+ read = 0;
+ else
+ read = gnutls_record_recv (ctx->session, buf + offset,
+ bufsize - offset);
+
+ if (read < 0)
{
- if (gnutls_record_check_pending (ctx->session)
- || select_fd (fd, 0, WAIT_FOR_READ))
- ret = gnutls_record_recv (ctx->session, buf + offset,
- bufsize - offset);
+ if (offset)
+ read = 0;
+ else
+ return read;
}
- while (ret == GNUTLS_E_INTERRUPTED);
- if (ret > 0)
+ if (read > 0)
{
memcpy (ctx->peekbuf + offset, buf + offset,
- ret);
- ctx->peeklen += ret;
+ read);
+ ctx->peeklen += read;
}
}
- return offset + ret;
+ return offset + read;
}
static const char *
/* gnutls_transport is the singleton that describes the SSL transport
methods provided by this file. */
-static struct transport_implementation wgnutls_transport = {
+static struct transport_implementation wgnutls_transport =
+{
wgnutls_read, wgnutls_write, wgnutls_poll,
wgnutls_peek, wgnutls_errstr, wgnutls_close
};
struct wgnutls_transport_context *ctx;
gnutls_session session;
int err;
- int allowed_protocols[4] = {0, 0, 0, 0};
gnutls_init (&session, GNUTLS_CLIENT);
gnutls_set_default_priority (session);
gnutls_certificate_type_set_priority (session, cert_type_priority);
gnutls_transport_set_ptr (session, (gnutls_transport_ptr) FD_TO_SOCKET (fd));
err = 0;
+#if HAVE_GNUTLS_PRIORITY_SET_DIRECT
+ switch (opt.secure_protocol)
+ {
+ case secure_protocol_auto:
+ break;
+ case secure_protocol_sslv2:
+ case secure_protocol_sslv3:
+ err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL", NULL);
+ break;
+ case secure_protocol_tlsv1:
+ err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0", NULL);
+ break;
+ default:
+ abort ();
+ }
+#else
+ int allowed_protocols[4] = {0, 0, 0, 0};
switch (opt.secure_protocol)
{
case secure_protocol_auto:
allowed_protocols[0] = GNUTLS_SSL3;
err = gnutls_protocol_set_priority (session, allowed_protocols);
break;
+
case secure_protocol_tlsv1:
allowed_protocols[0] = GNUTLS_TLS1_0;
allowed_protocols[1] = GNUTLS_TLS1_1;
allowed_protocols[2] = GNUTLS_TLS1_2;
err = gnutls_protocol_set_priority (session, allowed_protocols);
break;
+
default:
abort ();
}
+#endif
+
if (err < 0)
{
logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));