crypt32: Implement CertFindCertificateInStore, with tests.
This commit is contained in:
parent
3600b04877
commit
aa6dc003a4
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user