Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
9059892e
Commit
9059892e
authored
Oct 28, 2009
by
Juan Lang
Committed by
Alexandre Julliard
Oct 29, 2009
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
crypt32: Implement CertVerifyCertificateChainPolicy for CERT_CHAIN_POLICY_SSL.
parent
2fbb736e
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
231 additions
and
0 deletions
+231
-0
chain.c
dlls/crypt32/chain.c
+231
-0
No files found.
dlls/crypt32/chain.c
View file @
9059892e
...
...
@@ -2117,6 +2117,234 @@ static BOOL WINAPI verify_basic_constraints_policy(LPCSTR szPolicyOID,
return
TRUE
;
}
static
inline
PCERT_EXTENSION
get_subject_alt_name_ext
(
PCCERT_CONTEXT
cert
)
{
PCERT_EXTENSION
ext
;
ext
=
CertFindExtension
(
szOID_SUBJECT_ALT_NAME2
,
cert
->
pCertInfo
->
cExtension
,
cert
->
pCertInfo
->
rgExtension
);
if
(
!
ext
)
ext
=
CertFindExtension
(
szOID_SUBJECT_ALT_NAME
,
cert
->
pCertInfo
->
cExtension
,
cert
->
pCertInfo
->
rgExtension
);
return
ext
;
}
static
BOOL
match_dns_to_subject_alt_name
(
PCERT_EXTENSION
ext
,
LPCWSTR
server_name
)
{
BOOL
matches
=
FALSE
;
CERT_ALT_NAME_INFO
*
subjectName
;
DWORD
size
;
TRACE_
(
chain
)(
"%s
\n
"
,
debugstr_w
(
server_name
));
/* FIXME: This can be spoofed by the embedded NULL vulnerability. The
* returned CERT_ALT_NAME_INFO doesn't have a way to indicate the
* encoded length of a name, so a certificate issued to
* winehq.org\0badsite.com will get treated as having been issued to
* winehq.org.
*/
if
(
CryptDecodeObjectEx
(
X509_ASN_ENCODING
,
X509_ALTERNATE_NAME
,
ext
->
Value
.
pbData
,
ext
->
Value
.
cbData
,
CRYPT_DECODE_ALLOC_FLAG
|
CRYPT_DECODE_NOCOPY_FLAG
,
NULL
,
&
subjectName
,
&
size
))
{
DWORD
i
;
BOOL
found
=
FALSE
;
for
(
i
=
0
;
!
found
&&
i
<
subjectName
->
cAltEntry
;
i
++
)
{
if
(
subjectName
->
rgAltEntry
[
i
].
dwAltNameChoice
==
CERT_ALT_NAME_DNS_NAME
)
{
TRACE_
(
chain
)(
"dNSName: %s
\n
"
,
debugstr_w
(
subjectName
->
rgAltEntry
[
i
].
u
.
pwszDNSName
));
found
=
TRUE
;
if
(
!
strcmpiW
(
server_name
,
subjectName
->
rgAltEntry
[
i
].
u
.
pwszDNSName
))
matches
=
TRUE
;
}
}
LocalFree
(
subjectName
);
}
return
matches
;
}
static
BOOL
find_matching_domain_component
(
CERT_NAME_INFO
*
name
,
LPCWSTR
component
)
{
BOOL
matches
=
FALSE
;
DWORD
i
,
j
;
for
(
i
=
0
;
!
matches
&&
i
<
name
->
cRDN
;
i
++
)
for
(
j
=
0
;
j
<
name
->
rgRDN
[
i
].
cRDNAttr
;
j
++
)
if
(
!
strcmp
(
szOID_DOMAIN_COMPONENT
,
name
->
rgRDN
[
i
].
rgRDNAttr
[
j
].
pszObjId
))
{
PCERT_RDN_ATTR
attr
;
attr
=
&
name
->
rgRDN
[
i
].
rgRDNAttr
[
j
];
/* Compare with memicmpW rather than strcmpiW in order to avoid
* a match with a string with an embedded NULL. The component
* must match one domain component attribute's entire string
* value with a case-insensitive match.
*/
matches
=
!
memicmpW
(
component
,
(
LPWSTR
)
attr
->
Value
.
pbData
,
attr
->
Value
.
cbData
/
sizeof
(
WCHAR
));
}
return
matches
;
}
static
BOOL
match_dns_to_subject_dn
(
PCCERT_CONTEXT
cert
,
LPCWSTR
server_name
)
{
BOOL
matches
=
FALSE
;
CERT_NAME_INFO
*
name
;
DWORD
size
;
TRACE_
(
chain
)(
"%s
\n
"
,
debugstr_w
(
server_name
));
if
(
CryptDecodeObjectEx
(
X509_ASN_ENCODING
,
X509_UNICODE_NAME
,
cert
->
pCertInfo
->
Subject
.
pbData
,
cert
->
pCertInfo
->
Subject
.
cbData
,
CRYPT_DECODE_ALLOC_FLAG
|
CRYPT_DECODE_NOCOPY_FLAG
,
NULL
,
&
name
,
&
size
))
{
/* If the subject distinguished name contains any name components,
* make sure all of them are present.
*/
if
(
CertFindRDNAttr
(
szOID_DOMAIN_COMPONENT
,
name
))
{
LPCWSTR
ptr
=
server_name
;
matches
=
TRUE
;
do
{
LPCWSTR
dot
=
strchrW
(
ptr
,
'.'
),
end
;
/* 254 is the maximum DNS label length, see RFC 1035 */
WCHAR
component
[
255
];
DWORD
len
;
end
=
dot
?
dot
:
ptr
+
strlenW
(
ptr
);
len
=
end
-
ptr
;
if
(
len
>=
sizeof
(
component
)
/
sizeof
(
component
[
0
]))
{
WARN_
(
chain
)(
"domain component %s too long
\n
"
,
debugstr_wn
(
ptr
,
len
));
matches
=
FALSE
;
}
else
{
memcpy
(
component
,
ptr
,
len
*
sizeof
(
WCHAR
));
component
[
len
]
=
0
;
matches
=
find_matching_domain_component
(
name
,
component
);
}
ptr
=
dot
?
dot
+
1
:
end
;
}
while
(
matches
&&
ptr
&&
*
ptr
);
}
else
{
PCERT_RDN_ATTR
attr
;
/* If the certificate isn't using a DN attribute in the name, make
* make sure the common name matches. Again, use memicmpW rather
* than strcmpiW in order to avoid being fooled by an embedded NULL.
*/
if
((
attr
=
CertFindRDNAttr
(
szOID_COMMON_NAME
,
name
)))
{
TRACE_
(
chain
)(
"CN = %s
\n
"
,
debugstr_w
(
(
LPWSTR
)
attr
->
Value
.
pbData
));
matches
=
!
memicmpW
(
server_name
,
(
LPWSTR
)
attr
->
Value
.
pbData
,
attr
->
Value
.
cbData
/
sizeof
(
WCHAR
));
}
}
LocalFree
(
name
);
}
return
matches
;
}
static
BOOL
WINAPI
verify_ssl_policy
(
LPCSTR
szPolicyOID
,
PCCERT_CHAIN_CONTEXT
pChainContext
,
PCERT_CHAIN_POLICY_PARA
pPolicyPara
,
PCERT_CHAIN_POLICY_STATUS
pPolicyStatus
)
{
pPolicyStatus
->
lChainIndex
=
pPolicyStatus
->
lElementIndex
=
-
1
;
if
(
pChainContext
->
TrustStatus
.
dwErrorStatus
&
CERT_TRUST_IS_NOT_SIGNATURE_VALID
)
{
pPolicyStatus
->
dwError
=
TRUST_E_CERT_SIGNATURE
;
find_element_with_error
(
pChainContext
,
CERT_TRUST_IS_NOT_SIGNATURE_VALID
,
&
pPolicyStatus
->
lChainIndex
,
&
pPolicyStatus
->
lElementIndex
);
}
else
if
(
pChainContext
->
TrustStatus
.
dwErrorStatus
&
CERT_TRUST_IS_UNTRUSTED_ROOT
)
{
pPolicyStatus
->
dwError
=
CERT_E_UNTRUSTEDROOT
;
find_element_with_error
(
pChainContext
,
CERT_TRUST_IS_UNTRUSTED_ROOT
,
&
pPolicyStatus
->
lChainIndex
,
&
pPolicyStatus
->
lElementIndex
);
}
else
if
(
pChainContext
->
TrustStatus
.
dwErrorStatus
&
CERT_TRUST_IS_CYCLIC
)
{
pPolicyStatus
->
dwError
=
CERT_E_UNTRUSTEDROOT
;
find_element_with_error
(
pChainContext
,
CERT_TRUST_IS_CYCLIC
,
&
pPolicyStatus
->
lChainIndex
,
&
pPolicyStatus
->
lElementIndex
);
/* For a cyclic chain, which element is a cycle isn't meaningful */
pPolicyStatus
->
lElementIndex
=
-
1
;
}
else
if
(
pChainContext
->
TrustStatus
.
dwErrorStatus
&
CERT_TRUST_IS_NOT_TIME_VALID
)
{
pPolicyStatus
->
dwError
=
CERT_E_EXPIRED
;
find_element_with_error
(
pChainContext
,
CERT_TRUST_IS_NOT_TIME_VALID
,
&
pPolicyStatus
->
lChainIndex
,
&
pPolicyStatus
->
lElementIndex
);
}
else
pPolicyStatus
->
dwError
=
NO_ERROR
;
/* We only need bother checking whether the name in the end certificate
* matches if the chain is otherwise okay.
*/
if
(
!
pPolicyStatus
->
dwError
&&
pPolicyPara
&&
pPolicyPara
->
cbSize
>=
sizeof
(
CERT_CHAIN_POLICY_PARA
))
{
HTTPSPolicyCallbackData
*
sslPara
=
pPolicyPara
->
pvExtraPolicyPara
;
if
(
sslPara
&&
sslPara
->
u
.
cbSize
>=
sizeof
(
HTTPSPolicyCallbackData
))
{
if
(
sslPara
->
dwAuthType
==
AUTHTYPE_SERVER
&&
sslPara
->
pwszServerName
)
{
PCCERT_CONTEXT
cert
;
PCERT_EXTENSION
altNameExt
;
BOOL
matches
;
cert
=
pChainContext
->
rgpChain
[
0
]
->
rgpElement
[
0
]
->
pCertContext
;
altNameExt
=
get_subject_alt_name_ext
(
cert
);
/* If the alternate name extension exists, the name it contains
* is bound to the certificate, so make sure the name matches
* it. Otherwise, look for the server name in the subject
* distinguished name. RFC5280, section 4.2.1.6:
* "Whenever such identities are to be bound into a
* certificate, the subject alternative name (or issuer
* alternative name) extension MUST be used; however, a DNS
* name MAY also be represented in the subject field using the
* domainComponent attribute."
*/
if
(
altNameExt
)
matches
=
match_dns_to_subject_alt_name
(
altNameExt
,
sslPara
->
pwszServerName
);
else
matches
=
match_dns_to_subject_dn
(
cert
,
sslPara
->
pwszServerName
);
if
(
!
matches
)
{
pPolicyStatus
->
dwError
=
CERT_E_CN_NO_MATCH
;
pPolicyStatus
->
lChainIndex
=
0
;
pPolicyStatus
->
lElementIndex
=
0
;
}
}
}
}
return
TRUE
;
}
static
BYTE
msPubKey1
[]
=
{
0x30
,
0x82
,
0x01
,
0x0a
,
0x02
,
0x82
,
0x01
,
0x01
,
0x00
,
0xdf
,
0x08
,
0xba
,
0xe3
,
0x3f
,
0x6e
,
0x64
,
0x9b
,
0xf5
,
0x89
,
0xaf
,
0x28
,
0x96
,
0x4a
,
0x07
,
0x8f
,
0x1b
,
0x2e
,
0x8b
,
0x3e
,
0x1d
,
...
...
@@ -2257,6 +2485,9 @@ BOOL WINAPI CertVerifyCertificateChainPolicy(LPCSTR szPolicyOID,
case
LOWORD
(
CERT_CHAIN_POLICY_AUTHENTICODE
):
verifyPolicy
=
verify_authenticode_policy
;
break
;
case
LOWORD
(
CERT_CHAIN_POLICY_SSL
):
verifyPolicy
=
verify_ssl_policy
;
break
;
case
LOWORD
(
CERT_CHAIN_POLICY_BASIC_CONSTRAINTS
):
verifyPolicy
=
verify_basic_constraints_policy
;
break
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment