[cpp-sp] 05/05: Start to hack away at cert checking
Rod Widdowson
rdw at steadingsoftware.com
Wed May 7 13:14:03 UTC 2025
This is an automated email from the git hooks/post-receive script.
rdw pushed a commit to branch dev/SPPSP-8-playpen
in repository cpp-sp.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=29c94863db8b550f2cd4fbd283423351a470c7ec
commit 29c94863db8b550f2cd4fbd283423351a470c7ec
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Wed May 7 14:11:31 2025 +0100
Start to hack away at cert checking
---
Projects/WinHttpProject/WinHttpProject.cpp | 165 +++++++++++++++++++--
Projects/WinHttpProject/WinHttpProject.vcxproj | 5 +
.../WinHttpProject/WinHttpProject.vcxproj.filters | 5 +
3 files changed, 160 insertions(+), 15 deletions(-)
diff --git a/Projects/WinHttpProject/WinHttpProject.cpp b/Projects/WinHttpProject/WinHttpProject.cpp
index 63ad25ee..a3cacdd0 100644
--- a/Projects/WinHttpProject/WinHttpProject.cpp
+++ b/Projects/WinHttpProject/WinHttpProject.cpp
@@ -11,6 +11,44 @@ using namespace std;
//static WINHTTP_STATUS_CALLBACK Callback;
+HCERTCHAINENGINE engine = NULL;
+HCERTSTORE certStore;
+
+static
+BOOLEAN
+CheckCertCtx(PCCERT_CONTEXT context) {
+
+ PCCERT_CONTEXT outCtx
+
+ = CertFindCertificateInStore(certStore, X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, context, NULL);
+/*
+// if (!CertGetCertificateChain(engine, context, NULL, context->hCertStore, &chainPara, 0, // No revocation checking
+// if (!CertGetCertificateChain(NULL, context, NULL, context->hCertStore, &chainPara, 0, // No revocation checking
+ if (!CertGetCertificateChain(NULL, context, NULL, certStore, &chainPara, 0, // No revocation checking
+ NULL, &chainContext)) {
+ cout << "CertGetCertificateChain failed " << GetLastError() << endl;
+
+ return FALSE;
+ }
+
+ CERT_SIMPLE_CHAIN* pSimpleChain = chainContext->rgpChain[0];
+ DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
+ dwTrustErrorMask = pSimpleChain->TrustStatus.dwErrorStatus;
+ CertFreeCertificateChain(chainContext);
+
+ if (dwTrustErrorMask) {
+
+ cout << "TrustError Mask: 0x" << hex << dwTrustErrorMask << endl;
+
+ return FALSE;
+
+ }
+ */
+ return TRUE;
+}
+
+
+
static void Callback(
HINTERNET hInternet,
DWORD_PTR dwContext,
@@ -18,20 +56,26 @@ static void Callback(
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
- PCCERT_CONTEXT pCert = NULL;
- DWORD dwSize = sizeof(pCert);
+ PCCERT_CONTEXT pCertCtx = NULL;
+ DWORD dwSize = sizeof(pCertCtx);
cout << "Handle " << hex << hInternet <<endl;
cout << "Context " << dec << dwContext << endl;
switch (dwInternetStatus) {
case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST:
wcout << L"Sending Request (" << dwInternetStatus << L") " << endl;
- if (!WinHttpQueryOption(hInternet, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &pCert, &dwSize)) {
+ if (!WinHttpQueryOption(hInternet, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &pCertCtx, &dwSize)) {
cout << "Gack " << GetLastError() << endl;
} else {
CHAR buffer[1024];
- CertNameToStrA(X509_ASN_ENCODING, &pCert->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, buffer, sizeof(buffer));
+ CertNameToStrA(X509_ASN_ENCODING, &pCertCtx->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, buffer, sizeof(buffer));
cout << "Subject name " << buffer << endl;
- CertFreeCertificateContext(pCert);
+
+ if (!CheckCertCtx(pCertCtx)) {
+ cout << "Check Failed" << endl;
+ }
+
+
+ CertFreeCertificateContext(pCertCtx);
}
break;
@@ -64,9 +108,105 @@ Utf8ToUtf16(string InputString) {
return result;
}
+//
+// Certificate checking
+// I spelunked the curl code and there are some cute tricks but effectively
+//
+// Suck the cert file into memory
+//
+// Create an in Memory Certificate store(HCERTSTORE) using CertOpenStore with a provider CERT_STORE_PROV_MEMORY
+//
+// This should probably be a private field and be torn down
+//
+// Suck the cerificate into the cert store(CryptQueryObject then CertAddCertificateContextToStore)
+//
+// plug the HCERTSTORE into a CERT_CHAIN_ENGINE_CONFIG and plug that into CertCreateCertificateChainEngine to get a HCERTENGINE
+//
+// Also a private filed, also torn down
+//
+// Then call CertGetCertificateChain with the PCCERT_CONTEXT we get inside our worker method.
+//
+// Documentation for the above all starts https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/
+
+static
+void enumerateStore(HCERTSTORE store) {
+
+ PCCERT_CONTEXT cert = CertEnumCertificatesInStore(store, NULL);
+
+ cout << "CERT STORE\n";
+ while (cert) {
+ CHAR buffer[1024];
+ CertNameToStrA(X509_ASN_ENCODING, &cert->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, buffer, sizeof(buffer));
+ cout << "\t Subject name " << buffer << endl;
+ cert = CertEnumCertificatesInStore(store, cert);
+ }
+}
int main()
{
+ DWORD msgAndCertEncodingType, contentType, formatType;
+ PCERT_CONTEXT certContext = NULL;
+
+ if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
+ L"V:\\perforce\\SP\\cpp-sp\\Projects\\WinHttpProject\\shib.cert",
+ // L"V:\\perforce\\SP\\cpp-sp\\tests\\data\\remoting\\impl\\trustfile.pem",
+ CERT_QUERY_CONTENT_FLAG_CERT,
+ CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED,
+ 0,
+ &msgAndCertEncodingType,
+ &contentType,
+ &formatType,
+ NULL,
+ NULL,
+ (void const**) &certContext)) {
+
+ cerr << "CryptQueryObject failed 0x" << hex << GetLastError() << endl ;
+ return 1;
+ }
+{
+ CHAR buffer[1024];
+ CertNameToStrA(X509_ASN_ENCODING, &certContext->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, buffer, sizeof(buffer));
+ cout << "Subject name " << buffer << endl;
+}
+
+ if ((msgAndCertEncodingType != X509_ASN_ENCODING) ||
+ (contentType != CERT_QUERY_CONTENT_CERT) ||
+ (formatType != CERT_QUERY_FORMAT_BASE64_ENCODED)) {
+
+ cerr << "CryptQueryObject unexpected input. Encoding: 0x" << hex << msgAndCertEncodingType <<
+ ", context: 0x" << contentType <<
+ ", format: 0x" << formatType << endl;
+ }
+
+ certStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, NULL);
+
+ if (certStore == NULL) {
+
+ cerr << "CertOpenStore failed 0x" << hex << GetLastError() << endl;
+ return 1;
+ }
+ enumerateStore(certStore);
+
+ if (!CertAddCertificateContextToStore(certStore, certContext, CERT_STORE_ADD_ALWAYS, NULL)) {
+
+ cerr << "CertAddCertificateContextToStore failed 0x" << hex << GetLastError() << endl;
+ return 1;
+ }
+ enumerateStore(certStore);
+ CertFreeCertificateContext(certContext);
+ enumerateStore(certStore);
+
+ CERT_CHAIN_ENGINE_CONFIG cfg = {0};
+ cfg.cbSize = sizeof(cfg);
+ cfg.hExclusiveRoot = certStore;
+
+ if (!CertCreateCertificateChainEngine(&cfg, &engine)) {
+
+ cerr << "CertCreateCertificateChainEngine failed 0x" << hex << GetLastError() << endl;
+ return 1;
+ }
+
+
string url("https://shibboleth.net/downloads/PGP_KEYS");
wstring wUrl(Utf8ToUtf16(url));
@@ -171,15 +311,10 @@ int main()
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
-}
+ enumerateStore(certStore);
-// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
-// Debug program: F5 or Debug > Start Debugging menu
+ if (certStore) CertCloseStore(certStore, 0);
+ if (engine) CertFreeCertificateChainEngine(engine);
+
+}
-// Tips for Getting Started:
-// 1. Use the Solution Explorer window to add/manage files
-// 2. Use the Team Explorer window to connect to source control
-// 3. Use the Output window to see build output and other messages
-// 4. Use the Error List window to view errors
-// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
-// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file
diff --git a/Projects/WinHttpProject/WinHttpProject.vcxproj b/Projects/WinHttpProject/WinHttpProject.vcxproj
index f5c04f71..964559b2 100644
--- a/Projects/WinHttpProject/WinHttpProject.vcxproj
+++ b/Projects/WinHttpProject/WinHttpProject.vcxproj
@@ -131,6 +131,11 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClInclude Include="..\..\..\curl\lib\vtls\schannel_verify.c">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">USE_SCHANNEL=1;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FileType>CppCode</FileType>
+ </ClInclude>
<ClCompile Include="WinHttpProject.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/Projects/WinHttpProject/WinHttpProject.vcxproj.filters b/Projects/WinHttpProject/WinHttpProject.vcxproj.filters
index aa36c5af..92142e1a 100644
--- a/Projects/WinHttpProject/WinHttpProject.vcxproj.filters
+++ b/Projects/WinHttpProject/WinHttpProject.vcxproj.filters
@@ -19,4 +19,9 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\curl\lib\vtls\schannel_verify.c">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project>
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list