Commit c84c53b1 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: More fully implement CertIsValidCRLForCertificate.

parent e5c56b17
...@@ -19,10 +19,12 @@ ...@@ -19,10 +19,12 @@
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#define NONAMELESSUNION
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "wincrypt.h" #include "wincrypt.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h"
#include "crypt32_private.h" #include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt); WINE_DEFAULT_DEBUG_CHANNEL(crypt);
...@@ -484,11 +486,155 @@ BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext, ...@@ -484,11 +486,155 @@ BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
return ret; return ret;
} }
static BOOL compare_dist_point_name(const CRL_DIST_POINT_NAME *name1,
const CRL_DIST_POINT_NAME *name2)
{
BOOL match;
if (name1->dwDistPointNameChoice == name2->dwDistPointNameChoice)
{
match = TRUE;
if (name1->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
{
if (name1->u.FullName.cAltEntry == name2->u.FullName.cAltEntry)
{
DWORD i;
for (i = 0; match && i < name1->u.FullName.cAltEntry; i++)
{
const CERT_ALT_NAME_ENTRY *entry1 =
&name1->u.FullName.rgAltEntry[i];
const CERT_ALT_NAME_ENTRY *entry2 =
&name2->u.FullName.rgAltEntry[i];
if (entry1->dwAltNameChoice == entry2->dwAltNameChoice)
{
switch (entry1->dwAltNameChoice)
{
case CERT_ALT_NAME_URL:
match = !strcmpiW(entry1->u.pwszURL,
entry2->u.pwszURL);
break;
case CERT_ALT_NAME_DIRECTORY_NAME:
match = (entry1->u.DirectoryName.cbData ==
entry2->u.DirectoryName.cbData) &&
!memcmp(entry1->u.DirectoryName.pbData,
entry2->u.DirectoryName.pbData,
entry1->u.DirectoryName.cbData);
break;
default:
FIXME("unimplemented for type %d\n",
entry1->dwAltNameChoice);
match = FALSE;
}
}
else
match = FALSE;
}
}
else
match = FALSE;
}
}
else
match = FALSE;
return match;
}
static BOOL match_dist_point_with_issuing_dist_point(
const CRL_DIST_POINT *distPoint, const CRL_ISSUING_DIST_POINT *idp)
{
BOOL match;
/* While RFC 5280, section 4.2.1.13 recommends against segmenting
* CRL distribution points by reasons, it doesn't preclude doing so.
* "This profile RECOMMENDS against segmenting CRLs by reason code."
* If the issuing distribution point for this CRL is only valid for
* some reasons, only match if the reasons covered also match the
* reasons in the CRL distribution point.
*/
if (idp->OnlySomeReasonFlags.cbData)
{
if (idp->OnlySomeReasonFlags.cbData == distPoint->ReasonFlags.cbData)
{
DWORD i;
match = TRUE;
for (i = 0; match && i < distPoint->ReasonFlags.cbData; i++)
if (idp->OnlySomeReasonFlags.pbData[i] !=
distPoint->ReasonFlags.pbData[i])
match = FALSE;
}
else
match = FALSE;
}
else
match = TRUE;
if (match)
match = compare_dist_point_name(&idp->DistPointName,
&distPoint->DistPointName);
return match;
}
BOOL WINAPI CertIsValidCRLForCertificate(PCCERT_CONTEXT pCert, BOOL WINAPI CertIsValidCRLForCertificate(PCCERT_CONTEXT pCert,
PCCRL_CONTEXT pCrl, DWORD dwFlags, void *pvReserved) PCCRL_CONTEXT pCrl, DWORD dwFlags, void *pvReserved)
{ {
PCERT_EXTENSION ext;
BOOL ret;
TRACE("(%p, %p, %08x, %p)\n", pCert, pCrl, dwFlags, pvReserved); TRACE("(%p, %p, %08x, %p)\n", pCert, pCrl, dwFlags, pvReserved);
if (!pCert)
return TRUE; return TRUE;
if ((ext = CertFindExtension(szOID_ISSUING_DIST_POINT,
pCrl->pCrlInfo->cExtension, pCrl->pCrlInfo->rgExtension)))
{
CRL_ISSUING_DIST_POINT *idp;
DWORD size;
if ((ret = CryptDecodeObjectEx(pCrl->dwCertEncodingType,
X509_ISSUING_DIST_POINT, ext->Value.pbData, ext->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG, NULL, &idp, &size)))
{
if ((ext = CertFindExtension(szOID_CRL_DIST_POINTS,
pCert->pCertInfo->cExtension, pCert->pCertInfo->rgExtension)))
{
CRL_DIST_POINTS_INFO *distPoints;
if ((ret = CryptDecodeObjectEx(pCert->dwCertEncodingType,
X509_CRL_DIST_POINTS, ext->Value.pbData, ext->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG, NULL, &distPoints, &size)))
{
DWORD i;
ret = FALSE;
for (i = 0; !ret && i < distPoints->cDistPoint; i++)
ret = match_dist_point_with_issuing_dist_point(
&distPoints->rgDistPoint[i], idp);
if (!ret)
SetLastError(CRYPT_E_NO_MATCH);
LocalFree(distPoints);
}
}
else
{
/* no CRL dist points extension in cert, compare CRL's issuer
* to cert's issuer.
*/
if (!CertCompareCertificateName(pCrl->dwCertEncodingType,
&pCrl->pCrlInfo->Issuer, &pCert->pCertInfo->Issuer))
{
ret = FALSE;
SetLastError(CRYPT_E_NO_MATCH);
}
}
LocalFree(idp);
}
}
else
ret = TRUE;
return ret;
} }
static PCRL_ENTRY CRYPT_FindCertificateInCRL(PCERT_INFO cert, const CRL_INFO *crl) static PCRL_ENTRY CRYPT_FindCertificateInCRL(PCERT_INFO cert, const CRL_INFO *crl)
......
...@@ -755,10 +755,10 @@ static void testIsValidCRLForCert(void) ...@@ -755,10 +755,10 @@ static void testIsValidCRLForCert(void)
ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL); ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
ok(!ret && GetLastError() == CRYPT_E_NO_MATCH, ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
"expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError()); "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
}
ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL); ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
ok(!ret && GetLastError() == CRYPT_E_NO_MATCH, ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
"expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError()); "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
}
/* With a CRL_ISSUING_DIST_POINT in the CRL, it matches the cert containing /* With a CRL_ISSUING_DIST_POINT in the CRL, it matches the cert containing
* a CRL_DIST_POINTS_INFO extension. * a CRL_DIST_POINTS_INFO extension.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment