wget: ssl support, securtity patches archlinux.

This commit is contained in:
str1ngs 2011-06-22 13:15:51 -07:00
parent 6d9cc2a9ce
commit dadb69d6ee
3 changed files with 379 additions and 1 deletions

View file

@ -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)
{

View file

@ -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 <string.h>
#include <openssl/ssl.h>
-#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/rand.h>
@@ -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
+ */

View file

@ -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 <pancake@nopcode.org>"
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
}