mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Add GnuTLS support.
This commit is contained in:
parent
2ef83f89bd
commit
cca63ff3f1
@ -1,3 +1,7 @@
|
|||||||
|
2005-07-05 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* configure.in: Add check for GnuTLS if --with-ssl=gnutls is used.
|
||||||
|
|
||||||
2005-07-03 Hrvoje Niksic <hniksic@xemacs.org>
|
2005-07-03 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* po/POTFILES.in: Include src/ptimer.c.
|
* po/POTFILES.in: Include src/ptimer.c.
|
||||||
|
22
configure.in
22
configure.in
@ -239,9 +239,20 @@ dnl
|
|||||||
dnl Checks for libraries.
|
dnl Checks for libraries.
|
||||||
dnl
|
dnl
|
||||||
|
|
||||||
dnl Check for OpenSSL
|
if test x"$with_ssl" = xgnutls
|
||||||
if test x"$with_ssl" != x"no"
|
|
||||||
then
|
then
|
||||||
|
dnl Now actually check for -lssl
|
||||||
|
AC_LIB_HAVE_LINKFLAGS([gnutls], [], [
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
], [gnutls_global_init()])
|
||||||
|
if test x"$LIBGNUTLS" != x
|
||||||
|
then
|
||||||
|
AC_MSG_NOTICE([compiling in support for SSL via GnuTLS])
|
||||||
|
AC_DEFINE([HAVE_GNUTLS], 1,
|
||||||
|
[Define if support for the GnuTLS library is being compiled in.])
|
||||||
|
SSL_OBJ='gnutls.o'
|
||||||
|
fi
|
||||||
|
else
|
||||||
dnl As of this writing (OpenSSL 0.9.6), the libcrypto shared library
|
dnl As of this writing (OpenSSL 0.9.6), the libcrypto shared library
|
||||||
dnl doesn't record its dependency on libdl, so we need to make sure
|
dnl doesn't record its dependency on libdl, so we need to make sure
|
||||||
dnl -ldl ends up in LIBS on systems that have it. Most OSes use
|
dnl -ldl ends up in LIBS on systems that have it. Most OSes use
|
||||||
@ -262,12 +273,13 @@ then
|
|||||||
], [SSL_library_init ()])
|
], [SSL_library_init ()])
|
||||||
if test x"$LIBSSL" != x
|
if test x"$LIBSSL" != x
|
||||||
then
|
then
|
||||||
AC_MSG_NOTICE([compiling in support for SSL])
|
AC_MSG_NOTICE([compiling in support for SSL via OpenSSL])
|
||||||
AC_DEFINE([HAVE_SSL], 1,
|
AC_DEFINE([HAVE_OPENSSL], 1,
|
||||||
[Define if SSL support is being compiled in.])
|
[Define if support for the OpenSSL library is being compiled in.])
|
||||||
SSL_OBJ='openssl.o'
|
SSL_OBJ='openssl.o'
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(SSL_OBJ)
|
AC_SUBST(SSL_OBJ)
|
||||||
|
|
||||||
dnl Enable NTLM if requested and if SSL is available.
|
dnl Enable NTLM if requested and if SSL is available.
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
2005-07-05 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* wget.h (or): Define HAVE_SSL when either HAVE_OPENSSL or
|
||||||
|
HAVE_GNUTLS are defined.
|
||||||
|
|
||||||
|
* gnutls.c: New file.
|
||||||
|
|
||||||
2005-07-05 Hrvoje Niksic <hniksic@xemacs.org>
|
2005-07-05 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* http.c (gethttp): Don't print the request write error message
|
* http.c (gethttp): Don't print the request write error message
|
||||||
|
@ -51,7 +51,7 @@ CPPFLAGS = @CPPFLAGS@
|
|||||||
DEFS = @DEFS@ -DSYSTEM_WGETRC=\"$(sysconfdir)/wgetrc\" -DLOCALEDIR=\"$(localedir)\"
|
DEFS = @DEFS@ -DSYSTEM_WGETRC=\"$(sysconfdir)/wgetrc\" -DLOCALEDIR=\"$(localedir)\"
|
||||||
CFLAGS = @CFLAGS@
|
CFLAGS = @CFLAGS@
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = @LDFLAGS@
|
||||||
LIBS = @LIBS@ @LIBSSL@
|
LIBS = @LIBS@ @LIBSSL@ @LIBGNUTLS@
|
||||||
exeext = @exeext@
|
exeext = @exeext@
|
||||||
|
|
||||||
INCLUDES = -I. -I$(srcdir)
|
INCLUDES = -I. -I$(srcdir)
|
||||||
|
254
src/gnutls.c
Normal file
254
src/gnutls.c
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
/* SSL support via GnuTLS library.
|
||||||
|
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GNU Wget.
|
||||||
|
|
||||||
|
GNU Wget is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
GNU Wget is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Wget; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
#include "wget.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "connect.h"
|
||||||
|
#include "url.h"
|
||||||
|
#include "ssl.h"
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
preprocessor macro. */
|
||||||
|
|
||||||
|
static gnutls_certificate_credentials credentials;
|
||||||
|
|
||||||
|
bool
|
||||||
|
ssl_init ()
|
||||||
|
{
|
||||||
|
gnutls_global_init ();
|
||||||
|
gnutls_certificate_allocate_credentials (&credentials);
|
||||||
|
if (opt.ca_cert)
|
||||||
|
gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
|
||||||
|
GNUTLS_X509_FMT_PEM);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wgnutls_transport_context {
|
||||||
|
gnutls_session session; /* GnuTLS session handle */
|
||||||
|
int last_error; /* last error returned by read/write/... */
|
||||||
|
|
||||||
|
/* Since GnuTLS doesn't support the equivalent to recv(...,
|
||||||
|
MSG_PEEK) or SSL_peek(), we have to do it ourselves. Peeked data
|
||||||
|
is stored to PEEKBUF, and wgnutls_read checks that buffer before
|
||||||
|
actually reading. */
|
||||||
|
char peekbuf[512];
|
||||||
|
int peekstart, peeklen;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
# define MIN(i, j) ((i) <= (j) ? (i) : (j))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
wgnutls_read (int fd, char *buf, int bufsize, void *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
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);
|
||||||
|
ctx->peeklen -= copysize;
|
||||||
|
if (ctx->peeklen != 0)
|
||||||
|
ctx->peekstart += copysize;
|
||||||
|
else
|
||||||
|
ctx->peekstart = 0;
|
||||||
|
return copysize;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
ret = gnutls_record_recv (ctx->session, buf, bufsize);
|
||||||
|
while (ret == GNUTLS_E_INTERRUPTED);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
ctx->last_error = ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
wgnutls_write (int fd, char *buf, int bufsize, void *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
|
do
|
||||||
|
ret = gnutls_record_send (ctx->session, buf, bufsize);
|
||||||
|
while (ret == GNUTLS_E_INTERRUPTED);
|
||||||
|
if (ret < 0)
|
||||||
|
ctx->last_error = ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
wgnutls_poll (int fd, double timeout, int wait_for, void *arg)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
do
|
||||||
|
ret = gnutls_record_recv (ctx->session, buf, bufsize);
|
||||||
|
while (ret == GNUTLS_E_INTERRUPTED);
|
||||||
|
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
memcpy (ctx->peekbuf, buf, ret);
|
||||||
|
ctx->peeklen = ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
wgnutls_errstr (int fd, void *arg)
|
||||||
|
{
|
||||||
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
|
return gnutls_strerror (ctx->last_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wgnutls_close (int fd, void *arg)
|
||||||
|
{
|
||||||
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
|
/*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
|
||||||
|
methods provided by this file. */
|
||||||
|
|
||||||
|
static struct transport_implementation wgnutls_transport = {
|
||||||
|
wgnutls_read, wgnutls_write, wgnutls_poll,
|
||||||
|
wgnutls_peek, wgnutls_errstr, wgnutls_close
|
||||||
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
ssl_connect (int fd)
|
||||||
|
{
|
||||||
|
static const int cert_type_priority[] = {
|
||||||
|
GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0
|
||||||
|
};
|
||||||
|
struct wgnutls_transport_context *ctx;
|
||||||
|
gnutls_session session;
|
||||||
|
int err;
|
||||||
|
gnutls_init (&session, GNUTLS_CLIENT);
|
||||||
|
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);
|
||||||
|
err = gnutls_handshake (session);
|
||||||
|
if (err < 0)
|
||||||
|
{
|
||||||
|
logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
|
||||||
|
gnutls_deinit (session);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ctx = xnew0 (struct wgnutls_transport_context);
|
||||||
|
ctx->session = session;
|
||||||
|
fd_register_transport (fd, &wgnutls_transport, ctx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ssl_check_certificate (int fd, const char *host)
|
||||||
|
{
|
||||||
|
struct wgnutls_transport_context *ctx = fd_transport_context (fd);
|
||||||
|
|
||||||
|
unsigned int status;
|
||||||
|
const gnutls_datum *cert_list;
|
||||||
|
int cert_list_size, ret;
|
||||||
|
gnutls_x509_crt cert;
|
||||||
|
|
||||||
|
/* If the user has specified --no-check-cert, we still want to warn
|
||||||
|
him about problems with the server's certificate. */
|
||||||
|
const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
ret = gnutls_certificate_verify_peers2 (ctx->session, &status);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
|
||||||
|
severity, escnonprint (host));
|
||||||
|
success = false;
|
||||||
|
goto no_cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & GNUTLS_CERT_INVALID)
|
||||||
|
{
|
||||||
|
logprintf (LOG_NOTQUIET, _("%s: The certificate of `%s' is not trusted.\n"),
|
||||||
|
severity, escnonprint (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));
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (status & GNUTLS_CERT_REVOKED)
|
||||||
|
{
|
||||||
|
logprintf (LOG_NOTQUIET, _("%s: The certificate of `%s' has been revoked.\n"),
|
||||||
|
severity, escnonprint (host));
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
no_cert:
|
||||||
|
return opt.check_cert ? success : true;
|
||||||
|
}
|
@ -40,6 +40,10 @@ so, delete this exception statement from your version. */
|
|||||||
# define NDEBUG
|
# define NDEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined HAVE_OPENSSL || defined HAVE_GNUTLS
|
||||||
|
# define HAVE_SSL
|
||||||
|
#endif
|
||||||
|
|
||||||
/* `gettext (FOO)' is long to write, so we use `_(FOO)'. If NLS is
|
/* `gettext (FOO)' is long to write, so we use `_(FOO)'. If NLS is
|
||||||
unavailable, _(STRING) simply returns STRING. */
|
unavailable, _(STRING) simply returns STRING. */
|
||||||
#ifdef HAVE_NLS
|
#ifdef HAVE_NLS
|
||||||
|
Loading…
Reference in New Issue
Block a user