X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Fopenssl.c;h=3924e41ea19e9cf7af2c7b0e6296206753d1e789;hb=c9c0e4c6418350d913638d73e0a50bebdb5fd983;hp=4eef5c6c49c82efa3510da3ce6c005cd50068d0c;hpb=d92049ef6680731574c0e533628f6b69fb9f28fd;p=wget diff --git a/src/openssl.c b/src/openssl.c index 4eef5c6c..3924e41e 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -1,6 +1,6 @@ /* 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. @@ -33,9 +33,7 @@ as that of the covered work. */ #include #include -#ifdef HAVE_UNISTD_H -# include -#endif +#include #include #include @@ -48,6 +46,10 @@ as that of the covered work. */ #include "url.h" #include "ssl.h" +#ifdef WINDOWS +# include +#endif + /* Application-wide SSL context. This is common to all SSL connections. */ static SSL_CTX *ssl_ctx; @@ -157,9 +159,9 @@ key_type_to_ssl_type (enum keyfile_type type) Returns true on success, false otherwise. */ bool -ssl_init () +ssl_init (void) { - SSL_METHOD *meth; + SSL_METHOD const *meth; if (ssl_ctx) /* The SSL has already been initialized. */ @@ -184,9 +186,11 @@ ssl_init () 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; @@ -197,7 +201,9 @@ ssl_init () 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; @@ -261,6 +267,7 @@ openssl_read (int fd, char *buf, int bufsize, void *arg) while (ret == -1 && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL && errno == EINTR); + return ret; } @@ -283,10 +290,10 @@ openssl_poll (int fd, double timeout, int wait_for, void *arg) { 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); } @@ -296,6 +303,8 @@ openssl_peek (int fd, char *buf, int bufsize, void *arg) 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 @@ -364,11 +373,7 @@ openssl_close (int fd, void *arg) 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))); } @@ -390,7 +395,7 @@ static struct transport_implementation openssl_transport = { 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; @@ -401,7 +406,23 @@ ssl_connect_wget (int fd) 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) @@ -576,8 +597,7 @@ ssl_check_certificate (int fd, const char *host) /* 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; @@ -602,11 +622,13 @@ ssl_check_certificate (int fd, const char *host) } 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 */