diff options
Diffstat (limited to 'src/openssl.c')
-rw-r--r-- | src/openssl.c | 127 |
1 files changed, 107 insertions, 20 deletions
diff --git a/src/openssl.c b/src/openssl.c index 7c92ac0..68cd11a 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -40,6 +40,11 @@ as that of the covered work. */ #include <openssl/x509v3.h> #include <openssl/err.h> #include <openssl/rand.h> +#include <openssl/bio.h> +#if OPENSSL_VERSION_NUMBER >= 0x00907000 +#include <openssl/conf.h> +#include <openssl/engine.h> +#endif #include "utils.h" #include "connect.h" @@ -153,6 +158,9 @@ key_type_to_ssl_type (enum keyfile_type type) } } +/* SSL has been initialized */ +static int ssl_true_initialized = 0; + /* Create an SSL Context and set default paths etc. Called the first time an HTTP download is attempted. @@ -162,6 +170,15 @@ bool ssl_init (void) { SSL_METHOD const *meth; + long ssl_options = 0; + +#if OPENSSL_VERSION_NUMBER >= 0x00907000 + if (ssl_true_initialized == 0) + { + OPENSSL_config (NULL); + ssl_true_initialized = 1; + } +#endif if (ssl_ctx) /* The SSL has already been initialized. */ @@ -176,6 +193,12 @@ ssl_init (void) goto error; } +#if OPENSSL_VERSION_NUMBER >= 0x00907000 + OPENSSL_load_builtin_modules(); + ENGINE_load_builtin_engines(); + CONF_modules_load_file(NULL, NULL, + CONF_MFLAGS_DEFAULT_SECTION|CONF_MFLAGS_IGNORE_MISSING_FILE); +#endif SSL_library_init (); SSL_load_error_strings (); SSLeay_add_all_algorithms (); @@ -183,22 +206,48 @@ ssl_init (void) switch (opt.secure_protocol) { - case secure_protocol_auto: - meth = SSLv23_client_method (); - break; #ifndef OPENSSL_NO_SSL2 case secure_protocol_sslv2: meth = SSLv2_client_method (); break; #endif + +#ifndef OPENSSL_NO_SSL3 case secure_protocol_sslv3: meth = SSLv3_client_method (); break; +#endif + + case secure_protocol_auto: case secure_protocol_pfs: + meth = SSLv23_client_method (); + ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + break; case secure_protocol_tlsv1: meth = TLSv1_client_method (); break; + +#if OPENSSL_VERSION_NUMBER >= 0x10001000 + case secure_protocol_tlsv1_1: + meth = TLSv1_1_client_method (); + break; + + case secure_protocol_tlsv1_2: + meth = TLSv1_2_client_method (); + break; +#else + case secure_protocol_tlsv1_1: + logprintf (LOG_NOTQUIET, _("Your OpenSSL version is too old to support TLSv1.1\n")); + goto error; + + case secure_protocol_tlsv1_2: + logprintf (LOG_NOTQUIET, _("Your OpenSSL version is too old to support TLSv1.2\n")); + goto error; +#endif + default: + logprintf (LOG_NOTQUIET, _("OpenSSL: unimplemented 'secure-protocol' option value %d\n"), opt.secure_protocol); + logprintf (LOG_NOTQUIET, _("Please report this issue to bug-wget@gnu.org\n")); abort (); } @@ -208,6 +257,9 @@ ssl_init (void) if (!ssl_ctx) goto error; + if (ssl_options) + SSL_CTX_set_options (ssl_ctx, ssl_options); + /* 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) */ @@ -217,6 +269,18 @@ ssl_init (void) SSL_CTX_set_default_verify_paths (ssl_ctx); SSL_CTX_load_verify_locations (ssl_ctx, opt.ca_cert, opt.ca_directory); + if (opt.crl_file) + { + X509_STORE *store = SSL_CTX_get_cert_store (ssl_ctx); + X509_LOOKUP *lookup; + + if (!(lookup = X509_STORE_add_lookup (store, X509_LOOKUP_file ())) + || (!X509_load_crl_file (lookup, opt.crl_file, X509_FILETYPE_PEM))) + goto error; + + X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); + } + /* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the certificate is invalid. We verify the certificate separately in ssl_check_certificate, which provides much better diagnostics @@ -305,7 +369,7 @@ openssl_read (int fd, char *buf, int bufsize, void *arg) } static int -openssl_write (int fd, char *buf, int bufsize, void *arg) +openssl_write (int fd _GL_UNUSED, char *buf, int bufsize, void *arg) { int ret = 0; struct openssl_transport_context *ctx = arg; @@ -347,7 +411,7 @@ openssl_peek (int fd, char *buf, int bufsize, void *arg) } static const char * -openssl_errstr (int fd, void *arg) +openssl_errstr (int fd _GL_UNUSED, void *arg) { struct openssl_transport_context *ctx = arg; unsigned long errcode; @@ -359,7 +423,7 @@ openssl_errstr (int fd, void *arg) return NULL; /* Get rid of previous contents of ctx->last_error, if any. */ - xfree_null (ctx->last_error); + xfree (ctx->last_error); /* Iterate over OpenSSL's error stack and accumulate errors in the last_error buffer, separated by "; ". This is better than using @@ -403,7 +467,7 @@ openssl_close (int fd, void *arg) SSL_shutdown (conn); SSL_free (conn); - xfree_null (ctx->last_error); + xfree (ctx->last_error); xfree (ctx); close (fd); @@ -459,10 +523,10 @@ ssl_connect_wget (int fd, const char *hostname) if (! is_valid_ip_address (hostname)) { if (! SSL_set_tlsext_host_name (conn, hostname)) - { - DEBUGP (("Failed to set TLS server-name indication.")); - goto error; - } + { + DEBUGP (("Failed to set TLS server-name indication.")); + goto error; + } } #endif @@ -544,6 +608,27 @@ pattern_match (const char *pattern, const char *string) return *n == '\0'; } +static char *_get_rfc2253_formatted (X509_NAME *name) +{ + int len; + char *out = NULL; + BIO* b; + + if ((b = BIO_new (BIO_s_mem ()))) + { + if (X509_NAME_print_ex (b, name, 0, XN_FLAG_RFC2253) >= 0 + && (len = BIO_number_written (b)) > 0) + { + out = xmalloc (len + 1); + BIO_read (b, out, len); + out[len] = 0; + } + BIO_free (b); + } + + return out ? out : xstrdup(""); +} + /* Verify the validity of the certificate presented by the server. Also check that the "common name" of the server, as presented by its certificate, corresponds to HOST. (HOST typically comes from @@ -587,23 +672,25 @@ ssl_check_certificate (int fd, const char *host) IF_DEBUG { - char *subject = X509_NAME_oneline (X509_get_subject_name (cert), 0, 0); - char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0); + char *subject = _get_rfc2253_formatted (X509_get_subject_name (cert)); + char *issuer = _get_rfc2253_formatted (X509_get_issuer_name (cert)); DEBUGP (("certificate:\n subject: %s\n issuer: %s\n", quotearg_n_style (0, escape_quoting_style, subject), quotearg_n_style (1, escape_quoting_style, issuer))); - OPENSSL_free (subject); - OPENSSL_free (issuer); + xfree (subject); + xfree (issuer); } vresult = SSL_get_verify_result (conn); if (vresult != X509_V_OK) { - char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0); + char *issuer = _get_rfc2253_formatted (X509_get_issuer_name (cert)); logprintf (LOG_NOTQUIET, _("%s: cannot verify %s's certificate, issued by %s:\n"), severity, quotearg_n_style (0, escape_quoting_style, host), quote_n (1, issuer)); + xfree(issuer); + /* Try to print more user-friendly (and translated) messages for the frequent verification errors. */ switch (vresult) @@ -689,7 +776,7 @@ ssl_check_certificate (int fd, const char *host) /* Compare and check for NULL attack in ASN1_STRING */ if (pattern_match ((char *)name_in_utf8, host) && (strlen ((char *)name_in_utf8) == - ASN1_STRING_length (name->d.dNSName))) + (size_t) ASN1_STRING_length (name->d.dNSName))) { OPENSSL_free (name_in_utf8); break; @@ -699,7 +786,7 @@ ssl_check_certificate (int fd, const char *host) } } } - sk_GENERAL_NAME_free (subjectAltNames); + sk_GENERAL_NAME_pop_free(subjectAltNames, GENERAL_NAME_free); if (host_in_octet_string) ASN1_OCTET_STRING_free(host_in_octet_string); @@ -712,7 +799,7 @@ ssl_check_certificate (int fd, const char *host) success = false; } } - + if (alt_name_checked == false) { /* Test commomName */ @@ -753,7 +840,7 @@ ssl_check_certificate (int fd, const char *host) xentry = X509_NAME_get_entry(xname,i); sdata = X509_NAME_ENTRY_get_data(xentry); - if (strlen (common_name) != ASN1_STRING_length (sdata)) + if (strlen (common_name) != (size_t) ASN1_STRING_length (sdata)) { logprintf (LOG_NOTQUIET, _("\ %s: certificate common name is invalid (contains a NUL character).\n\ |