diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c index d324314e9e2..e951ef8e9c5 100644 --- a/dlls/crypt32/chain.c +++ b/dlls/crypt32/chain.c @@ -3035,7 +3035,31 @@ static BOOL match_dns_to_subject_alt_name(PCERT_EXTENSION ext, { TRACE_(chain)("dNSName: %s\n", debugstr_w( subjectName->rgAltEntry[i].u.pwszDNSName)); - if (!strcmpiW(server_name, + if (subjectName->rgAltEntry[i].u.pwszDNSName[0] == '*') + { + LPCWSTR server_name_dot; + + /* Matching a wildcard: a wildcard matches a single name + * component, which is terminated by a dot. RFC 1034 + * doesn't define whether multiple wildcards are allowed, + * but I will assume that they are not until proven + * otherwise. RFC 1034 also states that 'the "*" label + * always matches at least one whole label and sometimes + * more, but always whole labels.' Native crypt32 does not + * match more than one label with a wildcard, so I do the + * same here. Thus, a wildcard only accepts the first + * label, then requires an exact match of the remaining + * string. + */ + server_name_dot = strchrW(server_name, '.'); + if (server_name_dot) + { + if (!strcmpiW(server_name_dot, + subjectName->rgAltEntry[i].u.pwszDNSName + 1)) + matches = TRUE; + } + } + else if (!strcmpiW(server_name, subjectName->rgAltEntry[i].u.pwszDNSName)) matches = TRUE; } diff --git a/dlls/crypt32/tests/chain.c b/dlls/crypt32/tests/chain.c index 0484aa1ca4a..a59a95a0bb1 100644 --- a/dlls/crypt32/tests/chain.c +++ b/dlls/crypt32/tests/chain.c @@ -3818,7 +3818,7 @@ static const ChainPolicyCheck opensslPolicyCheckWithoutMatchingName = { static const ChainPolicyCheck winehqPolicyCheckWithMatchingName = { { sizeof(chain29) / sizeof(chain29[0]), chain29 }, - { 0, 0, -1, -1, NULL}, NULL, TODO_ERROR + { 0, 0, -1, -1, NULL}, NULL, 0 }; static const ChainPolicyCheck winehqPolicyCheckWithoutMatchingName = {