forked from Mirrors/wine-wine
crypt32/tests: Test CertAddCertificateLinkToStore.
parent
c232af490e
commit
0dfb0299f6
|
@ -2063,6 +2063,362 @@ static void testAddSerialized(void)
|
|||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
static void compareStore(HCERTSTORE store, LPCSTR name, const BYTE *pb,
|
||||
DWORD cb)
|
||||
{
|
||||
BOOL ret;
|
||||
CRYPT_DATA_BLOB blob = { 0, NULL };
|
||||
|
||||
ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
|
||||
CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
|
||||
ok(blob.cbData == cb, "%s: expected size %d, got %d\n", name, cb,
|
||||
blob.cbData);
|
||||
blob.pbData = HeapAlloc(GetProcessHeap(), 0, blob.cbData);
|
||||
if (blob.pbData)
|
||||
{
|
||||
ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
|
||||
CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
|
||||
ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
|
||||
ok(!memcmp(pb, blob.pbData, cb), "%s: unexpected value\n", name);
|
||||
HeapFree(GetProcessHeap(), 0, blob.pbData);
|
||||
}
|
||||
}
|
||||
|
||||
static const BYTE serializedCertWithFriendlyName[] = {
|
||||
0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,
|
||||
0x00,0x6e,0x00,0x65,0x00,0x54,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,
|
||||
0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,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,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 serializedStoreWithCertWithFriendlyName[] = {
|
||||
0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,
|
||||
0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,0x00,0x6e,0x00,0x65,0x00,0x54,0x00,
|
||||
0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
|
||||
0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,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,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
|
||||
0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||
static const BYTE serializedStoreWithCertAndHash[] = {
|
||||
0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x03,0x00,0x00,0x00,0x01,0x00,0x00,
|
||||
0x00,0x14,0x00,0x00,0x00,0x6e,0x30,0x90,0x71,0x5f,0xd9,0x23,0x56,0xeb,0xae,
|
||||
0x25,0x40,0xe6,0x22,0xda,0x19,0x26,0x02,0xa6,0x08,0x20,0x00,0x00,0x00,0x01,
|
||||
0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,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,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
|
||||
0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||
|
||||
static void testAddCertificateLink(void)
|
||||
{
|
||||
BOOL ret;
|
||||
HCERTSTORE store1, store2;
|
||||
PCCERT_CONTEXT source, linked;
|
||||
DWORD size;
|
||||
LPBYTE buf;
|
||||
CERT_NAME_BLOB blob;
|
||||
static const WCHAR szPrefix[] = { 'c','e','r',0 };
|
||||
static const WCHAR szDot[] = { '.',0 };
|
||||
static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
|
||||
WCHAR filename1[MAX_PATH], filename2[MAX_PATH];
|
||||
HANDLE file;
|
||||
|
||||
if (0)
|
||||
{
|
||||
/* Crashes, i.e. the store is dereferenced without checking. */
|
||||
ret = CertAddCertificateLinkToStore(NULL, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
/* Adding a certificate link to a store requires a valid add disposition */
|
||||
store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertAddCertificateLinkToStore(store1, NULL, 0, NULL);
|
||||
todo_wine
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
||||
sizeof(bigCert));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertAddCertificateLinkToStore(store1, source, 0, NULL);
|
||||
todo_wine
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
|
||||
NULL);
|
||||
todo_wine
|
||||
ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
|
||||
if (0)
|
||||
{
|
||||
/* Crashes, i.e. the source certificate is dereferenced without
|
||||
* checking when a valid add disposition is given.
|
||||
*/
|
||||
ret = CertAddCertificateLinkToStore(store1, NULL, CERT_STORE_ADD_ALWAYS,
|
||||
NULL);
|
||||
}
|
||||
CertCloseStore(store1, 0);
|
||||
|
||||
store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
|
||||
&linked);
|
||||
todo_wine
|
||||
ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
ok(linked->hCertStore == store1, "unexpected store");
|
||||
ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
|
||||
ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
|
||||
GetLastError());
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (buf)
|
||||
{
|
||||
ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
|
||||
/* The serialized linked certificate is identical to the serialized
|
||||
* original certificate.
|
||||
*/
|
||||
ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
|
||||
ok(!memcmp(serializedCert, buf, size),
|
||||
"Unexpected serialized cert\n");
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
/* Set a friendly name on the source certificate... */
|
||||
blob.pbData = (LPBYTE)WineTestW;
|
||||
blob.cbData = sizeof(WineTestW);
|
||||
ret = CertSetCertificateContextProperty(source,
|
||||
CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
|
||||
ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
|
||||
GetLastError());
|
||||
/* and the linked certificate has the same friendly name. */
|
||||
ret = CertGetCertificateContextProperty(linked,
|
||||
CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
|
||||
ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
|
||||
GetLastError());
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (buf)
|
||||
{
|
||||
ret = CertGetCertificateContextProperty(linked,
|
||||
CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
|
||||
ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
|
||||
"unexpected friendly name\n");
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
CertFreeCertificateContext(linked);
|
||||
}
|
||||
CertFreeCertificateContext(source);
|
||||
CertCloseStore(store1, 0);
|
||||
|
||||
/* Test adding a cert to a file store, committing the change to the store,
|
||||
* and creating a link to the resulting cert.
|
||||
*/
|
||||
if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
|
||||
return;
|
||||
|
||||
DeleteFileW(filename1);
|
||||
file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
||||
CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
|
||||
ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
||||
CloseHandle(file);
|
||||
|
||||
ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
|
||||
bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
|
||||
ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
|
||||
GetLastError());
|
||||
|
||||
/* Test adding a link to a memory store. */
|
||||
store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
|
||||
&linked);
|
||||
todo_wine
|
||||
ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
ok(linked->hCertStore == store2, "unexpected store");
|
||||
ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
|
||||
ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
|
||||
GetLastError());
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (buf)
|
||||
{
|
||||
ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
|
||||
/* The serialized linked certificate is identical to the serialized
|
||||
* original certificate.
|
||||
*/
|
||||
ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
|
||||
ok(!memcmp(serializedCert, buf, size),
|
||||
"Unexpected serialized cert\n");
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
/* Set a friendly name on the source certificate... */
|
||||
blob.pbData = (LPBYTE)WineTestW;
|
||||
blob.cbData = sizeof(WineTestW);
|
||||
ret = CertSetCertificateContextProperty(source,
|
||||
CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
|
||||
ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
|
||||
GetLastError());
|
||||
/* and the linked certificate has the same friendly name. */
|
||||
ret = CertGetCertificateContextProperty(linked,
|
||||
CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
|
||||
ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
|
||||
GetLastError());
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (buf)
|
||||
{
|
||||
ret = CertGetCertificateContextProperty(linked,
|
||||
CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
|
||||
ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
|
||||
"unexpected friendly name\n");
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
CertFreeCertificateContext(linked);
|
||||
}
|
||||
CertCloseStore(store2, 0);
|
||||
|
||||
if (!GetTempFileNameW(szDot, szPrefix, 0, filename2))
|
||||
return;
|
||||
|
||||
DeleteFileW(filename2);
|
||||
file = CreateFileW(filename2, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
||||
CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
|
||||
ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
||||
CloseHandle(file);
|
||||
/* Test adding a link to a file store. */
|
||||
ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
|
||||
&linked);
|
||||
todo_wine
|
||||
ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
ok(linked->hCertStore == store2, "unexpected store");
|
||||
ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
|
||||
ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
|
||||
GetLastError());
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (buf)
|
||||
{
|
||||
ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
|
||||
/* The serialized linked certificate now contains the friendly
|
||||
* name property.
|
||||
*/
|
||||
ok(size == sizeof(serializedCertWithFriendlyName),
|
||||
"Wrong size %d\n", size);
|
||||
ok(!memcmp(serializedCertWithFriendlyName, buf, size),
|
||||
"Unexpected serialized cert\n");
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
CertFreeCertificateContext(linked);
|
||||
compareStore(store2, "file store -> file store",
|
||||
serializedStoreWithCertWithFriendlyName,
|
||||
sizeof(serializedStoreWithCertWithFriendlyName));
|
||||
}
|
||||
CertCloseStore(store2, 0);
|
||||
DeleteFileW(filename2);
|
||||
|
||||
CertFreeCertificateContext(source);
|
||||
|
||||
CertCloseStore(store1, 0);
|
||||
DeleteFileW(filename1);
|
||||
|
||||
/* Test adding a link to a system store (which is a collection store.) */
|
||||
store1 = CertOpenSystemStoreA(0, "My");
|
||||
source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
||||
sizeof(bigCert));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
|
||||
&linked);
|
||||
todo_wine
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
CertFreeCertificateContext(source);
|
||||
|
||||
/* Test adding a link to a file store, where the linked certificate is
|
||||
* in a system store.
|
||||
*/
|
||||
ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
|
||||
bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
|
||||
ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
|
||||
GetLastError());
|
||||
if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
|
||||
return;
|
||||
|
||||
DeleteFileW(filename1);
|
||||
file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
||||
CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
|
||||
ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
||||
CloseHandle(file);
|
||||
|
||||
ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
|
||||
&linked);
|
||||
todo_wine
|
||||
ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
ok(linked->hCertStore == store2, "unexpected store");
|
||||
ret = pCertControlStore(store2, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
||||
ok(ret, "CertControlStore failed: %d\n", ret);
|
||||
compareStore(store2, "file store -> system store",
|
||||
serializedStoreWithCertAndHash,
|
||||
sizeof(serializedStoreWithCertAndHash));
|
||||
CertFreeCertificateContext(linked);
|
||||
}
|
||||
|
||||
CertCloseStore(store2, 0);
|
||||
DeleteFileW(filename1);
|
||||
|
||||
/* Test adding a link to a registry store, where the linked certificate is
|
||||
* in a system store.
|
||||
*/
|
||||
store2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
|
||||
CERT_SYSTEM_STORE_CURRENT_USER, WineTestW);
|
||||
ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
||||
ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
|
||||
&linked);
|
||||
todo_wine
|
||||
ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
ok(linked->hCertStore == store2, "unexpected store");
|
||||
CertDeleteCertificateFromStore(linked);
|
||||
}
|
||||
CertCloseStore(store2, 0);
|
||||
|
||||
CertFreeCertificateContext(source);
|
||||
CertCloseStore(store1, 0);
|
||||
}
|
||||
|
||||
static DWORD countCertsInStore(HCERTSTORE store)
|
||||
{
|
||||
PCCERT_CONTEXT cert = NULL;
|
||||
|
@ -2191,6 +2547,7 @@ START_TEST(store)
|
|||
testStoreProperty();
|
||||
|
||||
testAddSerialized();
|
||||
testAddCertificateLink();
|
||||
|
||||
test_I_UpdateStore();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue