Module: wine Branch: master Commit: 1ce46d5e4a38b9be67b442747ab6952a0bf44a88 URL: http://source.winehq.org/git/wine.git/?a=commit;h=1ce46d5e4a38b9be67b442747a... Author: Juan Lang <juan.lang(a)gmail.com> Date: Thu Aug 30 17:59:13 2007 -0700 crypt32: Check whether each signing certificate can be a CA. --- dlls/crypt32/chain.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ dlls/crypt32/tests/chain.c | 2 +- 2 files changed, 55 insertions(+), 1 deletions(-) diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c index 4372a8d..5a2b8ef 100644 --- a/dlls/crypt32/chain.c +++ b/dlls/crypt32/chain.c @@ -358,6 +358,51 @@ static BOOL CRYPT_CheckRootCert(HCERTCHAINENGINE hRoot, return ret; } +static BOOL CRYPT_CanCertBeCA(PCCERT_CONTEXT cert, BOOL defaultIfNotSpecified) +{ + BOOL ret; + PCERT_EXTENSION ext = CertFindExtension(szOID_BASIC_CONSTRAINTS, + cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension); + + if (ext) + { + CERT_BASIC_CONSTRAINTS_INFO *info; + DWORD size = 0; + + ret = CryptDecodeObjectEx(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS, + ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, + NULL, (LPBYTE)&info, &size); + if (ret) + { + if (info->SubjectType.cbData == 1) + ret = info->SubjectType.pbData[0] & CERT_CA_SUBJECT_FLAG; + LocalFree(info); + } + } + else + { + ext = CertFindExtension(szOID_BASIC_CONSTRAINTS2, + cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension); + if (ext) + { + CERT_BASIC_CONSTRAINTS2_INFO *info; + DWORD size = 0; + + ret = CryptDecodeObjectEx(X509_ASN_ENCODING, + szOID_BASIC_CONSTRAINTS2, ext->Value.pbData, ext->Value.cbData, + CRYPT_DECODE_ALLOC_FLAG, NULL, (LPBYTE)&info, &size); + if (ret) + { + ret = info->fCA; + LocalFree(info); + } + } + else + ret = defaultIfNotSpecified; + } + return ret; +} + static BOOL CRYPT_CheckSimpleChain(PCertificateChainEngine engine, PCERT_SIMPLE_CHAIN chain, LPFILETIME time) { @@ -371,6 +416,15 @@ static BOOL CRYPT_CheckSimpleChain(PCertificateChainEngine engine, chain->rgpElement[i]->pCertContext->pCertInfo) != 0) chain->rgpElement[i]->TrustStatus.dwErrorStatus |= CERT_TRUST_IS_NOT_TIME_VALID; + if (i != 0) + { + BOOL ca; + + ca = CRYPT_CanCertBeCA(chain->rgpElement[i]->pCertContext, TRUE); + if (!ca) + chain->rgpElement[i]->TrustStatus.dwErrorStatus |= + CERT_TRUST_INVALID_BASIC_CONSTRAINTS; + } /* FIXME: check valid usages and name constraints */ CRYPT_CombineTrustStatus(&chain->TrustStatus, &chain->rgpElement[i]->TrustStatus); diff --git a/dlls/crypt32/tests/chain.c b/dlls/crypt32/tests/chain.c index 507ab24..a7e1928 100644 --- a/dlls/crypt32/tests/chain.c +++ b/dlls/crypt32/tests/chain.c @@ -1502,7 +1502,7 @@ static ChainCheck chainCheck[] = { { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_TIME_VALID, 0 }, 1, simpleStatus3 }, - TODO_ERROR | TODO_INFO }, + TODO_INFO }, { { sizeof(chain4) / sizeof(chain4[0]), chain4 }, { { 0, CERT_TRUST_HAS_PREFERRED_ISSUER }, { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT |