1
0
mirror of https://github.com/mirror/wget.git synced 2025-03-28 13:00:10 +08:00

Enhance SSL/TLS security

This commit hardens SSL/TLS a bit more in the following ways:

 * Explicitly exclude NULL authentication and the 'MEDIUM' cipher list
   category. Ciphers in the 'HIGH' level are only considered - this
   includes all symmetric ciphers with key lengths larger than 128 bits,
   and some ('modern') 128-bit ciphers, such as AES in GCM mode.
 * Allow RSA key exchange by default, but exclude it when
   Perfect Forward Secrecy is desired (with --secure-protocol=PFS).
 * Introduce new option --ciphers to set the cipher list that the SSL/TLS
   engine will favor. This string is fed directly to the underlying TLS
   library (GnuTLS or OpenSSL) without further processing, and hence its
   format and syntax are directly dependent on the specific library.

Reported-by: Jeffrey Walton <noloader@gmail.com>
This commit is contained in:
Ander Juaristi 2018-04-28 14:06:34 +02:00 committed by Tim Rühsen
parent 26a50942d8
commit 744671aac6
5 changed files with 81 additions and 31 deletions

View File

@ -535,35 +535,10 @@ _sni_hostname(const char *hostname)
return sni_hostname;
}
bool
ssl_connect_wget (int fd, const char *hostname, int *continue_session)
static int
set_prio_default (gnutls_session_t session)
{
struct wgnutls_transport_context *ctx;
gnutls_session_t session;
int err;
gnutls_init (&session, GNUTLS_CLIENT);
/* We set the server name but only if it's not an IP address. */
if (! is_valid_ip_address (hostname))
{
/* GnuTLS 3.4.x (x<=10) disrespects the length parameter, we have to construct a new string */
/* see https://gitlab.com/gnutls/gnutls/issues/78 */
const char *sni_hostname = _sni_hostname(hostname);
gnutls_server_name_set (session, GNUTLS_NAME_DNS, sni_hostname, strlen(sni_hostname));
xfree(sni_hostname);
}
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
#ifndef FD_TO_SOCKET
# define FD_TO_SOCKET(X) (X)
#endif
#ifdef HAVE_INTPTR_T
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) FD_TO_SOCKET (fd));
#else
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) FD_TO_SOCKET (fd));
#endif
int err = -1;
#if HAVE_GNUTLS_PRIORITY_SET_DIRECT
switch (opt.secure_protocol)
@ -642,6 +617,53 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
}
#endif
return err;
}
bool
ssl_connect_wget (int fd, const char *hostname, int *continue_session)
{
struct wgnutls_transport_context *ctx;
gnutls_session_t session;
int err;
gnutls_init (&session, GNUTLS_CLIENT);
/* We set the server name but only if it's not an IP address. */
if (! is_valid_ip_address (hostname))
{
/* GnuTLS 3.4.x (x<=10) disrespects the length parameter, we have to construct a new string */
/* see https://gitlab.com/gnutls/gnutls/issues/78 */
const char *sni_hostname = _sni_hostname(hostname);
gnutls_server_name_set (session, GNUTLS_NAME_DNS, sni_hostname, strlen(sni_hostname));
xfree(sni_hostname);
}
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
#ifndef FD_TO_SOCKET
# define FD_TO_SOCKET(X) (X)
#endif
#ifdef HAVE_INTPTR_T
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) FD_TO_SOCKET (fd));
#else
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) FD_TO_SOCKET (fd));
#endif
if (!opt.tls_ciphers_string)
{
err = set_prio_default (session);
}
else
{
#if HAVE_GNUTLS_PRIORITY_SET_DIRECT
err = gnutls_priority_set_direct (session, opt.tls_ciphers_string, NULL);
#else
logprintf (LOG_NOTQUIET, _("GnuTLS: Cannot set prio string directly. Falling back to default priority.\n"));
err = gnutls_set_default_priority ();
#endif
}
if (err < 0)
{
logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));

View File

@ -281,6 +281,7 @@ static const struct {
#endif
{ "preservepermissions", &opt.preserve_perm, cmd_boolean },
#ifdef HAVE_SSL
{ "ciphers", &opt.tls_ciphers_string, cmd_string },
{ "privatekey", &opt.private_key, cmd_file },
{ "privatekeytype", &opt.private_key_type, cmd_cert_type },
#endif

View File

@ -392,6 +392,7 @@ static struct cmdline_option option_data[] =
{ "preferred-location", 0, OPT_VALUE, "preferredlocation", -1 },
#endif
{ "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 },
{ IF_SSL ("ciphers"), 0, OPT_VALUE, "ciphers", -1 },
{ IF_SSL ("private-key"), 0, OPT_VALUE, "privatekey", -1 },
{ IF_SSL ("private-key-type"), 0, OPT_VALUE, "privatekeytype", -1 },
{ "progress", 0, OPT_VALUE, "progress", -1 },
@ -875,6 +876,10 @@ HTTPS (SSL/TLS) options:\n"),
--egd-file=FILE file naming the EGD socket with random data\n"),
#endif
"\n",
N_("\
--ciphers=STR Set the priority string (GnuTLS) or cipher list string (OpenSSL) directly.\n\
Use with care. This option overrides --secure-protocol.\n\
The format and syntax of this string depend on the specific SSL/TLS engine.\n"),
#endif /* HAVE_SSL */
#ifdef HAVE_HSTS

View File

@ -173,6 +173,7 @@ ssl_init (void)
{
SSL_METHOD const *meth;
long ssl_options = 0;
char *ciphers_string = NULL;
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
int ssl_proto_version = 0;
#endif
@ -305,10 +306,29 @@ ssl_init (void)
#endif
/* OpenSSL ciphers: https://www.openssl.org/docs/apps/ciphers.html
* Since we want a good protection, we also use HIGH (that excludes MD4 ciphers and some more)
*
* Rules:
* 1. --ciphers overrides everything
* 2. We allow RSA key exchange by default (secure_protocol_auto)
* 3. We disallow RSA key exchange if PFS was requested (secure_protocol_pfs)
*/
if (opt.secure_protocol == secure_protocol_pfs)
SSL_CTX_set_cipher_list (ssl_ctx, "HIGH:MEDIUM:!RC4:!SRP:!PSK:!RSA:!aNULL@STRENGTH");
if (!opt.tls_ciphers_string)
{
if (opt.secure_protocol == secure_protocol_auto)
ciphers_string = "HIGH:!aNULL:!RC4:!MD5:!SRP:!PSK";
else if (opt.secure_protocol == secure_protocol_pfs)
ciphers_string = "HIGH:!aNULL:!RC4:!MD5:!SRP:!PSK:!kRSA";
}
else
{
ciphers_string = opt.tls_ciphers_string;
}
if (ciphers_string && !SSL_CTX_set_cipher_list(ssl_ctx, ciphers_string))
{
logprintf(LOG_NOTQUIET, _("OpenSSL: Invalid cipher list: %s\n"), ciphers_string);
goto error;
}
SSL_CTX_set_default_verify_paths (ssl_ctx);
SSL_CTX_load_verify_locations (ssl_ctx, opt.ca_cert, opt.ca_directory);

View File

@ -257,6 +257,8 @@ struct options
bool ftps_fallback_to_ftp;
bool ftps_implicit;
bool ftps_clear_data_connection;
char *tls_ciphers_string;
#endif /* HAVE_SSL */
bool cookies; /* whether cookies are used. */