1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

[svn] Support wildcards for matching of hosts against common names presented by

the TLS certificate.
This commit is contained in:
hniksic 2005-05-11 00:58:57 -07:00
parent 51ae4dc884
commit 4054865a00
2 changed files with 50 additions and 15 deletions

View File

@ -1,3 +1,9 @@
2005-05-11 Hrvoje Niksic <hniksic@xemacs.org>
* openssl.c (pattern_match): New function.
(ssl_check_server_identity): Treat peer certificate common name as
wildcard.
2005-05-10 Hrvoje Niksic <hniksic@xemacs.org> 2005-05-10 Hrvoje Niksic <hniksic@xemacs.org>
* openssl.c (ssl_check_server_identity): Print certificate subject * openssl.c (ssl_check_server_identity): Print certificate subject

View File

@ -346,6 +346,42 @@ ssl_connect (int fd)
return 0; return 0;
} }
/* Return 1 is STRING (case-insensitively) matches PATTERN, 0
otherwise. The recognized wildcard character is "*", which matches
any character in STRING except ".". Any number of the "*" wildcard
may be present in the pattern.
This is used to match of hosts as indicated in rfc2818: "Names may
contain the wildcard character * which is considered to match any
single domain name component or component fragment. E.g., *.a.com
matches foo.a.com but not bar.foo.a.com. f*.com matches foo.com but
not bar.com." */
static int
pattern_match (const char *pattern, const char *string)
{
const char *p = pattern, *n = string;
char c;
for (; (c = TOLOWER (*p++)) != '\0'; n++)
if (c == '*')
{
for (c = TOLOWER (*p); c == '*'; c = TOLOWER (*++p))
;
for (; *n != '\0'; n++)
if (TOLOWER (*n) == c && pattern_match (p, n))
return 1;
else if (*n == '.')
return 0;
return c == '\0';
}
else
{
if (c != TOLOWER (*n))
return 0;
}
return *n == '\0';
}
/* Check that the identity of the remote host, as presented by its /* Check that the identity of the remote host, as presented by its
server certificate, corresponds to HOST, which is the host name the server certificate, corresponds to HOST, which is the host name the
user thinks he's connecting to. This assumes that FD has been user thinks he's connecting to. This assumes that FD has been
@ -403,27 +439,20 @@ ssl_check_server_identity (int fd, const char *host)
} }
/* Check that the common name in the presented certificate matches /* Check that the common name in the presented certificate matches
HOST. This is a very simple implementation that should be HOST. This should be improved in the following ways:
improved in the following ways:
1. It should use dNSName if available; according to rfc2818: "If - It should use dNSName/ipAddress subjectAltName extensions if
a subjectAltName extension of type dNSName is present, that available; according to rfc2818: "If a subjectAltName extension
MUST be used as the identity." Ditto for iPAddress. of type dNSName is present, that MUST be used as the identity."
2. It should support the wildcard character "*". Quoting - When matching against common names, it should loop over all
rfc2818, "Names may contain the wildcard character * which is
considered to match any single domain name component or
component fragment. E.g., *.a.com matches foo.a.com but not
bar.foo.a.com. f*.com matches foo.com but not bar.com."
3. When matching against common names, it should loop over all
common names and choose the most specific (apparently the last common names and choose the most specific (apparently the last
one). */ one). */
peer_CN[0] = '\0'; peer_CN[0] = '\0';
X509_NAME_get_text_by_NID (X509_get_subject_name (peer_cert), X509_NAME_get_text_by_NID (X509_get_subject_name (peer_cert),
NID_commonName, peer_CN, sizeof (peer_CN)); NID_commonName, peer_CN, sizeof (peer_CN));
if (0 != strcasecmp (peer_CN, host)) if (!pattern_match (peer_CN, host))
{ {
logprintf (LOG_NOTQUIET, _("\ logprintf (LOG_NOTQUIET, _("\
%s: certificate common name `%s' doesn't match requested host name `%s'.\n"), %s: certificate common name `%s' doesn't match requested host name `%s'.\n"),