static BOOL compare_crl_issued_for(PCCRL_CONTEXT pCrlContext, DWORD dwType, DWORD dwFlags, const void *pvPara) { const CRL_FIND_ISSUED_FOR_PARA *para = pvPara; BOOL ret; ret = CertCompareCertificateName(para->pIssuerCert->dwCertEncodingType, ¶->pIssuerCert->pCertInfo->Issuer, &pCrlContext->pCrlInfo->Issuer); return ret; }
static BOOL compare_crl_existing(PCCRL_CONTEXT pCrlContext, DWORD dwType, DWORD dwFlags, const void *pvPara) { BOOL ret; if (pvPara) { PCCRL_CONTEXT crl = pvPara; ret = CertCompareCertificateName(pCrlContext->dwCertEncodingType, &pCrlContext->pCrlInfo->Issuer, &crl->pCrlInfo->Issuer); } else ret = TRUE; return ret; }
/*********************************************************************** * TrustIsCertificateSelfSigned (WINTRUST.@) */ BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert ) { PCERT_EXTENSION ext; DWORD size; BOOL ret; TRACE("%p\n", cert); if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension))) { CERT_AUTHORITY_KEY_ID2_INFO *info; ret = CryptDecodeObjectEx(cert->dwCertEncodingType, X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, &info, &size); if (ret) { if (info->AuthorityCertIssuer.cAltEntry && info->AuthorityCertSerialNumber.cbData) { PCERT_ALT_NAME_ENTRY directoryName = NULL; DWORD i; for (i = 0; !directoryName && i < info->AuthorityCertIssuer.cAltEntry; i++) if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME) directoryName = &info->AuthorityCertIssuer.rgAltEntry[i]; if (directoryName) { ret = CertCompareCertificateName(cert->dwCertEncodingType, &directoryName->u.DirectoryName, &cert->pCertInfo->Issuer) && CertCompareIntegerBlob(&info->AuthorityCertSerialNumber, &cert->pCertInfo->SerialNumber); } else { FIXME("no supported name type in authority key id2\n"); ret = FALSE; } } else if (info->KeyId.cbData) { ret = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); if (ret && size == info->KeyId.cbData) { LPBYTE buf = CryptMemAlloc(size); if (buf) { CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, buf, &size); ret = !memcmp(buf, info->KeyId.pbData, size); CryptMemFree(buf); } else ret = FALSE; } else ret = FALSE; } LocalFree(info); } } else if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER, cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension))) { CERT_AUTHORITY_KEY_ID_INFO *info; ret = CryptDecodeObjectEx(cert->dwCertEncodingType, X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, &info, &size); if (ret) { if (info->CertIssuer.cbData && info->CertSerialNumber.cbData) { ret = CertCompareCertificateName(cert->dwCertEncodingType, &info->CertIssuer, &cert->pCertInfo->Issuer) && CertCompareIntegerBlob(&info->CertSerialNumber, &cert->pCertInfo->SerialNumber); } else if (info->KeyId.cbData) { ret = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); if (ret && size == info->KeyId.cbData) { LPBYTE buf = CryptMemAlloc(size); if (buf) { CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, buf, &size); ret = !memcmp(buf, info->KeyId.pbData, size); CryptMemFree(buf); } else ret = FALSE; } else ret = FALSE; } else ret = FALSE; LocalFree(info); } } else ret = CertCompareCertificateName(cert->dwCertEncodingType, &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer); return ret; }
static BOOL compare_crl_issued_by(PCCRL_CONTEXT pCrlContext, DWORD dwType, DWORD dwFlags, const void *pvPara) { BOOL ret; if (pvPara) { PCCERT_CONTEXT issuer = pvPara; ret = CertCompareCertificateName(issuer->dwCertEncodingType, &issuer->pCertInfo->Subject, &pCrlContext->pCrlInfo->Issuer); if (ret && (dwFlags & CRL_FIND_ISSUED_BY_SIGNATURE_FLAG)) ret = CryptVerifyCertificateSignatureEx(0, issuer->dwCertEncodingType, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL, (void *)pCrlContext, CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)issuer, 0, NULL); if (ret && (dwFlags & CRL_FIND_ISSUED_BY_AKI_FLAG)) { PCERT_EXTENSION ext = CertFindExtension( szOID_AUTHORITY_KEY_IDENTIFIER2, pCrlContext->pCrlInfo->cExtension, pCrlContext->pCrlInfo->rgExtension); if (ext) { CERT_AUTHORITY_KEY_ID2_INFO *info; DWORD size; if ((ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) { if (info->AuthorityCertIssuer.cAltEntry && info->AuthorityCertSerialNumber.cbData) { PCERT_ALT_NAME_ENTRY directoryName = NULL; DWORD i; for (i = 0; !directoryName && i < info->AuthorityCertIssuer.cAltEntry; i++) if (info->AuthorityCertIssuer.rgAltEntry[i]. dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME) directoryName = &info->AuthorityCertIssuer.rgAltEntry[i]; if (directoryName) { ret = CertCompareCertificateName( issuer->dwCertEncodingType, &issuer->pCertInfo->Subject, &directoryName->u.DirectoryName); if (ret) ret = CertCompareIntegerBlob( &issuer->pCertInfo->SerialNumber, &info->AuthorityCertSerialNumber); } else { FIXME("no supported name type in authority key id2\n"); ret = FALSE; } } else if (info->KeyId.cbData) { DWORD size; ret = CertGetCertificateContextProperty(issuer, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); if (ret && size == info->KeyId.cbData) { LPBYTE buf = CryptMemAlloc(size); if (buf) { CertGetCertificateContextProperty(issuer, CERT_KEY_IDENTIFIER_PROP_ID, buf, &size); ret = !memcmp(buf, info->KeyId.pbData, size); CryptMemFree(buf); } else ret = FALSE; } else ret = FALSE; } else { FIXME("unsupported value for AKI extension\n"); ret = FALSE; } LocalFree(info); } } /* else: a CRL without an AKI matches any cert */ } } else ret = TRUE; return ret; }
// Select, and return a handle to a server certificate located by name // Usually used for a best guess at a certificate to be used as the SSL certificate for a server SECURITY_STATUS CertFindServerByName(PCCERT_CONTEXT & pCertContext, LPCTSTR pszSubjectName, boolean fUserStore) { HCERTSTORE hMyCertStore = NULL; TCHAR pszFriendlyNameString[128]; TCHAR pszNameString[128]; if (pszSubjectName == NULL || _tcslen(pszSubjectName) == 0) { DebugMsg("**** No subject name specified!"); return E_POINTER; } if (fUserStore) hMyCertStore = CertOpenSystemStore(NULL, _T("MY")); else { // Open the local machine certificate store. hMyCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING, NULL, CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY"); } if (!hMyCertStore) { int err = GetLastError(); if (err == ERROR_ACCESS_DENIED) DebugMsg("**** CertOpenStore failed with 'access denied'"); else DebugMsg("**** Error %d returned by CertOpenStore", err); return HRESULT_FROM_WIN32(err); } if (pCertContext) // The caller passed in a certificate context we no longer need, so free it CertFreeCertificateContext(pCertContext); pCertContext = NULL; char * serverauth = szOID_PKIX_KP_SERVER_AUTH; CERT_ENHKEY_USAGE eku; PCCERT_CONTEXT pCertContextSaved = NULL; eku.cUsageIdentifier = 1; eku.rgpszUsageIdentifier = &serverauth; // Find a server certificate. Note that this code just searches for a // certificate that has the required enhanced key usage for server authentication // it then selects the best one (ideally one that contains the server name // in the subject name). while (NULL != (pCertContext = CertFindCertificateInStore(hMyCertStore, X509_ASN_ENCODING, CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG, CERT_FIND_ENHKEY_USAGE, &eku, pCertContext))) { //ShowCertInfo(pCertContext); if (!CertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszFriendlyNameString, sizeof(pszFriendlyNameString))) { DebugMsg("CertGetNameString failed getting friendly name."); continue; } DebugMsg("Certificate '%S' is allowed to be used for server authentication.", ATL::CT2W(pszFriendlyNameString)); if (!CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, sizeof(pszNameString))) DebugMsg("CertGetNameString failed getting subject name."); else if (_tcscmp(pszNameString, pszSubjectName)) DebugMsg("Certificate has wrong subject name."); else if (CertCompareCertificateName(X509_ASN_ENCODING, &pCertContext->pCertInfo->Subject, &pCertContext->pCertInfo->Issuer)) { if (!pCertContextSaved) { DebugMsg("A self-signed certificate was found and saved in case it is needed."); pCertContextSaved = CertDuplicateCertificateContext(pCertContext); } } else { DebugMsg("Certificate is acceptable."); if (pCertContextSaved) // We have a saved self signed certificate context we no longer need, so free it CertFreeCertificateContext(pCertContextSaved); pCertContextSaved = NULL; break; } } if (pCertContextSaved && !pCertContext) { // We have a saved self-signed certificate and nothing better DebugMsg("A self-signed certificate was the best we had."); pCertContext = pCertContextSaved; pCertContextSaved = NULL; } if (!pCertContext) { DWORD LastError = GetLastError(); if (LastError == CRYPT_E_NOT_FOUND) { DebugMsg("**** CertFindCertificateInStore did not find a certificate, creating one"); pCertContext = CreateCertificate(true, pszSubjectName); if (!pCertContext) { LastError = GetLastError(); DebugMsg("**** Error 0x%x returned by CreateCertificate", LastError); std::cout << "Could not create certificate, are you running as administrator?" << std::endl; return HRESULT_FROM_WIN32(LastError); } } else { DebugMsg("**** Error 0x%x returned by CertFindCertificateInStore", LastError); return HRESULT_FROM_WIN32(LastError); } } return SEC_E_OK; }