From e82005fe2dcd983769b09550e0f69f8bb36def05 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Fri, 13 Nov 2009 17:44:42 -0800 Subject: [PATCH] crypt32: Only compare the hostname portion of a URL when checking against a name constraint. --- dlls/crypt32/chain.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c index 3badef1da77..0fd9df793e3 100644 --- a/dlls/crypt32/chain.c +++ b/dlls/crypt32/chain.c @@ -517,14 +517,58 @@ static BOOL url_matches(LPCWSTR constraint, LPCWSTR name, *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS; else if (!name) ; /* no match */ - else if (constraint[0] == '.') + else { - if (lstrlenW(name) > lstrlenW(constraint)) - match = !lstrcmpiW(name + lstrlenW(name) - lstrlenW(constraint), - constraint); + LPCWSTR colon, authority_end, at, hostname = NULL; + /* The maximum length for a hostname is 254 in the DNS, see RFC 1034 */ + WCHAR hostname_buf[255]; + + /* RFC 5280: only the hostname portion of the URL is compared. From + * section 4.2.1.10: + * "For URIs, the constraint applies to the host part of the name. + * The constraint MUST be specified as a fully qualified domain name + * and MAY specify a host or a domain." + * The format for URIs is in RFC 2396. + * + * First, remove any scheme that's present. */ + colon = strchrW(name, ':'); + if (colon && *(colon + 1) == '/' && *(colon + 2) == '/') + name = colon + 3; + /* Next, find the end of the authority component. (The authority is + * generally just the hostname, but it may contain a username or a port. + * Those are removed next.) + */ + authority_end = strchrW(name, '/'); + if (!authority_end) + authority_end = strchrW(name, '?'); + if (!authority_end) + authority_end = name + strlenW(name); + /* Remove any port number from the authority */ + for (colon = authority_end; colon >= name && *colon != ':'; colon--) + ; + if (*colon == ':') + authority_end = colon; + /* Remove any username from the authority */ + if ((at = strchrW(name, '@'))) + name = at; + /* Ignore any path or query portion of the URL. */ + if (*authority_end) + { + if (authority_end - name < sizeof(hostname_buf) / + sizeof(hostname_buf[0])) + { + memcpy(hostname_buf, name, + (authority_end - name) * sizeof(WCHAR)); + hostname_buf[authority_end - name] = 0; + hostname = hostname_buf; + } + /* else: Hostname is too long, not a match */ + } + else + hostname = name; + if (hostname) + match = !lstrcmpiW(constraint, hostname); } - else - match = !lstrcmpiW(constraint, name); return match; } -- 2.11.4.GIT