# include "w32sock.h"
#endif
+#include "host.h"
+
static int
key_type_to_gnutls_type (enum keyfile_type type)
{
confused with actual gnutls functions -- such as the gnutls_read
preprocessor macro. */
-static gnutls_certificate_credentials credentials;
+static gnutls_certificate_credentials_t credentials;
bool
-ssl_init ()
+ssl_init (void)
{
/* Becomes true if GnuTLS is initialized. */
static bool ssl_initialized = false;
dir = opendir (ca_directory);
if (dir == NULL)
{
- if (opt.ca_directory)
+ if (opt.ca_directory && *opt.ca_directory)
logprintf (LOG_NOTQUIET, _("ERROR: Cannot open directory %s.\n"),
opt.ca_directory);
}
struct wgnutls_transport_context
{
- gnutls_session session; /* GnuTLS session handle */
+ gnutls_session_t session; /* GnuTLS session handle */
int last_error; /* last error returned by read/write/... */
/* Since GnuTLS doesn't support the equivalent to recv(...,
int flags = 0;
#endif
int ret = 0;
- struct ptimer *timer;
+ struct ptimer *timer = NULL;
struct wgnutls_transport_context *ctx = arg;
int timed_out = 0;
flags = fcntl (fd, F_GETFL, 0);
if (flags < 0)
return flags;
+ if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
+ return -1;
+#else
+ /* XXX: Assume it was blocking before. */
+ const int one = 1;
+ if (ioctl (fd, FIONBIO, &one) < 0)
+ return -1;
#endif
+
timer = ptimer_new ();
- if (timer == 0)
+ if (timer == NULL)
return -1;
}
do
{
- double next_timeout;
- if (timeout > 0.0)
- {
- next_timeout = timeout - ptimer_measure (timer);
- if (next_timeout < 0.0)
- break;
- }
+ double next_timeout = 0;
+ if (timeout)
+ {
+ next_timeout = timeout - ptimer_measure (timer);
+ if (next_timeout < 0)
+ break;
+ }
ret = GNUTLS_E_AGAIN;
if (timeout == 0 || gnutls_record_check_pending (ctx->session)
|| select_fd (fd, next_timeout, WAIT_FOR_READ))
{
- if (timeout)
- {
-#ifdef F_GETFL
- if (fcntl (fd, F_SETFL, flags | O_NONBLOCK))
- break;
-#else
- /* XXX: Assume it was blocking before. */
- const int one = 1;
- if (ioctl (fd, FIONBIO, &one) < 0)
- break;
-#endif
- }
-
ret = gnutls_record_recv (ctx->session, buf, bufsize);
-
- if (timeout)
- {
-#ifdef F_GETFL
- if (fcntl (fd, F_SETFL, flags) < 0)
- break;
-#else
- const int zero = 0;
- if (ioctl (fd, FIONBIO, &zero) < 0)
- break;
-#endif
- }
+ timed_out = timeout && ptimer_measure (timer) >= timeout;
}
-
- timed_out = timeout && ptimer_measure (timer) >= timeout;
}
while (ret == GNUTLS_E_INTERRUPTED || (ret == GNUTLS_E_AGAIN && !timed_out));
if (timeout)
- ptimer_destroy (timer);
+ {
+ ptimer_destroy (timer);
- if (timeout && timed_out && ret == GNUTLS_E_AGAIN)
- errno = ETIMEDOUT;
+#ifdef F_GETFL
+ if (fcntl (fd, F_SETFL, flags) < 0)
+ return -1;
+#else
+ const int zero = 0;
+ if (ioctl (fd, FIONBIO, &zero) < 0)
+ return -1;
+#endif
+
+ if (timed_out && ret == GNUTLS_E_AGAIN)
+ errno = ETIMEDOUT;
+ }
return ret;
}
wgnutls_poll (int fd, double timeout, int wait_for, void *arg)
{
struct wgnutls_transport_context *ctx = arg;
- return ctx->peeklen || gnutls_record_check_pending (ctx->session)
- || select_fd (fd, timeout, wait_for);
+
+ if (timeout)
+ return ctx->peeklen || gnutls_record_check_pending (ctx->session)
+ || select_fd (fd, timeout, wait_for);
+ else
+ return ctx->peeklen || gnutls_record_check_pending (ctx->session);
}
static int
int read = 0;
struct wgnutls_transport_context *ctx = arg;
int offset = MIN (bufsize, ctx->peeklen);
- if (bufsize > sizeof ctx->peekbuf)
- bufsize = sizeof ctx->peekbuf;
if (ctx->peeklen)
- memcpy (buf, ctx->peekbuf, offset);
+ {
+ memcpy (buf, ctx->peekbuf, offset);
+ return offset;
+ }
+
+ if (bufsize > sizeof ctx->peekbuf)
+ bufsize = sizeof ctx->peekbuf;
if (bufsize > offset)
{
- if (gnutls_record_check_pending (ctx->session) <= 0
+ if (opt.read_timeout && gnutls_record_check_pending (ctx->session) == 0
&& select_fd (fd, 0.0, WAIT_FOR_READ) <= 0)
read = 0;
else
};
bool
-ssl_connect_wget (int fd)
+ssl_connect_wget (int fd, const char *hostname)
{
struct wgnutls_transport_context *ctx;
- gnutls_session session;
- int err;
+ gnutls_session_t session;
+ int err,alert;
gnutls_init (&session, GNUTLS_CLIENT);
+ const char *str;
+
+ /* We set the server name but only if it's not an IP address. */
+ if (! is_valid_ip_address (hostname))
+ {
+ gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
+ strlen (hostname));
+ }
+
gnutls_set_default_priority (session);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
#ifndef FD_TO_SOCKET
# define FD_TO_SOCKET(X) (X)
#endif
- gnutls_transport_set_ptr (session, (gnutls_transport_ptr) FD_TO_SOCKET (fd));
+ gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) FD_TO_SOCKET (fd));
err = 0;
#if HAVE_GNUTLS_PRIORITY_SET_DIRECT
break;
case secure_protocol_sslv2:
case secure_protocol_sslv3:
- err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL", NULL);
+ err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0", NULL);
break;
case secure_protocol_tlsv1:
err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0", NULL);
return false;
}
- err = gnutls_handshake (session);
+ /* We don't stop the handshake process for non-fatal errors */
+ do
+ {
+ err = gnutls_handshake (session);
+ if (err < 0)
+ {
+ logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
+ if (err == GNUTLS_E_WARNING_ALERT_RECEIVED ||
+ err == GNUTLS_E_FATAL_ALERT_RECEIVED)
+ {
+ alert = gnutls_alert_get (session);
+ str = gnutls_alert_get_name (alert);
+ if (str == NULL)
+ str = "(unknown)";
+ logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n", alert, str);
+ }
+ }
+ }
+ while (err == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_error_is_fatal (err) == 0);
+
if (err < 0)
{
- logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
gnutls_deinit (session);
return false;
}
if (gnutls_certificate_type_get (ctx->session) == GNUTLS_CRT_X509)
{
time_t now = time (NULL);
- gnutls_x509_crt cert;
- const gnutls_datum *cert_list;
+ gnutls_x509_crt_t cert;
+ const gnutls_datum_t *cert_list;
unsigned int cert_list_size;
if ((err = gnutls_x509_crt_init (&cert)) < 0)
{
logprintf (LOG_NOTQUIET, _("No certificate found\n"));
success = false;
- goto out;
+ goto crt_deinit;
}
err = gnutls_x509_crt_import (cert, cert_list, GNUTLS_X509_FMT_DER);
if (err < 0)
logprintf (LOG_NOTQUIET, _("Error parsing certificate: %s\n"),
gnutls_strerror (err));
success = false;
- goto out;
+ goto crt_deinit;
}
if (now < gnutls_x509_crt_get_activation_time (cert))
{
quote (host));
success = false;
}
+ crt_deinit:
gnutls_x509_crt_deinit (cert);
}