/* SSL support via GnuTLS library.
- Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+ Foundation, Inc.
This file is part of GNU Wget.
You should have received a copy of the GNU General Public License
along with Wget. If not, see <http://www.gnu.org/licenses/>.
-In addition, as a special exception, the Free Software Foundation
-gives permission to link the code of its release of Wget with the
-OpenSSL project's "OpenSSL" library (or with modified versions of it
-that use the same license as the "OpenSSL" library), and distribute
-the linked executables. You must obey the GNU General Public License
-in all respects for all of the code used other than "OpenSSL". If you
-modify this file, you may extend this exception to your version of the
-file, but you are not obligated to do so. If you do not wish to do
-so, delete this exception statement from your version. */
+Additional permission under GNU GPL version 3 section 7
-#include <config.h>
+If you modify this program, or any covered work, by linking or
+combining it with the OpenSSL project's OpenSSL library (or a
+modified version of that library), containing parts covered by the
+terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
+grants you additional permission to convey the resulting work.
+Corresponding Source for a non-source form of such a combination
+shall include the source code for the parts of OpenSSL used as well
+as that of the covered work. */
+
+#include "wget.h"
#include <assert.h>
#include <errno.h>
#endif
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
-#include "wget.h"
#include "utils.h"
#include "connect.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)
{
if (err < 0)
{
logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
- severity, escnonprint (host));
+ severity, quotearg_style (escape_quoting_style, host));
success = false;
goto out;
}
if (status & GNUTLS_CERT_INVALID)
{
- logprintf (LOG_NOTQUIET, _("%s: The certificate of `%s' is not trusted.\n"),
- severity, escnonprint (host));
+ logprintf (LOG_NOTQUIET, _("%s: The certificate of %s is not trusted.\n"),
+ severity, quote (host));
success = false;
}
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
{
- logprintf (LOG_NOTQUIET, _("%s: The certificate of `%s' hasn't got a known issuer.\n"),
- severity, escnonprint (host));
+ logprintf (LOG_NOTQUIET, _("%s: The certificate of %s hasn't got a known issuer.\n"),
+ severity, quote (host));
success = false;
}
if (status & GNUTLS_CERT_REVOKED)
{
- logprintf (LOG_NOTQUIET, _("%s: The certificate of `%s' has been revoked.\n"),
- severity, escnonprint (host));
+ logprintf (LOG_NOTQUIET, _("%s: The certificate of %s has been revoked.\n"),
+ severity, quote (host));
success = false;
}
if (!gnutls_x509_crt_check_hostname (cert, host))
{
logprintf (LOG_NOTQUIET,
- _("The certificate's owner does not match hostname '%s'\n"),
- host);
+ _("The certificate's owner does not match hostname %s\n"),
+ quote (host));
success = false;
}
gnutls_x509_crt_deinit (cert);