1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013-2017 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #pragma comment(lib, "Crypt32.lib")
23 static DWORD
VerifyServerCertificate(PCCERT_CONTEXT pServerCert
, PTSTR pwszServerName
, DWORD dwCertFlags
)
25 if (pServerCert
== nullptr || pwszServerName
== nullptr)
26 return (DWORD
)SEC_E_WRONG_PRINCIPAL
;
28 LPSTR rgszUsages
[] = { szOID_PKIX_KP_SERVER_AUTH
, szOID_SERVER_GATED_CRYPTO
, szOID_SGC_NETSCAPE
};
29 DWORD cUsages
= sizeof(rgszUsages
) / sizeof(LPSTR
);
31 // Build certificate chain.
32 CERT_CHAIN_PARA ChainPara
= { 0 };
33 ChainPara
.cbSize
= sizeof(ChainPara
);
34 ChainPara
.RequestedUsage
.dwType
= USAGE_MATCH_TYPE_OR
;
35 ChainPara
.RequestedUsage
.Usage
.cUsageIdentifier
= cUsages
;
36 ChainPara
.RequestedUsage
.Usage
.rgpszUsageIdentifier
= rgszUsages
;
38 PCCERT_CHAIN_CONTEXT pChainContext
= nullptr;
39 if (!CertGetCertificateChain(nullptr, pServerCert
, nullptr, pServerCert
->hCertStore
, &ChainPara
, CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
, nullptr, &pChainContext
))
40 return GetLastError();
41 SCOPE_EXIT
{ CertFreeCertificateChain(pChainContext
); };
43 // Validate certificate chain.
44 HTTPSPolicyCallbackData polHttps
= { 0 };
45 polHttps
.cbStruct
= sizeof(HTTPSPolicyCallbackData
);
46 polHttps
.dwAuthType
= AUTHTYPE_SERVER
;
47 polHttps
.fdwChecks
= dwCertFlags
;
48 polHttps
.pwszServerName
= pwszServerName
;
50 CERT_CHAIN_POLICY_PARA PolicyPara
= { 0 };
51 PolicyPara
.cbSize
= sizeof(PolicyPara
);
52 PolicyPara
.pvExtraPolicyPara
= &polHttps
;
54 CERT_CHAIN_POLICY_STATUS PolicyStatus
= { 0 };
55 PolicyStatus
.cbSize
= sizeof(PolicyStatus
);
57 if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL
, pChainContext
, &PolicyPara
, &PolicyStatus
))
58 return GetLastError();
60 if (PolicyStatus
.dwError
)
61 return PolicyStatus
.dwError
;