DWORD WINAPI CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, LPSTR pszNameString, DWORD cchNameString) { DWORD ret; TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType, dwFlags, pvTypePara, pszNameString, cchNameString); if (pszNameString) { LPWSTR wideName; DWORD nameLen; nameLen = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0); wideName = CryptMemAlloc(nameLen * sizeof(WCHAR)); if (wideName) { CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, wideName, nameLen); nameLen = WideCharToMultiByte(CP_ACP, 0, wideName, nameLen, pszNameString, cchNameString, NULL, NULL); if (nameLen <= cchNameString) ret = nameLen; else { pszNameString[cchNameString - 1] = '\0'; ret = cchNameString; } CryptMemFree(wideName); } else { *pszNameString = '\0'; ret = 1; } } else ret = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0); return ret; }
/*********************************************************************** * GetFriendlyNameOfCertW (CRYPTDLG.@) */ DWORD WINAPI GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert, LPWSTR pchBuffer, DWORD cchBuffer) { return CertGetNameStringW(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pchBuffer, cchBuffer); }
// // Retrieve the thumbprint of the certificate // DWORD GetCertificate(IN WCHAR* pwcTrustRootCA, IN PBYTE pbCertHash, IN DWORD* pcbCertHash) { HCERTSTORE hCertStore; WCHAR *pwcSubjectName; DWORD cwcSubjectName; PBYTE pbSHA1; DWORD cbSHA1; PCCERT_CONTEXT pCertContext = NULL; DWORD dwRet; dwRet = NO_ERROR; if( ( hCertStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, ( HCRYPTPROV ) NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"ROOT" ) ) ) { BOOL bFoundCert = FALSE; while( ( pCertContext = CertEnumCertificatesInStore( hCertStore, pCertContext ) ) && bFoundCert == FALSE ) { if( ( cwcSubjectName = CertGetNameString( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0 ) ) > 0 ) { if( ( pwcSubjectName = ( WCHAR* ) malloc( cwcSubjectName * sizeof( WCHAR ) ) ) ) { if( CertGetNameStringW( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pwcSubjectName, cwcSubjectName ) > 0 ) { //printf("Found the certificate [%ws] in the system store\n", pwcSubjectName); if ( wcscmp(pwcTrustRootCA, pwcSubjectName) == 0) { bFoundCert = TRUE; // Retrieve information on the property by first getting the property size. if(CertGetCertificateContextProperty( pCertContext, CERT_SHA1_HASH_PROP_ID , // work fine on XP NULL, &cbSHA1)) { // Use the size to allocate the memory for the property if ( pbSHA1 = (BYTE *) malloc(cbSHA1 * sizeof(BYTE) ) ) { // Retrieve HASH of the certificate if(CertGetCertificateContextProperty( pCertContext, CERT_SHA1_HASH_PROP_ID , pbSHA1, &cbSHA1)) { memcpy(pbCertHash, pbSHA1, cbSHA1); *pcbCertHash = cbSHA1; } else { printf("->GetCertificate :: Error retrieving certificate HASH.\n"); dwRet = ERROR_CANTOPEN; } free(pbSHA1); } else { printf("->GetCertificate :: Error allocating memory.\n"); dwRet = ERROR_NOT_ENOUGH_MEMORY; } } else { printf("->GetCertificate :: Error getting certificate property.\n"); dwRet = ERROR_CANTOPEN; } } } else { printf("->GetCertificate :: Error getting certificate name string.\n"); dwRet = ERROR_CANTOPEN; } free( pwcSubjectName ); cwcSubjectName = 0; } else { printf("->GetCertificate :: Error allocating memory.\n"); dwRet = ERROR_NOT_ENOUGH_MEMORY; } } else dwRet = ERROR_CANTOPEN; } if( !bFoundCert ) { printf("->GetCertificate :: Error looking for the certificate in the system store.\n"); dwRet = ERROR_CANTOPEN; } if( dwRet != NO_ERROR ) { if( pCertContext ) CertFreeCertificateContext( pCertContext ); } CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ); } else { printf("->GetCertificate :: Error opening system store.\n"); dwRet = ERROR_CANTOPEN; } return dwRet; }
static BOOL IsTrustedPublisherName( PCCERT_CHAIN_CONTEXT pChainContext ) { PCERT_SIMPLE_CHAIN pChain; PCCERT_CONTEXT pCertContext; // // Get the publisher's certificate from the chain context // pChain = pChainContext->rgpChain[0]; pCertContext = pChain->rgpElement[0]->pCertContext; // // Loop through the list of publisher subject names to be matched // for (DWORD i = 0; i < PUBLISHER_NAME_LIST_CNT; i++) { BOOL trusted = TRUE; // // Loop through the subject name attributes to be matched. // For example, O= ; L= ; S= ; C= ; // for (DWORD j = 0; trusted && j < PUBLISHER_ATTR_CNT; j++) { LPWSTR AttrString = NULL; DWORD AttrStringLength; // // First pass call to get the length of the subject name attribute. // Note, the returned length includes the NULL terminator. // AttrStringLength = CertGetNameStringW( pCertContext, CERT_NAME_ATTR_TYPE, 0, // dwFlags (void *) PublisherAttributeObjId[j], NULL, // AttrString 0); // AttrStringLength if (AttrStringLength <= 1) { // // A matching certificate must have all of the attributes // return FALSE; } AttrString = (LPWSTR) LocalAlloc( LPTR, AttrStringLength * sizeof(WCHAR)); if (AttrString == NULL) { return FALSE; } // // Second pass call to get the subject name attribute // AttrStringLength = CertGetNameStringW( pCertContext, CERT_NAME_ATTR_TYPE, 0, // dwFlags (void *) PublisherAttributeObjId[j], AttrString, AttrStringLength); if (AttrStringLength <= 1 || 0 != wcscmp(AttrString, PublisherNameList[i][j])) { // The subject name attribute doesn't match trusted = FALSE; } LocalFree(AttrString); } if (trusted) { // All the subject name attributes match return TRUE; } } return FALSE; }
/** * Worker for cmdDisplayAll. */ static BOOL WINAPI displaySystemStoreCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg) { if (g_cVerbosityLevel > 1) RTPrintf(" pvSystemStore=%p dwFlags=%#x pStoreInfo=%p pvReserved=%p\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved); LPCWSTR pwszStoreNm = NULL; if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) { const CERT_SYSTEM_STORE_RELOCATE_PARA *pRelPara = (const CERT_SYSTEM_STORE_RELOCATE_PARA *)pvSystemStore; pwszStoreNm = pRelPara->pwszSystemStore; RTPrintf(" %#010x '%ls' hKeyBase=%p\n", dwFlags, pwszStoreNm, pRelPara->hKeyBase); } else { pwszStoreNm = (LPCWSTR)pvSystemStore; RTPrintf(" %#010x '%ls'\n", dwFlags, pwszStoreNm); } /* * Open the store and list the certificates within. */ DWORD dwDst = (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK); HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, NULL /* hCryptProv = default */, dwDst | CERT_STORE_OPEN_EXISTING_FLAG, pwszStoreNm); if (hStore) { PCCERT_CONTEXT pCertCtx = NULL; while ((pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) != NULL) { if (g_cVerbosityLevel > 1) RTPrintf(" pCertCtx=%p dwCertEncodingType=%#x cbCertEncoded=%#x pCertInfo=%p\n", pCertCtx, pCertCtx->dwCertEncodingType, pCertCtx->cbCertEncoded, pCertCtx->pCertInfo); WCHAR wszName[1024]; if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/, wszName, sizeof(wszName))) { RTPrintf(" '%ls'\n", wszName); if (pCertCtx->pCertInfo) { RTTIMESPEC TmpTS; char szNotBefore[80]; RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotBefore), szNotBefore, sizeof(szNotBefore)); char szNotAfter[80]; RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotAfter), szNotAfter, sizeof(szNotAfter)); RTPrintf(" NotBefore='%s'\n", szNotBefore); RTPrintf(" NotAfter ='%s'\n", szNotAfter); if (pCertCtx->pCertInfo->Issuer.cbData) { if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL /*pvTypePara*/, wszName, sizeof(wszName))) RTPrintf(" Issuer='%ls'\n", wszName); else RTMsgError("CertGetNameStringW(Issuer) failed: %s\n", errorToString(GetLastError())); } } } else RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError())); } CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG); } else RTMsgError("CertOpenStore failed opening %#x:'%ls': %s\n", dwDst, pwszStoreNm, errorToString(GetLastError())); return TRUE; }
/** * Removes a certificate, given by file, from a store * * @returns true on success, false on failure (error message written). * @param dwDst The destination, like * CERT_SYSTEM_STORE_LOCAL_MACHINE or * ERT_SYSTEM_STORE_CURRENT_USER. * @param pszStoreNm The store name. * @param pszCertFile The file containing the certificate to add. */ static bool removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile) { /* * Read the certificate file first. */ PCCERT_CONTEXT pSrcCtx = NULL; HCERTSTORE hSrcStore = NULL; if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore)) return false; WCHAR wszName[1024]; if (!CertGetNameStringW(pSrcCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/, wszName, sizeof(wszName))) { RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError())); wszName[0] = '\0'; } /* * Open the destination store. */ bool fRc = false; HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm); if (hDstStore) { if (pSrcCtx) { fRc = true; unsigned cDeleted = 0; PCCERT_CONTEXT pCurCtx = NULL; while ((pCurCtx = CertEnumCertificatesInStore(hDstStore, pCurCtx)) != NULL) { if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pCurCtx->pCertInfo, pSrcCtx->pCertInfo)) { if (g_cVerbosityLevel > 1) RTMsgInfo("Removing '%ls'...", wszName); PCCERT_CONTEXT pDeleteCtx = CertDuplicateCertificateContext(pCurCtx); if (pDeleteCtx) { if (CertDeleteCertificateFromStore(pDeleteCtx)) cDeleted++; else RTMsgError("CertDeleteFromStore('%ls') failed: %s\n", wszName, errorToString(GetLastError())); } else RTMsgError("CertDuplicateCertificateContext('%ls') failed: %s\n", wszName, errorToString(GetLastError())); } } if (!cDeleted) RTMsgInfo("Found no matching certificates to remove."); } else { RTMsgError("Path not implemented at line %d\n", __LINE__); } CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG); } if (pSrcCtx) CertFreeCertificateContext(pSrcCtx); if (hSrcStore) CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG); return fRc; }
DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString) { DWORD ret; PCERT_NAME_BLOB name; LPCSTR altNameOID; TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType, dwFlags, pvTypePara, pszNameString, cchNameString); if (dwFlags & CERT_NAME_ISSUER_FLAG) { name = &pCertContext->pCertInfo->Issuer; altNameOID = szOID_ISSUER_ALT_NAME; } else { name = &pCertContext->pCertInfo->Subject; altNameOID = szOID_SUBJECT_ALT_NAME; } switch (dwType) { case CERT_NAME_SIMPLE_DISPLAY_TYPE: { static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME, szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME, szOID_RSA_emailAddr }; CERT_NAME_INFO *info = NULL; PCERT_RDN_ATTR nameAttr = NULL; DWORD bytes = 0, i; if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME, name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes)) { for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) / sizeof(simpleAttributeOIDs[0]); i++) nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info); } else ret = 0; if (!nameAttr) { PCERT_EXTENSION ext = CertFindExtension(altNameOID, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension); if (ext) { for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) / sizeof(simpleAttributeOIDs[0]); i++) nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info); if (!nameAttr) { /* FIXME: gotta then look for a rfc822Name choice in ext. * Failing that, look for the first attribute. */ FIXME("CERT_NAME_SIMPLE_DISPLAY_TYPE: stub\n"); ret = 0; } } } ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value, pszNameString, cchNameString); if (info) LocalFree(info); break; } case CERT_NAME_FRIENDLY_DISPLAY_TYPE: { DWORD cch = cchNameString; if (CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch)) ret = cch; else ret = CertGetNameStringW(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString, cchNameString); break; } default: FIXME("unimplemented for type %ld\n", dwType); ret = 0; } return ret; }
DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString) { DWORD ret = 0; PCERT_NAME_BLOB name; LPCSTR altNameOID; TRACE("(%p, %d, %08x, %p, %p, %d)\n", pCertContext, dwType, dwFlags, pvTypePara, pszNameString, cchNameString); if (dwFlags & CERT_NAME_ISSUER_FLAG) { name = &pCertContext->pCertInfo->Issuer; altNameOID = szOID_ISSUER_ALT_NAME; } else { name = &pCertContext->pCertInfo->Subject; altNameOID = szOID_SUBJECT_ALT_NAME; } switch (dwType) { case CERT_NAME_EMAIL_TYPE: { CERT_ALT_NAME_INFO *info; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_RFC822_NAME, &info); if (entry) { if (!pszNameString) ret = strlenW(entry->u.pwszRfc822Name) + 1; else if (cchNameString) { ret = min(strlenW(entry->u.pwszRfc822Name), cchNameString - 1); memcpy(pszNameString, entry->u.pwszRfc822Name, ret * sizeof(WCHAR)); pszNameString[ret++] = 0; } } if (info) LocalFree(info); if (!ret) ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, name, szOID_RSA_emailAddr, pszNameString, cchNameString); break; } case CERT_NAME_RDN_TYPE: if (name->cbData) ret = CertNameToStrW(pCertContext->dwCertEncodingType, name, *(DWORD *)pvTypePara, pszNameString, cchNameString); else { CERT_ALT_NAME_INFO *info; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_DIRECTORY_NAME, &info); if (entry) ret = CertNameToStrW(pCertContext->dwCertEncodingType, &entry->u.DirectoryName, *(DWORD *)pvTypePara, pszNameString, cchNameString); if (info) LocalFree(info); } break; case CERT_NAME_ATTR_TYPE: ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, name, pvTypePara, pszNameString, cchNameString); if (!ret) { CERT_ALT_NAME_INFO *altInfo; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_DIRECTORY_NAME, &altInfo); if (entry) ret = cert_name_to_str_with_indent(X509_ASN_ENCODING, 0, &entry->u.DirectoryName, 0, pszNameString, cchNameString); if (altInfo) LocalFree(altInfo); } break; case CERT_NAME_SIMPLE_DISPLAY_TYPE: { static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME, szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME, szOID_RSA_emailAddr }; CERT_NAME_INFO *nameInfo = NULL; DWORD bytes = 0, i; if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME, name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo, &bytes)) { PCERT_RDN_ATTR nameAttr = NULL; for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) / sizeof(simpleAttributeOIDs[0]); i++) nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], nameInfo); if (nameAttr) ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value, pszNameString, cchNameString); LocalFree(nameInfo); } if (!ret) { CERT_ALT_NAME_INFO *altInfo; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_RFC822_NAME, &altInfo); if (altInfo) { if (!entry && altInfo->cAltEntry) entry = &altInfo->rgAltEntry[0]; if (entry) { if (!pszNameString) ret = strlenW(entry->u.pwszRfc822Name) + 1; else if (cchNameString) { ret = min(strlenW(entry->u.pwszRfc822Name), cchNameString - 1); memcpy(pszNameString, entry->u.pwszRfc822Name, ret * sizeof(WCHAR)); pszNameString[ret++] = 0; } } LocalFree(altInfo); } } break; } case CERT_NAME_FRIENDLY_DISPLAY_TYPE: { DWORD cch = cchNameString; if (CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch)) ret = cch; else ret = CertGetNameStringW(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString, cchNameString); break; } case CERT_NAME_DNS_TYPE: { CERT_ALT_NAME_INFO *info; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_DNS_NAME, &info); if (entry) { if (!pszNameString) ret = strlenW(entry->u.pwszDNSName) + 1; else if (cchNameString) { ret = min(strlenW(entry->u.pwszDNSName), cchNameString - 1); memcpy(pszNameString, entry->u.pwszDNSName, ret * sizeof(WCHAR)); pszNameString[ret++] = 0; } } if (info) LocalFree(info); if (!ret) ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, name, szOID_COMMON_NAME, pszNameString, cchNameString); break; } case CERT_NAME_URL_TYPE: { CERT_ALT_NAME_INFO *info; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_URL, &info); if (entry) { if (!pszNameString) ret = strlenW(entry->u.pwszURL) + 1; else if (cchNameString) { ret = min(strlenW(entry->u.pwszURL), cchNameString - 1); memcpy(pszNameString, entry->u.pwszURL, ret * sizeof(WCHAR)); pszNameString[ret++] = 0; } } if (info) LocalFree(info); break; } default: FIXME("unimplemented for type %d\n", dwType); ret = 0; } if (!ret) { if (!pszNameString) ret = 1; else if (cchNameString) { pszNameString[0] = 0; ret = 1; } } return ret; }
static CURLcode verify_certificate(struct connectdata *conn, int sockindex) { SECURITY_STATUS status; struct SessionHandle *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CURLcode result = CURLE_OK; CERT_CONTEXT *pCertContextServer = NULL; const CERT_CHAIN_CONTEXT *pChainContext = NULL; status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &pCertContextServer); if((status != SEC_E_OK) || (pCertContextServer == NULL)) { failf(data, "schannel: Failed to read remote certificate context: %s", Curl_sspi_strerror(conn, status)); result = CURLE_PEER_FAILED_VERIFICATION; } if(result == CURLE_OK) { CERT_CHAIN_PARA ChainPara; memset(&ChainPara, 0, sizeof(ChainPara)); ChainPara.cbSize = sizeof(ChainPara); if(!CertGetCertificateChain(NULL, pCertContextServer, NULL, pCertContextServer->hCertStore, &ChainPara, 0, NULL, &pChainContext)) { failf(data, "schannel: CertGetCertificateChain failed: %s", Curl_sspi_strerror(conn, GetLastError())); pChainContext = NULL; result = CURLE_PEER_FAILED_VERIFICATION; } if(result == CURLE_OK) { CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0]; DWORD dwTrustErrorMask = ~(CERT_TRUST_IS_NOT_TIME_NESTED| CERT_TRUST_REVOCATION_STATUS_UNKNOWN); dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; if(dwTrustErrorMask) { if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN) failf(data, "schannel: CertGetCertificateChain trust error" " CERT_TRUST_IS_PARTIAL_CHAIN"); if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT) failf(data, "schannel: CertGetCertificateChain trust error" " CERT_TRUST_IS_UNTRUSTED_ROOT"); if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID) failf(data, "schannel: CertGetCertificateChain trust error" " CERT_TRUST_IS_NOT_TIME_VALID"); failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x", dwTrustErrorMask); result = CURLE_PEER_FAILED_VERIFICATION; } } } if(result == CURLE_OK) { if(data->set.ssl.verifyhost == 1) { infof(data, "warning: ignoring unsupported value (1) ssl.verifyhost\n"); } else if(data->set.ssl.verifyhost == 2) { WCHAR cert_hostname[128]; WCHAR *hostname = Curl_convert_UTF8_to_wchar(conn->host.name); DWORD len; len = CertGetNameStringW(pCertContextServer, CERT_NAME_DNS_TYPE, 0, NULL, cert_hostname, 128); if(len > 0 && cert_hostname[0] == '*') { /* this is a wildcard cert. try matching the last len - 1 chars */ int hostname_len = strlen(conn->host.name); if(wcsicmp(cert_hostname + 1, hostname + hostname_len - len + 2) != 0) result = CURLE_PEER_FAILED_VERIFICATION; } else if(len == 0 || wcsicmp(hostname, cert_hostname) != 0) { result = CURLE_PEER_FAILED_VERIFICATION; } if(result == CURLE_PEER_FAILED_VERIFICATION) { const char *_cert_hostname; _cert_hostname = Curl_convert_wchar_to_UTF8(cert_hostname); failf(data, "schannel: CertGetNameString() certificate hostname " "(%s) did not match connection (%s)", _cert_hostname, conn->host.name); Curl_safefree((void *)_cert_hostname); } Curl_safefree(hostname); } } if(pChainContext) CertFreeCertificateChain(pChainContext); if(pCertContextServer) CertFreeCertificateContext(pCertContextServer); return result; }
/** * Checks to see if a file stored at filePath matches the specified info. * * @param certContext The certificate context of the file * @param infoToMatch The acceptable information to match * @return FALSE if the info does not match or if any error occurs in the check */ BOOL DoCertificateAttributesMatch(PCCERT_CONTEXT certContext, CertificateCheckInfo &infoToMatch) { DWORD dwData; LPWSTR szName = nullptr; if (infoToMatch.issuer) { // Pass in nullptr to get the needed size of the issuer buffer. dwData = CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, nullptr, nullptr, 0); if (!dwData) { LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); return FALSE; } // Allocate memory for Issuer name buffer. szName = (LPWSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR)); if (!szName) { LOG_WARN(("Unable to allocate memory for issuer name. (%d)", GetLastError())); return FALSE; } // Get Issuer name. if (!CertGetNameStringW(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, nullptr, szName, dwData)) { LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); LocalFree(szName); return FALSE; } // If the issuer does not match, return a failure. if (!infoToMatch.issuer || wcscmp(szName, infoToMatch.issuer)) { LocalFree(szName); return FALSE; } LocalFree(szName); szName = nullptr; } if (infoToMatch.name) { // Pass in nullptr to get the needed size of the name buffer. dwData = CertGetNameString(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, nullptr, 0); if (!dwData) { LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); return FALSE; } // Allocate memory for the name buffer. szName = (LPWSTR)LocalAlloc(LPTR, dwData * sizeof(WCHAR)); if (!szName) { LOG_WARN(("Unable to allocate memory for subject name. (%d)", GetLastError())); return FALSE; } // Obtain the name. if (!(CertGetNameStringW(certContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, szName, dwData))) { LOG_WARN(("CertGetNameString failed. (%d)", GetLastError())); LocalFree(szName); return FALSE; } // If the issuer does not match, return a failure. if (!infoToMatch.name || wcscmp(szName, infoToMatch.name)) { LocalFree(szName); return FALSE; } // We have a match! LocalFree(szName); } // If there were any errors we would have aborted by now. return TRUE; }