crypt32: Partially implement CertGetIssuerCertificateFromStore.
This commit is contained in:
parent
9adcf560ae
commit
ed66801d3a
|
@ -52,7 +52,7 @@
|
||||||
@ stdcall CertGetCertificateContextProperty(ptr long ptr ptr)
|
@ stdcall CertGetCertificateContextProperty(ptr long ptr ptr)
|
||||||
@ stdcall CertGetEnhancedKeyUsage(ptr long ptr ptr)
|
@ stdcall CertGetEnhancedKeyUsage(ptr long ptr ptr)
|
||||||
@ stub CertGetIntendedKeyUsage
|
@ stub CertGetIntendedKeyUsage
|
||||||
@ stub CertGetIssuerCertificateFromStore
|
@ stdcall CertGetIssuerCertificateFromStore(long ptr ptr ptr)
|
||||||
@ stdcall CertGetNameStringA(ptr long long ptr ptr long)
|
@ stdcall CertGetNameStringA(ptr long long ptr ptr long)
|
||||||
@ stdcall CertGetNameStringW(ptr long long ptr ptr long)
|
@ stdcall CertGetNameStringW(ptr long long ptr ptr long)
|
||||||
@ stub CertGetPublicKeyLength
|
@ stub CertGetPublicKeyLength
|
||||||
|
|
|
@ -2646,6 +2646,13 @@ static BOOL compare_cert_by_subject_cert(PCCERT_CONTEXT pCertContext,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL compare_cert_by_issuer(PCCERT_CONTEXT pCertContext,
|
||||||
|
DWORD dwType, DWORD dwFlags, const void *pvPara)
|
||||||
|
{
|
||||||
|
return compare_cert_by_subject_cert(pCertContext, dwType, dwFlags,
|
||||||
|
((PCCERT_CONTEXT)pvPara)->pCertInfo);
|
||||||
|
}
|
||||||
|
|
||||||
PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
|
PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
|
||||||
DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType,
|
DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType,
|
||||||
const void *pvPara, PCCERT_CONTEXT pPrevCertContext)
|
const void *pvPara, PCCERT_CONTEXT pPrevCertContext)
|
||||||
|
@ -2673,6 +2680,9 @@ PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
|
||||||
case CERT_COMPARE_SUBJECT_CERT:
|
case CERT_COMPARE_SUBJECT_CERT:
|
||||||
compare = compare_cert_by_subject_cert;
|
compare = compare_cert_by_subject_cert;
|
||||||
break;
|
break;
|
||||||
|
case CERT_COMPARE_ISSUER_OF:
|
||||||
|
compare = compare_cert_by_issuer;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
FIXME("find type %08lx unimplemented\n", dwType);
|
FIXME("find type %08lx unimplemented\n", dwType);
|
||||||
compare = NULL;
|
compare = NULL;
|
||||||
|
@ -2713,6 +2723,50 @@ PCCERT_CONTEXT WINAPI CertGetSubjectCertificateFromStore(HCERTSTORE hCertStore,
|
||||||
CERT_FIND_SUBJECT_CERT, pCertId, NULL);
|
CERT_FIND_SUBJECT_CERT, pCertId, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCCERT_CONTEXT WINAPI CertGetIssuerCertificateFromStore(HCERTSTORE hCertStore,
|
||||||
|
PCCERT_CONTEXT pSubjectContext, PCCERT_CONTEXT pPrevIssuerContext,
|
||||||
|
DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
static const DWORD supportedFlags = CERT_STORE_REVOCATION_FLAG |
|
||||||
|
CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG;
|
||||||
|
PCCERT_CONTEXT ret;
|
||||||
|
|
||||||
|
TRACE("(%p, %p, %p, %08lx)\n", hCertStore, pSubjectContext,
|
||||||
|
pPrevIssuerContext, *pdwFlags);
|
||||||
|
|
||||||
|
if (*pdwFlags & ~supportedFlags)
|
||||||
|
{
|
||||||
|
SetLastError(E_INVALIDARG);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret = CertFindCertificateInStore(hCertStore,
|
||||||
|
pSubjectContext->dwCertEncodingType, 0, CERT_FIND_ISSUER_OF,
|
||||||
|
pSubjectContext, pPrevIssuerContext);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
if (*pdwFlags & CERT_STORE_REVOCATION_FLAG)
|
||||||
|
{
|
||||||
|
FIXME("revocation check requires CRL support\n");
|
||||||
|
*pdwFlags |= CERT_STORE_NO_CRL_FLAG;
|
||||||
|
}
|
||||||
|
if (*pdwFlags & CERT_STORE_TIME_VALIDITY_FLAG)
|
||||||
|
{
|
||||||
|
if (0 == CertVerifyTimeValidity(NULL, pSubjectContext->pCertInfo))
|
||||||
|
*pdwFlags &= ~CERT_STORE_TIME_VALIDITY_FLAG;
|
||||||
|
}
|
||||||
|
if (*pdwFlags & CERT_STORE_SIGNATURE_FLAG)
|
||||||
|
{
|
||||||
|
if (CryptVerifyCertificateSignatureEx(0,
|
||||||
|
pSubjectContext->dwCertEncodingType,
|
||||||
|
CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, (void *)pSubjectContext,
|
||||||
|
CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)ret, 0, NULL))
|
||||||
|
*pdwFlags &= ~CERT_STORE_SIGNATURE_FLAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
|
BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
|
||||||
HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
|
HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
|
||||||
{
|
{
|
||||||
|
|
|
@ -427,6 +427,129 @@ static void testGetSubjectCert(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This expires in 1970 or so */
|
||||||
|
static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
|
||||||
|
0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
|
||||||
|
0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
|
||||||
|
0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
|
||||||
|
0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
|
||||||
|
0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
|
||||||
|
0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
|
||||||
|
0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
|
||||||
|
0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
|
||||||
|
0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
|
||||||
|
0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||||
|
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
|
||||||
|
0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
|
||||||
|
0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
|
||||||
|
0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
|
||||||
|
0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
|
||||||
|
0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
|
||||||
|
0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
|
||||||
|
0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
|
||||||
|
0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
|
||||||
|
0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
|
||||||
|
0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
|
||||||
|
0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
|
||||||
|
0x49, 0xe5, 0xf9, 0x65, 0xf3 };
|
||||||
|
|
||||||
|
/* This expires in 2036 or so */
|
||||||
|
static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
|
||||||
|
0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
|
||||||
|
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
|
||||||
|
0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
|
||||||
|
0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
|
||||||
|
0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
|
||||||
|
0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
|
||||||
|
0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 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, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
|
||||||
|
0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
|
||||||
|
0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
|
||||||
|
0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
|
||||||
|
0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
|
||||||
|
0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
|
||||||
|
0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
|
||||||
|
|
||||||
|
static void testGetIssuerCert(void)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
PCCERT_CONTEXT parent, child;
|
||||||
|
DWORD flags = 0xffffffff;
|
||||||
|
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||||
|
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||||
|
|
||||||
|
ok(store != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
|
||||||
|
|
||||||
|
ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
||||||
|
expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
|
||||||
|
ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
|
||||||
|
GetLastError());
|
||||||
|
|
||||||
|
ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
||||||
|
childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
|
||||||
|
ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
|
||||||
|
GetLastError());
|
||||||
|
|
||||||
|
/* These crash:
|
||||||
|
parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
|
||||||
|
parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
|
||||||
|
*/
|
||||||
|
parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
|
||||||
|
ok(!parent && GetLastError() == E_INVALIDARG,
|
||||||
|
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||||
|
parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
|
||||||
|
ok(!parent && GetLastError() == E_INVALIDARG,
|
||||||
|
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||||
|
parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
|
||||||
|
ok(!parent && GetLastError() == E_INVALIDARG,
|
||||||
|
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||||
|
/* Confusing: the caller cannot set either of the
|
||||||
|
* CERT_STORE_NO_*_FLAGs, as these are not checks,
|
||||||
|
* they're results:
|
||||||
|
*/
|
||||||
|
flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
|
||||||
|
parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
|
||||||
|
ok(!parent && GetLastError() == E_INVALIDARG,
|
||||||
|
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||||
|
/* Perform no checks */
|
||||||
|
flags = 0;
|
||||||
|
parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
|
||||||
|
ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
|
||||||
|
GetLastError());
|
||||||
|
if (parent)
|
||||||
|
CertFreeCertificateContext(parent);
|
||||||
|
/* Check revocation and signature only */
|
||||||
|
flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
|
||||||
|
parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
|
||||||
|
ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
|
||||||
|
GetLastError());
|
||||||
|
/* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
|
||||||
|
* setting CERT_STORE_NO_CRL_FLAG.
|
||||||
|
*/
|
||||||
|
ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
|
||||||
|
"Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
|
||||||
|
flags);
|
||||||
|
if (parent)
|
||||||
|
CertFreeCertificateContext(parent);
|
||||||
|
/* Now check just the time */
|
||||||
|
flags = CERT_STORE_TIME_VALIDITY_FLAG;
|
||||||
|
parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
|
||||||
|
ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
|
||||||
|
GetLastError());
|
||||||
|
/* Oops: the child is not expired, so the time validity check actually
|
||||||
|
* succeeds, even though the signing cert is expired.
|
||||||
|
*/
|
||||||
|
ok(!flags, "Expected check to succeed, got %08lx\n", flags);
|
||||||
|
if (parent)
|
||||||
|
CertFreeCertificateContext(parent);
|
||||||
|
|
||||||
|
CertFreeCertificateContext(child);
|
||||||
|
CertCloseStore(store, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void testMemStore(void)
|
static void testMemStore(void)
|
||||||
{
|
{
|
||||||
HCERTSTORE store1, store2;
|
HCERTSTORE store1, store2;
|
||||||
|
@ -1702,6 +1825,7 @@ START_TEST(store)
|
||||||
testDupCert();
|
testDupCert();
|
||||||
testFindCert();
|
testFindCert();
|
||||||
testGetSubjectCert();
|
testGetSubjectCert();
|
||||||
|
testGetIssuerCert();
|
||||||
|
|
||||||
/* various combinations of CertOpenStore */
|
/* various combinations of CertOpenStore */
|
||||||
testMemStore();
|
testMemStore();
|
||||||
|
|
|
@ -2389,6 +2389,15 @@ static const WCHAR CERT_PHYSICAL_STORE_AUTH_ROOT_NAME[] =
|
||||||
#define CRYPT_UNICODE_NAME_DECODE_DISABLE_IE4_UTF8_FLAG \
|
#define CRYPT_UNICODE_NAME_DECODE_DISABLE_IE4_UTF8_FLAG \
|
||||||
CERT_RDN_DISABLE_IE4_UTF8_FLAG
|
CERT_RDN_DISABLE_IE4_UTF8_FLAG
|
||||||
|
|
||||||
|
#define CERT_STORE_SIGNATURE_FLAG 0x00000001
|
||||||
|
#define CERT_STORE_TIME_VALIDITY_FLAG 0x00000002
|
||||||
|
#define CERT_STORE_REVOCATION_FLAG 0x00000004
|
||||||
|
#define CERT_STORE_NO_CRL_FLAG 0x00010000
|
||||||
|
#define CERT_STORE_NO_ISSUER_FLAG 0x00020000
|
||||||
|
|
||||||
|
#define CERT_STORE_BASE_CRL_FLAG 0x00000100
|
||||||
|
#define CERT_STORE_DELTA_CRL_FLAG 0x00000200
|
||||||
|
|
||||||
/* subject types for CryptVerifyCertificateSignatureEx */
|
/* subject types for CryptVerifyCertificateSignatureEx */
|
||||||
#define CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB 1
|
#define CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB 1
|
||||||
#define CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT 2
|
#define CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT 2
|
||||||
|
@ -2728,6 +2737,10 @@ PCCTL_CONTEXT WINAPI CertFindCTLInStore(HCERTSTORE hCertStore,
|
||||||
DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType,
|
DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType,
|
||||||
const void *pvFindPara, PCCTL_CONTEXT pPrevCtlContext);
|
const void *pvFindPara, PCCTL_CONTEXT pPrevCtlContext);
|
||||||
|
|
||||||
|
PCCERT_CONTEXT WINAPI CertGetIssuerCertificateFromStore(HCERTSTORE hCertStore,
|
||||||
|
PCCERT_CONTEXT pSubjectContext, PCCERT_CONTEXT pPrevIssuerContext,
|
||||||
|
DWORD *pdwFlags);
|
||||||
|
|
||||||
PCCERT_CONTEXT WINAPI CertGetSubjectCertificateFromStore(HCERTSTORE hCertStore,
|
PCCERT_CONTEXT WINAPI CertGetSubjectCertificateFromStore(HCERTSTORE hCertStore,
|
||||||
DWORD dwCertEncodingType, PCERT_INFO pCertId);
|
DWORD dwCertEncodingType, PCERT_INFO pCertId);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue