Recipe 10.11 in the book "Secure Programming Cookbook for C and C++" showed an example of how to retrieve CRLs from a CA specified as a URL in the extension properties of an X.509 Certificate. The code presented in book used its own "search" function to find a cRLDistributionPoints extension in the certificate, and the Win32 WinInet functions to download the CRL from an HTTP or HTTPS location. Other types of URLs are possible as well, including LDAP and FTP; however, the code presented in the book does not support anything other than HTTP and HTTPS.
Newer versions of CryptoAPI provides two functions that help to get the CRL information, and can be used in place of the
GetDistrubtionPoint() and
SpcRetrieveCRL() functions presented in Recipe 10.11. The two functions are:
CryptGetObjectUrl()CryptRetrieveObjectByUrl()
Both are declared in
wincrypt.h and require the
Cryptnet.lib import library. Note that these functions are only available on Windows 2000, XP, and newer.
PCRYPT_URL_ARRAY SpcGetDistributionPointList(PCCERT_CONTEXT pCertContext)
{
DWORD dwFlags, cbUrlArray;
PCRYPT_URL_ARRAY pUrlArray;
dwFlags = CRYPT_GET_URL_FROM_PROPERTY | CRYPT_GET_URL_FROM_EXTENSION;
if (!CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT, pCertContext,
dwFlags, NULL, &cbUrlArray, NULL, NULL, NULL))
{
return NULL;
}
if (!(pUrlArray = (PCRYPT_URL_ARRAY)LocalAlloc(LMEM_FIXED, cbUrlArray)))
return NULL;
if (!CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT, pCertContext,
dwFlags, pUrlArray, &cbUrlArray, NULL, NULL, NULL))
{
LocalFree(pUrlArray);
return NULL;
}
return pUrlArray;
}
PCCRL_CONTEXT *SpcRetrieveRemoteCRLs(PCCERT_CONTEXT pCertContext)
{
DWORD dwFlags, dwIndex, i;
LPCSTR pszURL;
PCCRL_CONTEXT pCrlContext, *pCrlContexts;
PCRYPT_URL_ARRAY pUrlArray;
if (!(pUrlArray = GetDistributionPointBetter(pCertContext))) return NULL;
dwFlags = CRYPT_WIRE_ONLY_RETRIEVAL;
pCrlContexts = (PCCRL_CONTEXT *)LocalAlloc(LMEM_FIXED,
sizeof(PCCRL_CONTEXT) * (pUrlArray->cUrl + 1));
if (!pCrlContexts) {
LocalFree(pUrlArray);
return NULL;
}
for (dwIndex = i = 0; i < pUrlArray->cUrl; i++) {
if (!(lpszURL = make_thin(pUrlArray->rgwszUrl[i]))) continue;
if (!CryptRetrieveObjectByUrl(lpszURL, CONTEXT_OID_CRL, dwFlags, 5000,
(LPVOID *)&pCrlContext, 0, 0, 0, 0))
{
LocalFree(lpszUrl);
continue;
}
pCrlContexts[dwIndex++] = pCrlContext;
LocalFree(lpszUrl);
}
pCrlContexts[dwIndex] = NULL;
LocalFree(pUrlArray);
return pCrlContexts;
}