Module: wine Branch: master Commit: 048594854a4bbaa337ae3556ed5de4d5f3470a6a URL: http://source.winehq.org/git/wine.git/?a=commit;h=048594854a4bbaa337ae3556ed...
Author: Juan Lang juan.lang@gmail.com Date: Thu Dec 17 08:52:19 2009 -0800
crypt32: Check authority key identifer extension to determine if a certificate is self-signed.
---
dlls/crypt32/chain.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 111 insertions(+), 3 deletions(-)
diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c index 0d1a2f0..28a2206 100644 --- a/dlls/crypt32/chain.c +++ b/dlls/crypt32/chain.c @@ -230,10 +230,118 @@ typedef struct _CertificateChain LONG ref; } CertificateChain, *PCertificateChain;
-static inline BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert) +static BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert) { - return CertCompareCertificateName(cert->dwCertEncodingType, - &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer); + PCERT_EXTENSION ext; + DWORD size; + BOOL ret; + + 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; + } + 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 void CRYPT_FreeChainElement(PCERT_CHAIN_ELEMENT element)