Juan Lang : crypt32: More fully implement CertIsValidCRLForCertificate.
Alexandre Julliard
julliard at winehq.org
Thu Nov 19 10:15:21 CST 2009
Module: wine
Branch: master
Commit: c84c53b1a6fba37a1619bc099d379f8f0c86723a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c84c53b1a6fba37a1619bc099d379f8f0c86723a
Author: Juan Lang <juan.lang at gmail.com>
Date: Wed Nov 18 16:21:09 2009 -0800
crypt32: More fully implement CertIsValidCRLForCertificate.
---
dlls/crypt32/crl.c | 148 +++++++++++++++++++++++++++++++++++++++++++++-
dlls/crypt32/tests/crl.c | 2 +-
2 files changed, 148 insertions(+), 2 deletions(-)
diff --git a/dlls/crypt32/crl.c b/dlls/crypt32/crl.c
index f483256..f71e6a8 100644
--- a/dlls/crypt32/crl.c
+++ b/dlls/crypt32/crl.c
@@ -19,10 +19,12 @@
#include <assert.h>
#include <stdarg.h>
+#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "wincrypt.h"
#include "wine/debug.h"
+#include "wine/unicode.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
@@ -484,11 +486,155 @@ BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
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,
PCCRL_CONTEXT pCrl, DWORD dwFlags, void *pvReserved)
{
+ PCERT_EXTENSION ext;
+ BOOL ret;
+
TRACE("(%p, %p, %08x, %p)\n", pCert, pCrl, dwFlags, pvReserved);
- return TRUE;
+
+ if (!pCert)
+ 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)
diff --git a/dlls/crypt32/tests/crl.c b/dlls/crypt32/tests/crl.c
index bc6c862..cec233f 100644
--- a/dlls/crypt32/tests/crl.c
+++ b/dlls/crypt32/tests/crl.c
@@ -755,10 +755,10 @@ static void testIsValidCRLForCert(void)
ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
"expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
+ }
ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
"expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
- }
/* With a CRL_ISSUING_DIST_POINT in the CRL, it matches the cert containing
* a CRL_DIST_POINTS_INFO extension.
More information about the wine-cvs
mailing list