/* SSL support via GnuTLS library.
- Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
- Inc.
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+ Foundation, Inc.
This file is part of GNU Wget.
#endif
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "url.h"
#include "ssl.h"
+#ifdef WIN32
+# include "w32sock.h"
+#endif
+
/* Note: some of the functions private to this file have names that
begin with "wgnutls_" (e.g. wgnutls_read) so that they wouldn't be
confused with actual gnutls functions -- such as the gnutls_read
is stored to PEEKBUF, and wgnutls_read checks that buffer before
actually reading. */
char peekbuf[512];
- int peekstart, peeklen;
+ int peeklen;
};
#ifndef MIN
static int
wgnutls_read (int fd, char *buf, int bufsize, void *arg)
{
- int ret;
+ int ret = 0;
struct wgnutls_transport_context *ctx = arg;
if (ctx->peeklen)
{
/* If we have any peek data, simply return that. */
int copysize = MIN (bufsize, ctx->peeklen);
- memcpy (buf, ctx->peekbuf + ctx->peekstart, copysize);
+ memcpy (buf, ctx->peekbuf, copysize);
ctx->peeklen -= copysize;
if (ctx->peeklen != 0)
- ctx->peekstart += copysize;
- else
- ctx->peekstart = 0;
+ memmove (ctx->peekbuf, ctx->peekbuf + copysize, ctx->peeklen);
+
return copysize;
}
static int
wgnutls_poll (int fd, double timeout, int wait_for, void *arg)
{
- return 1;
+ struct wgnutls_transport_context *ctx = arg;
+ return ctx->peeklen || gnutls_record_check_pending (ctx->session)
+ || select_fd (fd, timeout, wait_for);
}
static int
wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
{
- int ret;
+ int ret = 0;
struct wgnutls_transport_context *ctx = arg;
+ int offset = ctx->peeklen;
- /* We don't support peeks following peeks: the reader must drain all
- peeked data before the next peek. */
- assert (ctx->peeklen == 0);
if (bufsize > sizeof ctx->peekbuf)
bufsize = sizeof ctx->peekbuf;
+ if (offset)
+ memcpy (buf, ctx->peekbuf, offset);
+
do
- ret = gnutls_record_recv (ctx->session, buf, bufsize);
+ {
+ if (gnutls_record_check_pending (ctx->session)
+ || select_fd (fd, 0, WAIT_FOR_READ))
+ ret = gnutls_record_recv (ctx->session, buf + offset, bufsize - offset);
+ }
while (ret == GNUTLS_E_INTERRUPTED);
- if (ret >= 0)
+ if (ret > 0)
{
- memcpy (ctx->peekbuf, buf, ret);
- ctx->peeklen = ret;
+ memcpy (ctx->peekbuf + offset, buf + offset, ret);
+ ctx->peeklen += ret;
}
- return ret;
+ return ctx->peeklen;
}
static const char *
/*gnutls_bye (ctx->session, GNUTLS_SHUT_RDWR);*/
gnutls_deinit (ctx->session);
xfree (ctx);
-#ifndef WINDOWS
close (fd);
-#else
- closesocket (fd);
-#endif
}
/* gnutls_transport is the singleton that describes the SSL transport
};
bool
-ssl_connect (int fd)
+ssl_connect_wget (int fd)
{
static const int cert_type_priority[] = {
GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0
gnutls_set_default_priority (session);
gnutls_certificate_type_set_priority (session, cert_type_priority);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
- gnutls_transport_set_ptr (session, (gnutls_transport_ptr) fd);
+#ifndef FD_TO_SOCKET
+# define FD_TO_SOCKET(X) (X)
+#endif
+ gnutls_transport_set_ptr (session, (gnutls_transport_ptr) FD_TO_SOCKET (fd));
err = gnutls_handshake (session);
if (err < 0)
{