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

crypt32: Implement CertFindCertificateInStore, with tests.

parent 3600b048
......@@ -460,7 +460,6 @@ static BOOL WINAPI CRYPT_MemAddCert(HCERTSTORE store, PCCERT_CONTEXT pCert,
{
TRACE("adding %p\n", entry);
CRYPT_InitCertRef(&entry->cert, (PWINE_CERT_CONTEXT)pCert, store);
list_init(&entry->entry);
EnterCriticalSection(&ms->cs);
list_add_tail(&ms->certs, &entry->entry);
LeaveCriticalSection(&ms->cs);
......@@ -512,8 +511,6 @@ static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store,
return (PWINE_CERT_CONTEXT_REF)ret;
}
static void CRYPT_UnrefCertificateContext(PWINE_CERT_CONTEXT_REF ref);
static BOOL WINAPI CRYPT_MemDeleteCert(HCERTSTORE hCertStore,
PCCERT_CONTEXT pCertContext, DWORD dwFlags)
{
......@@ -2321,7 +2318,7 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty(
switch (dwPropId)
{
case CERT_AUTO_ENROLL_PROP_ID:
case CERT_CTL_USAGE_PROP_ID:
case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
case CERT_DESCRIPTION_PROP_ID:
case CERT_FRIENDLY_NAME_PROP_ID:
case CERT_HASH_PROP_ID:
......@@ -3108,14 +3105,139 @@ BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
return TRUE;
}
typedef BOOL (*CertCompareFunc)(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, const void *pvPara);
static BOOL compare_cert_any(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, const void *pvPara)
{
return TRUE;
}
static BOOL compare_cert_by_md5_hash(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, const void *pvPara)
{
BOOL ret;
BYTE hash[16];
DWORD size = sizeof(hash);
ret = CertGetCertificateContextProperty(pCertContext,
CERT_MD5_HASH_PROP_ID, hash, &size);
if (ret)
{
const CRYPT_HASH_BLOB *pHash = (const CRYPT_HASH_BLOB *)pvPara;
if (size == pHash->cbData)
ret = !memcmp(pHash->pbData, hash, size);
else
ret = FALSE;
}
return ret;
}
static BOOL compare_cert_by_sha1_hash(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, const void *pvPara)
{
BOOL ret;
BYTE hash[20];
DWORD size = sizeof(hash);
ret = CertGetCertificateContextProperty(pCertContext,
CERT_SHA1_HASH_PROP_ID, hash, &size);
if (ret)
{
const CRYPT_HASH_BLOB *pHash = (const CRYPT_HASH_BLOB *)pvPara;
if (size == pHash->cbData)
ret = !memcmp(pHash->pbData, hash, size);
else
ret = FALSE;
}
return ret;
}
static BOOL compare_cert_by_name(PCCERT_CONTEXT pCertContext, DWORD dwType,
DWORD dwFlags, const void *pvPara)
{
const CERT_NAME_BLOB *blob = (const CERT_NAME_BLOB *)pvPara, *toCompare;
BOOL ret;
if (dwType & CERT_INFO_SUBJECT_FLAG)
toCompare = &pCertContext->pCertInfo->Subject;
else
toCompare = &pCertContext->pCertInfo->Issuer;
if (toCompare->cbData == blob->cbData)
ret = !memcmp(toCompare->pbData, blob->pbData, blob->cbData);
else
ret = FALSE;
return ret;
}
static BOOL compare_cert_by_subject_cert(PCCERT_CONTEXT pCertContext,
DWORD dwType, DWORD dwFlags, const void *pvPara)
{
const CERT_INFO *pCertInfo = (const CERT_INFO *)pvPara;
BOOL ret;
if (pCertInfo->Issuer.cbData == pCertContext->pCertInfo->Subject.cbData)
ret = !memcmp(pCertInfo->Issuer.pbData,
pCertContext->pCertInfo->Subject.pbData, pCertInfo->Issuer.cbData);
else
ret = FALSE;
return ret;
}
PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType,
const void *pvPara, PCCERT_CONTEXT pPrevCertContext)
{
FIXME("stub: %p %ld %ld %ld %p %p\n", hCertStore, dwCertEncodingType,
dwFlags, dwType, pvPara, pPrevCertContext);
SetLastError(CRYPT_E_NOT_FOUND);
return NULL;
PCCERT_CONTEXT ret;
CertCompareFunc compare;
TRACE("(%p, %ld, %ld, %ld, %p, %p)\n", hCertStore, dwCertEncodingType,
dwFlags, dwType, pvPara, pPrevCertContext);
switch (dwType >> CERT_COMPARE_SHIFT)
{
case CERT_COMPARE_ANY:
compare = compare_cert_any;
break;
case CERT_COMPARE_MD5_HASH:
compare = compare_cert_by_md5_hash;
break;
case CERT_COMPARE_SHA1_HASH:
compare = compare_cert_by_sha1_hash;
break;
case CERT_COMPARE_NAME:
compare = compare_cert_by_name;
break;
case CERT_COMPARE_SUBJECT_CERT:
compare = compare_cert_by_subject_cert;
break;
default:
FIXME("find type %08lx unimplemented\n", dwType);
compare = NULL;
}
if (compare)
{
BOOL matches = FALSE;
ret = pPrevCertContext;
do {
ret = CertEnumCertificatesInStore(hCertStore, ret);
if (ret)
matches = compare(ret, dwType, dwFlags, pvPara);
} while (ret != NULL && !matches);
if (!ret)
SetLastError(CRYPT_E_NOT_FOUND);
}
else
{
SetLastError(CRYPT_E_NOT_FOUND);
ret = NULL;
}
return ret;
}
BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
......
......@@ -52,6 +52,11 @@ static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
static const BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
0x6e, 0x67, 0x00 };
static const BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
static const BYTE signedBigCert[] = {
0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
......@@ -83,6 +88,32 @@ static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
static const BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
0x6e, 0x67, 0x00 };
static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
static const BYTE serialNum[] = { 1 };
static void testDupCert(void)
{
......@@ -129,6 +160,113 @@ static void testDupCert(void)
}
}
static void testFindCert(void)
{
HCERTSTORE store;
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
if (store)
{
PCCERT_CONTEXT context = NULL;
BOOL ret;
CERT_INFO certInfo = { 0 };
CRYPT_HASH_BLOB blob;
ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
GetLastError());
ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
GetLastError());
/* This has the same name as bigCert */
ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
GetLastError());
/* Crashes
context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
*/
/* Check first cert's there, by issuer */
certInfo.Subject.pbData = (LPBYTE)subjectName;
certInfo.Subject.cbData = sizeof(subjectName);
certInfo.SerialNumber.pbData = (LPBYTE)serialNum;
certInfo.SerialNumber.cbData = sizeof(serialNum);
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
GetLastError());
if (context)
{
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
ok(context != NULL, "Expected more than one cert\n");
if (context)
{
context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
ok(context == NULL, "Expected precisely two certs\n");
}
}
/* Check second cert's there as well, by subject name */
certInfo.Subject.pbData = (LPBYTE)subjectName2;
certInfo.Subject.cbData = sizeof(subjectName2);
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
GetLastError());
if (context)
{
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
ok(context == NULL, "Expected one cert only\n");
}
/* Strange but true: searching for the subject cert requires you to set
* the issuer, not the subject
*/
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
ok(context == NULL, "Expected no certificate\n");
certInfo.Subject.pbData = NULL;
certInfo.Subject.cbData = 0;
certInfo.Issuer.pbData = (LPBYTE)subjectName2;
certInfo.Issuer.cbData = sizeof(subjectName2);
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
GetLastError());
if (context)
{
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
ok(context == NULL, "Expected one cert only\n");
}
/* The nice thing about hashes, they're unique */
blob.pbData = (LPBYTE)bigCertHash;
blob.cbData = sizeof(bigCertHash);
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_SHA1_HASH, &blob, NULL);
ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
GetLastError());
if (context)
{
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
ok(context == NULL, "Expected one cert only\n");
}
CertCloseStore(store, 0);
}
}
static void testMemStore(void)
{
HCERTSTORE store1, store2;
......@@ -303,17 +441,6 @@ static void testMemStore(void)
CertCloseStore(store1, 0);
}
static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
static void testCollectionStore(void)
{
HCERTSTORE store1, store2, collection, collection2;
......@@ -1412,6 +1539,7 @@ static void testAddSerialized(void)
START_TEST(store)
{
testDupCert();
testFindCert();
/* various combinations of CertOpenStore */
testMemStore();
......
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