From dadb69d6ee322bcf048723e0ef7070b087e797cb Mon Sep 17 00:00:00 2001 From: str1ngs Date: Wed, 22 Jun 2011 13:15:51 -0700 Subject: [PATCH] wget: ssl support, securtity patches archlinux. --- .../patches/wget-1.12-CVE-2010-2252.patch | 155 +++++++++++++ .../patches/wget-1.12-subjectAltName.patch | 216 ++++++++++++++++++ srcpkgs/wget/template | 9 +- 3 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/wget/patches/wget-1.12-CVE-2010-2252.patch create mode 100644 srcpkgs/wget/patches/wget-1.12-subjectAltName.patch diff --git a/srcpkgs/wget/patches/wget-1.12-CVE-2010-2252.patch b/srcpkgs/wget/patches/wget-1.12-CVE-2010-2252.patch new file mode 100644 index 00000000000..f688148a362 --- /dev/null +++ b/srcpkgs/wget/patches/wget-1.12-CVE-2010-2252.patch @@ -0,0 +1,155 @@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' wget~/doc/wget.texi wget/doc/wget.texi +--- doc/wget.texi 2010-09-05 15:32:44.000000000 +0200 ++++ doc/wget.texi 2010-09-05 15:32:44.000000000 +0200 +@@ -1487,6 +1487,13 @@ + @code{Content-Disposition} headers to describe what the name of a + downloaded file should be. + ++@cindex Trust server names ++@item --trust-server-names ++ ++If this is set to on, on a redirect the last component of the ++redirection URL will be used as the local file name. By default it is ++used the last component in the original URL. ++ + @cindex authentication + @item --auth-no-challenge + +@@ -2797,6 +2804,10 @@ + Turn on recognition of the (non-standard) @samp{Content-Disposition} + HTTP header---if set to @samp{on}, the same as @samp{--content-disposition}. + ++@item trust_server_names = on/off ++If set to on, use the last component of a redirection URL for the local ++file name. ++ + @item continue = on/off + If set to on, force continuation of preexistent partially retrieved + files. See @samp{-c} before setting it. +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' wget~/src/http.c wget/src/http.c +--- src/http.c 2010-09-05 15:30:22.000000000 +0200 ++++ src/http.c 2010-09-05 15:32:44.000000000 +0200 +@@ -2410,8 +2410,9 @@ + /* The genuine HTTP loop! This is the part where the retrieval is + retried, and retried, and retried, and... */ + uerr_t +-http_loop (struct url *u, char **newloc, char **local_file, const char *referer, +- int *dt, struct url *proxy, struct iri *iri) ++http_loop (struct url *u, struct url *original_url, char **newloc, ++ char **local_file, const char *referer, int *dt, struct url *proxy, ++ struct iri *iri) + { + int count; + bool got_head = false; /* used for time-stamping and filename detection */ +@@ -2457,7 +2458,8 @@ + } + else if (!opt.content_disposition) + { +- hstat.local_file = url_file_name (u); ++ hstat.local_file = ++ url_file_name (opt.trustservernames ? u : original_url); + got_name = true; + } + +@@ -2497,7 +2499,7 @@ + + /* Send preliminary HEAD request if -N is given and we have an existing + * destination file. */ +- file_name = url_file_name (u); ++ file_name = url_file_name (opt.trustservernames ? u : original_url); + if (opt.timestamping + && !opt.content_disposition + && file_exists_p (file_name)) +@@ -2852,9 +2854,9 @@ + + /* Remember that we downloaded the file for later ".orig" code. */ + if (*dt & ADDED_HTML_EXTENSION) +- downloaded_file(FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file); ++ downloaded_file (FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file); + else +- downloaded_file(FILE_DOWNLOADED_NORMALLY, hstat.local_file); ++ downloaded_file (FILE_DOWNLOADED_NORMALLY, hstat.local_file); + + ret = RETROK; + goto exit; +@@ -2885,9 +2887,9 @@ + + /* Remember that we downloaded the file for later ".orig" code. */ + if (*dt & ADDED_HTML_EXTENSION) +- downloaded_file(FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file); ++ downloaded_file (FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file); + else +- downloaded_file(FILE_DOWNLOADED_NORMALLY, hstat.local_file); ++ downloaded_file (FILE_DOWNLOADED_NORMALLY, hstat.local_file); + + ret = RETROK; + goto exit; +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' wget~/src/http.h wget/src/http.h +--- src/http.h 2010-09-05 15:30:22.000000000 +0200 ++++ src/http.h 2010-09-05 15:32:44.000000000 +0200 +@@ -33,8 +33,8 @@ + + struct url; + +-uerr_t http_loop (struct url *, char **, char **, const char *, int *, +- struct url *, struct iri *); ++uerr_t http_loop (struct url *, struct url *, char **, char **, const char *, ++ int *, struct url *, struct iri *); + void save_cookies (void); + void http_cleanup (void); + time_t http_atotm (const char *); +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' wget~/src/init.c wget/src/init.c +--- src/init.c 2010-09-05 15:30:22.000000000 +0200 ++++ src/init.c 2010-09-05 15:32:44.000000000 +0200 +@@ -243,6 +243,7 @@ + { "timeout", NULL, cmd_spec_timeout }, + { "timestamping", &opt.timestamping, cmd_boolean }, + { "tries", &opt.ntry, cmd_number_inf }, ++ { "trustservernames", &opt.trustservernames, cmd_boolean }, + { "useproxy", &opt.use_proxy, cmd_boolean }, + { "user", &opt.user, cmd_string }, + { "useragent", NULL, cmd_spec_useragent }, +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' wget~/src/main.c wget/src/main.c +--- src/main.c 2010-09-05 15:30:22.000000000 +0200 ++++ src/main.c 2010-09-05 15:32:44.000000000 +0200 +@@ -266,6 +266,7 @@ + { "timeout", 'T', OPT_VALUE, "timeout", -1 }, + { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 }, + { "tries", 't', OPT_VALUE, "tries", -1 }, ++ { "trust-server-names", 0, OPT_BOOLEAN, "trustservernames", -1 }, + { "user", 0, OPT_VALUE, "user", -1 }, + { "user-agent", 'U', OPT_VALUE, "useragent", -1 }, + { "verbose", 'v', OPT_BOOLEAN, "verbose", -1 }, +@@ -675,6 +676,8 @@ + N_("\ + -I, --include-directories=LIST list of allowed directories.\n"), + N_("\ ++ --trust-server-names use the name specified by the redirection url last component.\n"), ++ N_("\ + -X, --exclude-directories=LIST list of excluded directories.\n"), + N_("\ + -np, --no-parent don't ascend to the parent directory.\n"), +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' wget~/src/options.h wget/src/options.h +--- src/options.h 2010-09-05 15:30:22.000000000 +0200 ++++ src/options.h 2010-09-05 15:32:44.000000000 +0200 +@@ -242,6 +242,7 @@ + char *encoding_remote; + char *locale; + ++ bool trustservernames; + #ifdef __VMS + int ftp_stmlf; /* Force Stream_LF format for binary FTP. */ + #endif /* def __VMS */ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' wget~/src/retr.c wget/src/retr.c +--- src/retr.c 2010-09-05 15:30:22.000000000 +0200 ++++ src/retr.c 2010-09-05 15:32:44.000000000 +0200 +@@ -689,7 +689,8 @@ + #endif + || (proxy_url && proxy_url->scheme == SCHEME_HTTP)) + { +- result = http_loop (u, &mynewloc, &local_file, refurl, dt, proxy_url, iri); ++ result = http_loop (u, orig_parsed, &mynewloc, &local_file, refurl, dt, ++ proxy_url, iri); + } + else if (u->scheme == SCHEME_FTP) + { diff --git a/srcpkgs/wget/patches/wget-1.12-subjectAltName.patch b/srcpkgs/wget/patches/wget-1.12-subjectAltName.patch new file mode 100644 index 00000000000..20f08d216b2 --- /dev/null +++ b/srcpkgs/wget/patches/wget-1.12-subjectAltName.patch @@ -0,0 +1,216 @@ +=== modified file 'src/openssl.c' +--- src/openssl.c 2009-09-22 16:16:43 +0000 ++++ src/openssl.c 2009-10-24 23:06:44 +0000 +@@ -39,7 +39,7 @@ + #include + + #include +-#include ++#include + #include + #include + +@@ -486,9 +486,11 @@ + ssl_check_certificate (int fd, const char *host) + { + X509 *cert; ++ GENERAL_NAMES *subjectAltNames; + char common_name[256]; + long vresult; + bool success = true; ++ bool alt_name_checked = false; + + /* If the user has specified --no-check-cert, we still want to warn + him about problems with the server's certificate. */ +@@ -536,7 +538,8 @@ + break; + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: +- logprintf (LOG_NOTQUIET, _(" Self-signed certificate encountered.\n")); ++ logprintf (LOG_NOTQUIET, ++ _(" Self-signed certificate encountered.\n")); + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + logprintf (LOG_NOTQUIET, _(" Issued certificate not yet valid.\n")); +@@ -558,10 +561,6 @@ + /* Check that HOST matches the common name in the certificate. + #### The following remains to be done: + +- - It should use dNSName/ipAddress subjectAltName extensions if +- available; according to rfc2818: "If a subjectAltName extension +- of type dNSName is present, that MUST be used as the identity." +- + - When matching against common names, it should loop over all + common names and choose the most specific one, i.e. the last + one, not the first one, which the current code picks. +@@ -569,50 +568,123 @@ + - Ensure that ASN1 strings from the certificate are encoded as + UTF-8 which can be meaningfully compared to HOST. */ + +- X509_NAME *xname = X509_get_subject_name(cert); +- common_name[0] = '\0'; +- X509_NAME_get_text_by_NID (xname, NID_commonName, common_name, +- sizeof (common_name)); ++ subjectAltNames = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL); + +- if (!pattern_match (common_name, host)) ++ if (subjectAltNames) + { +- logprintf (LOG_NOTQUIET, _("\ +-%s: certificate common name %s doesn't match requested host name %s.\n"), +- severity, quote_n (0, common_name), quote_n (1, host)); +- success = false; ++ /* Test subject alternative names */ ++ ++ /* 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); ++ ++ int numaltnames = sk_GENERAL_NAME_num (subjectAltNames); ++ int i; ++ for (i=0; i < numaltnames; i++) ++ { ++ const GENERAL_NAME *name = ++ sk_GENERAL_NAME_value (subjectAltNames, i); ++ if (name) ++ { ++ if (host_in_octet_string) ++ { ++ if (name->type == GEN_IPADD) ++ { ++ /* Check for ipAddress */ ++ /* TODO: Should we convert between IPv4-mapped IPv6 ++ * addresses and IPv4 addresses? */ ++ alt_name_checked = true; ++ if (!ASN1_STRING_cmp (host_in_octet_string, ++ name->d.iPAddress)) ++ break; ++ } ++ } ++ 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; ++ if (0 <= ASN1_STRING_to_UTF8 (&name_in_utf8, name->d.dNSName)) ++ { ++ /* 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))) ++ { ++ OPENSSL_free (name_in_utf8); ++ break; ++ } ++ OPENSSL_free (name_in_utf8); ++ } ++ } ++ } ++ } ++ sk_GENERAL_NAME_free (subjectAltNames); ++ if (host_in_octet_string) ++ ASN1_OCTET_STRING_free(host_in_octet_string); ++ ++ if (alt_name_checked == true && i >= numaltnames) ++ { ++ logprintf (LOG_NOTQUIET, ++ _("%s: no certificate subject alternative name matches\n" ++ "\trequested host name %s.\n"), ++ severity, quote_n (1, host)); ++ success = false; ++ } + } +- else ++ ++ if (alt_name_checked == false) + { +- /* We now determine the length of the ASN1 string. If it differs from +- * common_name's length, then there is a \0 before the string terminates. +- * This can be an instance of a null-prefix attack. +- * +- * https://www.blackhat.com/html/bh-usa-09/bh-usa-09-archives.html#Marlinspike +- * */ +- +- int i = -1, j; +- X509_NAME_ENTRY *xentry; +- ASN1_STRING *sdata; +- +- if (xname) { +- for (;;) +- { +- j = X509_NAME_get_index_by_NID (xname, NID_commonName, i); +- if (j == -1) break; +- i = j; ++ /* Test commomName */ ++ X509_NAME *xname = X509_get_subject_name(cert); ++ common_name[0] = '\0'; ++ X509_NAME_get_text_by_NID (xname, NID_commonName, common_name, ++ sizeof (common_name)); ++ ++ if (!pattern_match (common_name, host)) ++ { ++ logprintf (LOG_NOTQUIET, _("\ ++ %s: certificate common name %s doesn't match requested host name %s.\n"), ++ severity, quote_n (0, common_name), quote_n (1, host)); ++ success = false; ++ } ++ else ++ { ++ /* We now determine the length of the ASN1 string. If it ++ * differs from common_name's length, then there is a \0 ++ * before the string terminates. This can be an instance of a ++ * null-prefix attack. ++ * ++ * https://www.blackhat.com/html/bh-usa-09/bh-usa-09-archives.html#Marlinspike ++ * */ ++ ++ int i = -1, j; ++ X509_NAME_ENTRY *xentry; ++ ASN1_STRING *sdata; ++ ++ if (xname) { ++ for (;;) ++ { ++ j = X509_NAME_get_index_by_NID (xname, NID_commonName, i); ++ if (j == -1) break; ++ i = j; ++ } + } +- } + +- xentry = X509_NAME_get_entry(xname,i); +- sdata = X509_NAME_ENTRY_get_data(xentry); +- if (strlen (common_name) != ASN1_STRING_length (sdata)) +- { +- logprintf (LOG_NOTQUIET, _("\ +-%s: certificate common name is invalid (contains a NUL character).\n\ +-This may be an indication that the host is not who it claims to be\n\ +-(that is, it is not the real %s).\n"), +- severity, quote (host)); +- success = false; ++ xentry = X509_NAME_get_entry(xname,i); ++ sdata = X509_NAME_ENTRY_get_data(xentry); ++ if (strlen (common_name) != ASN1_STRING_length (sdata)) ++ { ++ logprintf (LOG_NOTQUIET, _("\ ++ %s: certificate common name is invalid (contains a NUL character).\n\ ++ This may be an indication that the host is not who it claims to be\n\ ++ (that is, it is not the real %s).\n"), ++ severity, quote (host)); ++ success = false; ++ } + } + } + +@@ -631,3 +703,7 @@ + /* Allow --no-check-cert to disable certificate checking. */ + return opt.check_cert ? success : true; + } ++ ++/* ++ * vim: tabstop=2 shiftwidth=2 softtabstop=2 ++ */ + diff --git a/srcpkgs/wget/template b/srcpkgs/wget/template index 5617739db4a..e63c47dd957 100644 --- a/srcpkgs/wget/template +++ b/srcpkgs/wget/template @@ -1,9 +1,10 @@ # Template file for 'wget' pkgname=wget version=1.12 -revision=2 +revision=3 distfiles="http://ftp.gnu.org/gnu/$pkgname/$pkgname-$version.tar.gz" build_style=gnu_configure +configure_args="--with-ssl" short_desc="The GNU wget utility" maintainer="pancake " checksum=7578ed0974e12caa71120581fa3962ee5a69f7175ddc3d6a6db0ecdcba65b572 @@ -43,3 +44,9 @@ post_build() mkdir -p ${DESTDIR}/usr/share/info touch -f ${DESTDIR}/usr/share/info/dir } + +post_install() +{ + echo "ca_certificate=/etc/ssl/certs/ca-certificates.crt" \ + >> ${DESTDIR}/etc/wgetrc +}