/* SSL support via OpenSSL library.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+ 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
Originally contributed by Christian Fraenkel.
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 <openssl/ssl.h>
#include "url.h"
#include "ssl.h"
+#ifdef WINDOWS
+# include <w32sock.h>
+#endif
+
/* Application-wide SSL context. This is common to all SSL
connections. */
static SSL_CTX *ssl_ctx;
bool
ssl_init ()
{
- SSL_METHOD *meth;
+ SSL_METHOD const *meth;
if (ssl_ctx)
/* The SSL has already been initialized. */
case secure_protocol_auto:
meth = SSLv23_client_method ();
break;
+#ifndef OPENSSL_NO_SSL2
case secure_protocol_sslv2:
meth = SSLv2_client_method ();
break;
+#endif
case secure_protocol_sslv3:
meth = SSLv3_client_method ();
break;
abort ();
}
- ssl_ctx = SSL_CTX_new (meth);
+ /* The type cast below accommodates older OpenSSL versions (0.9.8)
+ where SSL_CTX_new() is declared without a "const" argument. */
+ ssl_ctx = SSL_CTX_new ((SSL_METHOD *)meth);
if (!ssl_ctx)
goto error;
while (ret == -1
&& SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
&& errno == EINTR);
+
return ret;
}
{
struct openssl_transport_context *ctx = arg;
SSL *conn = ctx->conn;
- if (timeout == 0)
- return 1;
if (SSL_pending (conn))
return 1;
+ if (timeout == 0)
+ return 1;
return select_fd (fd, timeout, wait_for);
}
int ret;
struct openssl_transport_context *ctx = arg;
SSL *conn = ctx->conn;
+ if (! openssl_poll (fd, 0.0, WAIT_FOR_READ, arg))
+ return 0;
do
ret = SSL_peek (conn, buf, bufsize);
while (ret == -1
xfree_null (ctx->last_error);
xfree (ctx);
-#if defined(WINDOWS) || defined(USE_WATT32)
- closesocket (fd);
-#else
close (fd);
-#endif
DEBUGP (("Closed %d/SSL 0x%0*lx\n", fd, PTR_FORMAT (conn)));
}
Returns true on success, false on failure. */
bool
-ssl_connect_wget (int fd)
+ssl_connect_wget (int fd, const char *hostname)
{
SSL *conn;
struct openssl_transport_context *ctx;
conn = SSL_new (ssl_ctx);
if (!conn)
goto error;
- if (!SSL_set_fd (conn, fd))
+#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
+ /* If the SSL library was build with support for ServerNameIndication
+ then use it whenever we have a hostname. If not, don't, ever. */
+ if (! is_valid_ip_address (hostname))
+ {
+ if (! SSL_set_tlsext_host_name (conn, hostname))
+ {
+ DEBUGP (("Failed to set TLS server-name indication."));
+ goto error;
+ }
+ }
+#endif
+
+#ifndef FD_TO_SOCKET
+# define FD_TO_SOCKET(X) (X)
+#endif
+ if (!SSL_set_fd (conn, FD_TO_SOCKET (fd)))
goto error;
SSL_set_connect_state (conn);
if (SSL_connect (conn) <= 0 || conn->state != SSL_ST_OK)
/* Do we want to check for dNSNAmes or ipAddresses (see RFC 2818)?
* Signal it by host_in_octet_string. */
- ASN1_OCTET_STRING *host_in_octet_string = NULL;
- host_in_octet_string = a2i_IPADDRESS (host);
+ ASN1_OCTET_STRING *host_in_octet_string = a2i_IPADDRESS (host);
int numaltnames = sk_GENERAL_NAME_num (subjectAltNames);
int i;
}
else if (name->type == GEN_DNS)
{
- /* Check for dNSName */
- alt_name_checked = true;
/* dNSName should be IA5String (i.e. ASCII), however who
* does trust CA? Convert it into UTF-8 for sure. */
unsigned char *name_in_utf8 = NULL;
+
+ /* Check for dNSName */
+ alt_name_checked = true;
+
if (0 <= ASN1_STRING_to_UTF8 (&name_in_utf8, name->d.dNSName))
{
/* Compare and check for NULL attack in ASN1_STRING */