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

crypt32: Partially implement CertGetIssuerCertificateFromStore.

parent 9adcf560
...@@ -52,7 +52,7 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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[] = ...@@ -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, ...@@ -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);
......
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