| 1 | /*
|
|---|
| 2 | * crypt32 cert store function tests
|
|---|
| 3 | *
|
|---|
| 4 | * Copyright 2005-2006 Juan Lang
|
|---|
| 5 | *
|
|---|
| 6 | * This library is free software; you can redistribute it and/or
|
|---|
| 7 | * modify it under the terms of the GNU Lesser General Public
|
|---|
| 8 | * License as published by the Free Software Foundation; either
|
|---|
| 9 | * version 2.1 of the License, or (at your option) any later version.
|
|---|
| 10 | *
|
|---|
| 11 | * This library is distributed in the hope that it will be useful,
|
|---|
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 14 | * Lesser General Public License for more details.
|
|---|
| 15 | *
|
|---|
| 16 | * You should have received a copy of the GNU Lesser General Public
|
|---|
| 17 | * License along with this library; if not, write to the Free Software
|
|---|
| 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|---|
| 19 | */
|
|---|
| 20 |
|
|---|
| 21 | #include <assert.h>
|
|---|
| 22 | #include <stdio.h>
|
|---|
| 23 | #include <stdarg.h>
|
|---|
| 24 | #include <windef.h>
|
|---|
| 25 | #include <winbase.h>
|
|---|
| 26 | #include <winreg.h>
|
|---|
| 27 | #include <winerror.h>
|
|---|
| 28 | #include <wincrypt.h>
|
|---|
| 29 |
|
|---|
| 30 | #include "wine/test.h"
|
|---|
| 31 |
|
|---|
| 32 | /* The following aren't defined in wincrypt.h, as they're "reserved" */
|
|---|
| 33 | #define CERT_CERT_PROP_ID 32
|
|---|
| 34 | #define CERT_CRL_PROP_ID 33
|
|---|
| 35 | #define CERT_CTL_PROP_ID 34
|
|---|
| 36 |
|
|---|
| 37 | struct CertPropIDHeader
|
|---|
| 38 | {
|
|---|
| 39 | DWORD propID;
|
|---|
| 40 | DWORD unknown1;
|
|---|
| 41 | DWORD cb;
|
|---|
| 42 | };
|
|---|
| 43 |
|
|---|
| 44 | static const BYTE emptyCert[] = { 0x30, 0x00 };
|
|---|
| 45 | static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
|
|---|
| 46 | 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
|---|
| 47 | 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
|
|---|
| 48 | 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
|
|---|
| 49 | 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
|
|---|
| 50 | 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
|
|---|
| 51 | 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
|
|---|
| 52 | 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
|
|---|
| 53 | 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
|
|---|
| 54 | 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
|
|---|
| 55 | static const BYTE signedBigCert[] = {
|
|---|
| 56 | 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
|
|---|
| 57 | 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
|
|---|
| 58 | 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
|
|---|
| 59 | 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
|
|---|
| 60 | 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
|
|---|
| 61 | 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
|
|---|
| 62 | 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
|
|---|
| 63 | 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
|
|---|
| 64 | 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
|
|---|
| 65 | 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
|
|---|
| 66 | 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
|
|---|
| 67 | 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
|
|---|
| 68 | static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
|
|---|
| 69 | 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
|
|---|
| 70 | 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
|
|---|
| 71 | 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
|
|---|
| 72 | 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
|
|---|
| 73 | 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
|
|---|
| 74 | 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
|
|---|
| 75 | 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
|
|---|
| 76 | 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
|
|---|
| 77 | 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
|
|---|
| 78 | 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
|
|---|
| 79 | 0x01, 0x01 };
|
|---|
| 80 | static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
|
|---|
| 81 | 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
|---|
| 82 | 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
|
|---|
| 83 | 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
|
|---|
| 84 | 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
|
|---|
| 85 | 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
|
|---|
| 86 | static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
|
|---|
| 87 | 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
|---|
| 88 | 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
|
|---|
| 89 | 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
|
|---|
| 90 | 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
|
|---|
| 91 | 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
|
|---|
| 92 | 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
|
|---|
| 93 | 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
|
|---|
| 94 | 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
|
|---|
| 95 | 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
|
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 98 | static BOOL (WINAPI *pCertAddStoreToCollection)(HCERTSTORE,HCERTSTORE,DWORD,DWORD);
|
|---|
| 99 | static BOOL (WINAPI *pCertControlStore)(HCERTSTORE,DWORD,DWORD,void const*);
|
|---|
| 100 | static PCCRL_CONTEXT (WINAPI *pCertEnumCRLsInStore)(HCERTSTORE,PCCRL_CONTEXT);
|
|---|
| 101 | static BOOL (WINAPI *pCertEnumSystemStore)(DWORD,void*,void*,PFN_CERT_ENUM_SYSTEM_STORE);
|
|---|
| 102 | static BOOL (WINAPI *pCertGetStoreProperty)(HCERTSTORE,DWORD,void*,DWORD*);
|
|---|
| 103 | static void (WINAPI *pCertRemoveStoreFromCollection)(HCERTSTORE,HCERTSTORE);
|
|---|
| 104 | static BOOL (WINAPI *pCertSetStoreProperty)(HCERTSTORE,DWORD,DWORD,const void*);
|
|---|
| 105 |
|
|---|
| 106 | static void testMemStore(void)
|
|---|
| 107 | {
|
|---|
| 108 | HCERTSTORE store1, store2;
|
|---|
| 109 | PCCERT_CONTEXT context;
|
|---|
| 110 | BOOL ret;
|
|---|
| 111 | DWORD GLE;
|
|---|
| 112 |
|
|---|
| 113 | /* NULL provider */
|
|---|
| 114 | store1 = CertOpenStore(0, 0, 0, 0, NULL);
|
|---|
| 115 | ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 116 | "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
|---|
| 117 | /* weird flags */
|
|---|
| 118 | store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 119 | CERT_STORE_DELETE_FLAG, NULL);
|
|---|
| 120 | ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
|
|---|
| 121 | "Expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
|
|---|
| 122 |
|
|---|
| 123 | /* normal */
|
|---|
| 124 | store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 125 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 126 | ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
|
|---|
| 127 | /* open existing doesn't */
|
|---|
| 128 | store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 129 | CERT_STORE_OPEN_EXISTING_FLAG, NULL);
|
|---|
| 130 | ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError());
|
|---|
| 131 | ok(store1 != store2, "Expected different stores\n");
|
|---|
| 132 |
|
|---|
| 133 | /* add a bogus (empty) cert */
|
|---|
| 134 | context = NULL;
|
|---|
| 135 | ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
|
|---|
| 136 | sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
|
|---|
| 137 | /* Windows returns CRYPT_E_ASN1_EOD or OSS_DATA_ERROR, but accept
|
|---|
| 138 | * CRYPT_E_ASN1_CORRUPT as well (because matching errors is tough in this
|
|---|
| 139 | * case)
|
|---|
| 140 | */
|
|---|
| 141 | GLE = GetLastError();
|
|---|
| 142 | ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == CRYPT_E_ASN1_CORRUPT ||
|
|---|
| 143 | GLE == OSS_DATA_ERROR),
|
|---|
| 144 | "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
|
|---|
| 145 | GLE);
|
|---|
| 146 | /* add a "signed" cert--the signature isn't a real signature, so this adds
|
|---|
| 147 | * without any check of the signature's validity
|
|---|
| 148 | */
|
|---|
| 149 | ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
|
|---|
| 150 | signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
|
|---|
| 151 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
|---|
| 152 | ok(context != NULL, "Expected a valid cert context\n");
|
|---|
| 153 | if (context)
|
|---|
| 154 | {
|
|---|
| 155 | ok(context->cbCertEncoded == sizeof(signedBigCert),
|
|---|
| 156 | "Wrong cert size %d\n", context->cbCertEncoded);
|
|---|
| 157 | ok(!memcmp(context->pbCertEncoded, signedBigCert,
|
|---|
| 158 | sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
|
|---|
| 159 | /* remove it, the rest of the tests will work on an unsigned cert */
|
|---|
| 160 | ret = CertDeleteCertificateFromStore(context);
|
|---|
| 161 | ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
|
|---|
| 162 | GetLastError());
|
|---|
| 163 | }
|
|---|
| 164 | /* try adding a "signed" CRL as a cert */
|
|---|
| 165 | ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
|
|---|
| 166 | signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
|
|---|
| 167 | GLE = GetLastError();
|
|---|
| 168 | ok(!ret && (GLE == CRYPT_E_ASN1_BADTAG || GLE == CRYPT_E_ASN1_CORRUPT ||
|
|---|
| 169 | GLE == OSS_DATA_ERROR),
|
|---|
| 170 | "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
|
|---|
| 171 | GLE);
|
|---|
| 172 | /* add a cert to store1 */
|
|---|
| 173 | ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
|
|---|
| 174 | sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
|
|---|
| 175 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
|---|
| 176 | ok(context != NULL, "Expected a valid cert context\n");
|
|---|
| 177 | if (context)
|
|---|
| 178 | {
|
|---|
| 179 | DWORD size;
|
|---|
| 180 | BYTE *buf;
|
|---|
| 181 |
|
|---|
| 182 | ok(context->cbCertEncoded == sizeof(bigCert),
|
|---|
| 183 | "Wrong cert size %d\n", context->cbCertEncoded);
|
|---|
| 184 | ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
|
|---|
| 185 | "Unexpected encoded cert in context\n");
|
|---|
| 186 | ok(context->hCertStore == store1, "Unexpected store\n");
|
|---|
| 187 |
|
|---|
| 188 | /* check serializing this element */
|
|---|
| 189 | /* These crash
|
|---|
| 190 | ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
|
|---|
| 191 | ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
|
|---|
| 192 | ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
|
|---|
| 193 | */
|
|---|
| 194 | /* apparently flags are ignored */
|
|---|
| 195 | ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
|
|---|
| 196 | ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
|
|---|
| 197 | GetLastError());
|
|---|
| 198 | buf = HeapAlloc(GetProcessHeap(), 0, size);
|
|---|
| 199 | if (buf)
|
|---|
| 200 | {
|
|---|
| 201 | ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
|
|---|
| 202 | ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
|
|---|
| 203 | ok(!memcmp(serializedCert, buf, size),
|
|---|
| 204 | "Unexpected serialized cert\n");
|
|---|
| 205 | HeapFree(GetProcessHeap(), 0, buf);
|
|---|
| 206 | }
|
|---|
| 207 |
|
|---|
| 208 | ret = CertFreeCertificateContext(context);
|
|---|
| 209 | ok(ret, "CertFreeCertificateContext failed: %08x\n", GetLastError());
|
|---|
| 210 | }
|
|---|
| 211 | /* verify the cert's in store1 */
|
|---|
| 212 | context = CertEnumCertificatesInStore(store1, NULL);
|
|---|
| 213 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 214 | context = CertEnumCertificatesInStore(store1, context);
|
|---|
| 215 | ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
|
|---|
| 216 | "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 217 | /* verify store2 (the "open existing" mem store) is still empty */
|
|---|
| 218 | context = CertEnumCertificatesInStore(store2, NULL);
|
|---|
| 219 | ok(!context, "Expected an empty store\n");
|
|---|
| 220 | /* delete the cert from store1, and check it's empty */
|
|---|
| 221 | context = CertEnumCertificatesInStore(store1, NULL);
|
|---|
| 222 | if (context)
|
|---|
| 223 | {
|
|---|
| 224 | /* Deleting a bitwise copy crashes with an access to an uninitialized
|
|---|
| 225 | * pointer, so a cert context has some special data out there in memory
|
|---|
| 226 | * someplace
|
|---|
| 227 | CERT_CONTEXT copy;
|
|---|
| 228 | memcpy(©, context, sizeof(copy));
|
|---|
| 229 | ret = CertDeleteCertificateFromStore(©);
|
|---|
| 230 | */
|
|---|
| 231 | PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
|
|---|
| 232 |
|
|---|
| 233 | ok(copy != NULL, "CertDuplicateCertificateContext failed: %08x\n",
|
|---|
| 234 | GetLastError());
|
|---|
| 235 | ret = CertDeleteCertificateFromStore(context);
|
|---|
| 236 | ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
|
|---|
| 237 | GetLastError());
|
|---|
| 238 | /* try deleting a copy */
|
|---|
| 239 | ret = CertDeleteCertificateFromStore(copy);
|
|---|
| 240 | ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
|
|---|
| 241 | GetLastError());
|
|---|
| 242 | /* check that the store is empty */
|
|---|
| 243 | context = CertEnumCertificatesInStore(store1, NULL);
|
|---|
| 244 | ok(!context, "Expected an empty store\n");
|
|---|
| 245 | }
|
|---|
| 246 |
|
|---|
| 247 | /* close an empty store */
|
|---|
| 248 | ret = CertCloseStore(NULL, 0);
|
|---|
| 249 | ok(ret, "CertCloseStore failed: %d\n", GetLastError());
|
|---|
| 250 | ret = CertCloseStore(store1, 0);
|
|---|
| 251 | ok(ret, "CertCloseStore failed: %d\n", GetLastError());
|
|---|
| 252 | ret = CertCloseStore(store2, 0);
|
|---|
| 253 | ok(ret, "CertCloseStore failed: %d\n", GetLastError());
|
|---|
| 254 |
|
|---|
| 255 | /* This seems nonsensical, but you can open a read-only mem store, only
|
|---|
| 256 | * it isn't read-only
|
|---|
| 257 | */
|
|---|
| 258 | store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 259 | CERT_STORE_READONLY_FLAG, NULL);
|
|---|
| 260 | ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
|
|---|
| 261 | /* yep, this succeeds */
|
|---|
| 262 | ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
|
|---|
| 263 | sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
|
|---|
| 264 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
|---|
| 265 | ok(context != NULL, "Expected a valid cert context\n");
|
|---|
| 266 | if (context)
|
|---|
| 267 | {
|
|---|
| 268 | ok(context->cbCertEncoded == sizeof(bigCert),
|
|---|
| 269 | "Wrong cert size %d\n", context->cbCertEncoded);
|
|---|
| 270 | ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
|
|---|
| 271 | "Unexpected encoded cert in context\n");
|
|---|
| 272 | ok(context->hCertStore == store1, "Unexpected store\n");
|
|---|
| 273 | ret = CertDeleteCertificateFromStore(context);
|
|---|
| 274 | ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
|
|---|
| 275 | GetLastError());
|
|---|
| 276 | }
|
|---|
| 277 | CertCloseStore(store1, 0);
|
|---|
| 278 | }
|
|---|
| 279 |
|
|---|
| 280 | static void testCollectionStore(void)
|
|---|
| 281 | {
|
|---|
| 282 | HCERTSTORE store1, store2, collection, collection2;
|
|---|
| 283 | PCCERT_CONTEXT context;
|
|---|
| 284 | BOOL ret;
|
|---|
| 285 |
|
|---|
| 286 | if (!pCertAddStoreToCollection)
|
|---|
| 287 | {
|
|---|
| 288 | skip("CertAddStoreToCollection() is not available\n");
|
|---|
| 289 | return;
|
|---|
| 290 | }
|
|---|
| 291 |
|
|---|
| 292 | collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
|
|---|
| 293 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 294 |
|
|---|
| 295 | /* Try adding a cert to any empty collection */
|
|---|
| 296 | ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
|
|---|
| 297 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 298 | ok(!ret && GetLastError() == E_ACCESSDENIED,
|
|---|
| 299 | "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
|
|---|
| 300 |
|
|---|
| 301 | /* Create and add a cert to a memory store */
|
|---|
| 302 | store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 303 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 304 | ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
|
|---|
| 305 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 306 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
|---|
| 307 | /* Add the memory store to the collection, without allowing adding */
|
|---|
| 308 | ret = pCertAddStoreToCollection(collection, store1, 0, 0);
|
|---|
| 309 | ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
|
|---|
| 310 | /* Verify the cert is in the collection */
|
|---|
| 311 | context = CertEnumCertificatesInStore(collection, NULL);
|
|---|
| 312 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 313 | if (context)
|
|---|
| 314 | {
|
|---|
| 315 | ok(context->hCertStore == collection, "Unexpected store\n");
|
|---|
| 316 | CertFreeCertificateContext(context);
|
|---|
| 317 | }
|
|---|
| 318 | /* Check that adding to the collection isn't allowed */
|
|---|
| 319 | ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
|
|---|
| 320 | bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 321 | ok(!ret && GetLastError() == E_ACCESSDENIED,
|
|---|
| 322 | "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
|
|---|
| 323 |
|
|---|
| 324 | /* Create a new memory store */
|
|---|
| 325 | store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 326 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 327 | /* Try adding a store to a non-collection store */
|
|---|
| 328 | ret = pCertAddStoreToCollection(store1, store2,
|
|---|
| 329 | CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
|---|
| 330 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 331 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 332 | /* Try adding some bogus stores */
|
|---|
| 333 | /* This crashes in Windows
|
|---|
| 334 | ret = pCertAddStoreToCollection(0, store2,
|
|---|
| 335 | CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
|---|
| 336 | */
|
|---|
| 337 | /* This "succeeds"... */
|
|---|
| 338 | ret = pCertAddStoreToCollection(collection, 0,
|
|---|
| 339 | CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
|---|
| 340 | ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
|
|---|
| 341 | /* while this crashes.
|
|---|
| 342 | ret = pCertAddStoreToCollection(collection, 1,
|
|---|
| 343 | CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
|---|
| 344 | */
|
|---|
| 345 |
|
|---|
| 346 | /* Add it to the collection, this time allowing adding */
|
|---|
| 347 | ret = pCertAddStoreToCollection(collection, store2,
|
|---|
| 348 | CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
|---|
| 349 | ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
|
|---|
| 350 | /* Check that adding to the collection is allowed */
|
|---|
| 351 | ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
|
|---|
| 352 | bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 353 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
|---|
| 354 | /* Now check that it was actually added to store2 */
|
|---|
| 355 | context = CertEnumCertificatesInStore(store2, NULL);
|
|---|
| 356 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 357 | if (context)
|
|---|
| 358 | {
|
|---|
| 359 | ok(context->hCertStore == store2, "Unexpected store\n");
|
|---|
| 360 | CertFreeCertificateContext(context);
|
|---|
| 361 | }
|
|---|
| 362 | /* Check that the collection has both bigCert and bigCert2. bigCert comes
|
|---|
| 363 | * first because store1 was added first.
|
|---|
| 364 | */
|
|---|
| 365 | context = CertEnumCertificatesInStore(collection, NULL);
|
|---|
| 366 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 367 | if (context)
|
|---|
| 368 | {
|
|---|
| 369 | ok(context->hCertStore == collection, "Unexpected store\n");
|
|---|
| 370 | ok(context->cbCertEncoded == sizeof(bigCert),
|
|---|
| 371 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 372 | ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
|
|---|
| 373 | "Unexpected cert\n");
|
|---|
| 374 | context = CertEnumCertificatesInStore(collection, context);
|
|---|
| 375 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 376 | if (context)
|
|---|
| 377 | {
|
|---|
| 378 | ok(context->hCertStore == collection, "Unexpected store\n");
|
|---|
| 379 | ok(context->cbCertEncoded == sizeof(bigCert2),
|
|---|
| 380 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 381 | ok(!memcmp(context->pbCertEncoded, bigCert2,
|
|---|
| 382 | context->cbCertEncoded), "Unexpected cert\n");
|
|---|
| 383 | context = CertEnumCertificatesInStore(collection, context);
|
|---|
| 384 | ok(!context, "Unexpected cert\n");
|
|---|
| 385 | }
|
|---|
| 386 | }
|
|---|
| 387 | /* close store2, and check that the collection is unmodified */
|
|---|
| 388 | CertCloseStore(store2, 0);
|
|---|
| 389 | context = CertEnumCertificatesInStore(collection, NULL);
|
|---|
| 390 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 391 | if (context)
|
|---|
| 392 | {
|
|---|
| 393 | ok(context->hCertStore == collection, "Unexpected store\n");
|
|---|
| 394 | ok(context->cbCertEncoded == sizeof(bigCert),
|
|---|
| 395 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 396 | ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
|
|---|
| 397 | "Unexpected cert\n");
|
|---|
| 398 | context = CertEnumCertificatesInStore(collection, context);
|
|---|
| 399 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 400 | if (context)
|
|---|
| 401 | {
|
|---|
| 402 | ok(context->hCertStore == collection, "Unexpected store\n");
|
|---|
| 403 | ok(context->cbCertEncoded == sizeof(bigCert2),
|
|---|
| 404 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 405 | ok(!memcmp(context->pbCertEncoded, bigCert2,
|
|---|
| 406 | context->cbCertEncoded), "Unexpected cert\n");
|
|---|
| 407 | context = CertEnumCertificatesInStore(collection, context);
|
|---|
| 408 | ok(!context, "Unexpected cert\n");
|
|---|
| 409 | }
|
|---|
| 410 | }
|
|---|
| 411 |
|
|---|
| 412 | /* Adding a collection to a collection is legal */
|
|---|
| 413 | collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
|
|---|
| 414 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 415 | ret = pCertAddStoreToCollection(collection2, collection,
|
|---|
| 416 | CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
|---|
| 417 | ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
|
|---|
| 418 | /* check the contents of collection2 */
|
|---|
| 419 | context = CertEnumCertificatesInStore(collection2, NULL);
|
|---|
| 420 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 421 | if (context)
|
|---|
| 422 | {
|
|---|
| 423 | ok(context->hCertStore == collection2, "Unexpected store\n");
|
|---|
| 424 | ok(context->cbCertEncoded == sizeof(bigCert),
|
|---|
| 425 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 426 | ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
|
|---|
| 427 | "Unexpected cert\n");
|
|---|
| 428 | context = CertEnumCertificatesInStore(collection2, context);
|
|---|
| 429 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 430 | if (context)
|
|---|
| 431 | {
|
|---|
| 432 | ok(context->hCertStore == collection2, "Unexpected store\n");
|
|---|
| 433 | ok(context->cbCertEncoded == sizeof(bigCert2),
|
|---|
| 434 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 435 | ok(!memcmp(context->pbCertEncoded, bigCert2,
|
|---|
| 436 | context->cbCertEncoded), "Unexpected cert\n");
|
|---|
| 437 | context = CertEnumCertificatesInStore(collection2, context);
|
|---|
| 438 | ok(!context, "Unexpected cert\n");
|
|---|
| 439 | }
|
|---|
| 440 | }
|
|---|
| 441 |
|
|---|
| 442 | /* I'd like to test closing the collection in the middle of enumeration,
|
|---|
| 443 | * but my tests have been inconsistent. The first time calling
|
|---|
| 444 | * CertEnumCertificatesInStore on a closed collection succeeded, while the
|
|---|
| 445 | * second crashed. So anything appears to be fair game.
|
|---|
| 446 | * I'd also like to test removing a store from a collection in the middle
|
|---|
| 447 | * of an enumeration, but my tests in Windows have been inconclusive.
|
|---|
| 448 | * In one scenario it worked. In another scenario, about a third of the
|
|---|
| 449 | * time this leads to "random" crashes elsewhere in the code. This
|
|---|
| 450 | * probably means this is not allowed.
|
|---|
| 451 | */
|
|---|
| 452 |
|
|---|
| 453 | CertCloseStore(store1, 0);
|
|---|
| 454 | CertCloseStore(collection, 0);
|
|---|
| 455 | CertCloseStore(collection2, 0);
|
|---|
| 456 |
|
|---|
| 457 | /* Add the same cert to two memory stores, then put them in a collection */
|
|---|
| 458 | store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 459 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 460 | ok(store1 != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 461 | store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 462 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 463 | ok(store2 != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 464 |
|
|---|
| 465 | ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
|
|---|
| 466 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 467 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
|---|
| 468 | ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
|
|---|
| 469 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 470 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
|---|
| 471 | collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
|
|---|
| 472 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 473 | ok(collection != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 474 |
|
|---|
| 475 | ret = pCertAddStoreToCollection(collection, store1,
|
|---|
| 476 | CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
|---|
| 477 | ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
|
|---|
| 478 | ret = pCertAddStoreToCollection(collection, store2,
|
|---|
| 479 | CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
|---|
| 480 | ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
|
|---|
| 481 |
|
|---|
| 482 | /* Check that the collection has two copies of the same cert */
|
|---|
| 483 | context = CertEnumCertificatesInStore(collection, NULL);
|
|---|
| 484 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 485 | if (context)
|
|---|
| 486 | {
|
|---|
| 487 | ok(context->hCertStore == collection, "Unexpected store\n");
|
|---|
| 488 | ok(context->cbCertEncoded == sizeof(bigCert),
|
|---|
| 489 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 490 | ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
|
|---|
| 491 | "Unexpected cert\n");
|
|---|
| 492 | context = CertEnumCertificatesInStore(collection, context);
|
|---|
| 493 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 494 | if (context)
|
|---|
| 495 | {
|
|---|
| 496 | ok(context->hCertStore == collection, "Unexpected store\n");
|
|---|
| 497 | ok(context->cbCertEncoded == sizeof(bigCert),
|
|---|
| 498 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 499 | ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
|
|---|
| 500 | "Unexpected cert\n");
|
|---|
| 501 | context = CertEnumCertificatesInStore(collection, context);
|
|---|
| 502 | ok(context == NULL, "Unexpected cert\n");
|
|---|
| 503 | }
|
|---|
| 504 | }
|
|---|
| 505 |
|
|---|
| 506 | /* The following would check whether I can delete an identical cert, rather
|
|---|
| 507 | * than one enumerated from the store. It crashes, so that means I must
|
|---|
| 508 | * only call CertDeleteCertificateFromStore with contexts enumerated from
|
|---|
| 509 | * the store.
|
|---|
| 510 | context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
|---|
| 511 | sizeof(bigCert));
|
|---|
| 512 | ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
|
|---|
| 513 | GetLastError());
|
|---|
| 514 | if (context)
|
|---|
| 515 | {
|
|---|
| 516 | ret = CertDeleteCertificateFromStore(collection, context);
|
|---|
| 517 | printf("ret is %d, GetLastError is %08x\n", ret, GetLastError());
|
|---|
| 518 | CertFreeCertificateContext(context);
|
|---|
| 519 | }
|
|---|
| 520 | */
|
|---|
| 521 |
|
|---|
| 522 | /* Now check deleting from the collection. */
|
|---|
| 523 | context = CertEnumCertificatesInStore(collection, NULL);
|
|---|
| 524 | ok(context != NULL, "Expected a valid context\n");
|
|---|
| 525 | if (context)
|
|---|
| 526 | {
|
|---|
| 527 | CertDeleteCertificateFromStore(context);
|
|---|
| 528 | /* store1 should now be empty */
|
|---|
| 529 | context = CertEnumCertificatesInStore(store1, NULL);
|
|---|
| 530 | ok(!context, "Unexpected cert\n");
|
|---|
| 531 | /* and there should be one certificate in the collection */
|
|---|
| 532 | context = CertEnumCertificatesInStore(collection, NULL);
|
|---|
| 533 | ok(context != NULL, "Expected a valid cert\n");
|
|---|
| 534 | if (context)
|
|---|
| 535 | {
|
|---|
| 536 | ok(context->hCertStore == collection, "Unexpected store\n");
|
|---|
| 537 | ok(context->cbCertEncoded == sizeof(bigCert),
|
|---|
| 538 | "Wrong size %d\n", context->cbCertEncoded);
|
|---|
| 539 | ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
|
|---|
| 540 | "Unexpected cert\n");
|
|---|
| 541 | }
|
|---|
| 542 | context = CertEnumCertificatesInStore(collection, context);
|
|---|
| 543 | ok(context == NULL, "Unexpected cert\n");
|
|---|
| 544 | }
|
|---|
| 545 |
|
|---|
| 546 | if (!pCertRemoveStoreFromCollection)
|
|---|
| 547 | {
|
|---|
| 548 | skip("CertRemoveStoreFromCollection() is not available\n");
|
|---|
| 549 | }
|
|---|
| 550 | else
|
|---|
| 551 | {
|
|---|
| 552 | /* Finally, test removing stores from the collection. No return
|
|---|
| 553 | * value, so it's a bit funny to test.
|
|---|
| 554 | */
|
|---|
| 555 | /* This crashes
|
|---|
| 556 | * pCertRemoveStoreFromCollection(NULL, NULL);
|
|---|
| 557 | */
|
|---|
| 558 | /* This "succeeds," no crash, no last error set */
|
|---|
| 559 | SetLastError(0xdeadbeef);
|
|---|
| 560 | pCertRemoveStoreFromCollection(store2, collection);
|
|---|
| 561 | ok(GetLastError() == 0xdeadbeef,
|
|---|
| 562 | "Didn't expect an error to be set: %08x\n", GetLastError());
|
|---|
| 563 |
|
|---|
| 564 | /* After removing store2, the collection should be empty */
|
|---|
| 565 | SetLastError(0xdeadbeef);
|
|---|
| 566 | pCertRemoveStoreFromCollection(collection, store2);
|
|---|
| 567 | ok(GetLastError() == 0xdeadbeef,
|
|---|
| 568 | "Didn't expect an error to be set: %08x\n", GetLastError());
|
|---|
| 569 | context = CertEnumCertificatesInStore(collection, NULL);
|
|---|
| 570 | ok(!context, "Unexpected cert\n");
|
|---|
| 571 | }
|
|---|
| 572 |
|
|---|
| 573 | CertCloseStore(collection, 0);
|
|---|
| 574 | CertCloseStore(store2, 0);
|
|---|
| 575 | CertCloseStore(store1, 0);
|
|---|
| 576 | }
|
|---|
| 577 |
|
|---|
| 578 | /* Looks for the property with ID propID in the buffer buf. Returns a pointer
|
|---|
| 579 | * to its header if found, NULL if not.
|
|---|
| 580 | */
|
|---|
| 581 | static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
|
|---|
| 582 | DWORD propID)
|
|---|
| 583 | {
|
|---|
| 584 | const struct CertPropIDHeader *ret = NULL;
|
|---|
| 585 | BOOL failed = FALSE;
|
|---|
| 586 |
|
|---|
| 587 | while (size && !ret && !failed)
|
|---|
| 588 | {
|
|---|
| 589 | if (size < sizeof(struct CertPropIDHeader))
|
|---|
| 590 | failed = TRUE;
|
|---|
| 591 | else
|
|---|
| 592 | {
|
|---|
| 593 | const struct CertPropIDHeader *hdr =
|
|---|
| 594 | (const struct CertPropIDHeader *)buf;
|
|---|
| 595 |
|
|---|
| 596 | size -= sizeof(struct CertPropIDHeader);
|
|---|
| 597 | buf += sizeof(struct CertPropIDHeader);
|
|---|
| 598 | if (size < hdr->cb)
|
|---|
| 599 | failed = TRUE;
|
|---|
| 600 | else if (hdr->propID == propID)
|
|---|
| 601 | ret = hdr;
|
|---|
| 602 | else
|
|---|
| 603 | {
|
|---|
| 604 | buf += hdr->cb;
|
|---|
| 605 | size -= hdr->cb;
|
|---|
| 606 | }
|
|---|
| 607 | }
|
|---|
| 608 | }
|
|---|
| 609 | return ret;
|
|---|
| 610 | }
|
|---|
| 611 |
|
|---|
| 612 | typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
|
|---|
| 613 |
|
|---|
| 614 | static void testRegStore(void)
|
|---|
| 615 | {
|
|---|
| 616 | static const char tempKey[] = "Software\\Wine\\CryptTemp";
|
|---|
| 617 | HCERTSTORE store;
|
|---|
| 618 | LONG rc;
|
|---|
| 619 | HKEY key = NULL;
|
|---|
| 620 | DWORD disp, GLE;
|
|---|
| 621 |
|
|---|
| 622 | store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
|
|---|
| 623 | GLE = GetLastError();
|
|---|
| 624 | ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
|
|---|
| 625 | "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
|
|---|
| 626 | store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
|
|---|
| 627 | GLE = GetLastError();
|
|---|
| 628 | ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
|
|---|
| 629 | "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
|
|---|
| 630 |
|
|---|
| 631 | /* Opening up any old key works.. */
|
|---|
| 632 | key = HKEY_CURRENT_USER;
|
|---|
| 633 | store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
|
|---|
| 634 | /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
|
|---|
| 635 | */
|
|---|
| 636 | todo_wine ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 637 | CertCloseStore(store, 0);
|
|---|
| 638 |
|
|---|
| 639 | /* It looks like the remainder pretty much needs CertControlStore() */
|
|---|
| 640 | if (!pCertControlStore)
|
|---|
| 641 | {
|
|---|
| 642 | skip("CertControlStore() is not available\n");
|
|---|
| 643 | return;
|
|---|
| 644 | }
|
|---|
| 645 |
|
|---|
| 646 | rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
|
|---|
| 647 | NULL, &key, NULL);
|
|---|
| 648 | ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
|
|---|
| 649 | if (key)
|
|---|
| 650 | {
|
|---|
| 651 | BOOL ret;
|
|---|
| 652 | BYTE hash[20];
|
|---|
| 653 | DWORD size, i;
|
|---|
| 654 | static const char certificates[] = "Certificates\\";
|
|---|
| 655 | char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
|
|---|
| 656 | HKEY subKey;
|
|---|
| 657 | PCCERT_CONTEXT context;
|
|---|
| 658 |
|
|---|
| 659 | store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
|
|---|
| 660 | ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 661 | /* Add a certificate. It isn't persisted right away, since it's only
|
|---|
| 662 | * added to the cache..
|
|---|
| 663 | */
|
|---|
| 664 | ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
|---|
| 665 | bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 666 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
|
|---|
| 667 | GetLastError());
|
|---|
| 668 | /* so flush the cache to force a commit.. */
|
|---|
| 669 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
|---|
| 670 | ok(ret, "CertControlStore failed: %08x\n", GetLastError());
|
|---|
| 671 | /* and check that the expected subkey was written. */
|
|---|
| 672 | size = sizeof(hash);
|
|---|
| 673 | ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
|
|---|
| 674 | hash, &size);
|
|---|
| 675 | ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
|
|---|
| 676 | strcpy(subKeyName, certificates);
|
|---|
| 677 | for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
|
|---|
| 678 | i++, ptr += 2)
|
|---|
| 679 | sprintf(ptr, "%02X", hash[i]);
|
|---|
| 680 | rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
|
|---|
| 681 | &subKey, NULL);
|
|---|
| 682 | ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
|
|---|
| 683 | if (subKey)
|
|---|
| 684 | {
|
|---|
| 685 | LPBYTE buf;
|
|---|
| 686 |
|
|---|
| 687 | size = 0;
|
|---|
| 688 | RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
|
|---|
| 689 | buf = HeapAlloc(GetProcessHeap(), 0, size);
|
|---|
| 690 | if (buf)
|
|---|
| 691 | {
|
|---|
| 692 | rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
|
|---|
| 693 | ok(!rc, "RegQueryValueExA failed: %d\n", rc);
|
|---|
| 694 | if (!rc)
|
|---|
| 695 | {
|
|---|
| 696 | const struct CertPropIDHeader *hdr;
|
|---|
| 697 |
|
|---|
| 698 | /* Both the hash and the cert should be present */
|
|---|
| 699 | hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
|
|---|
| 700 | ok(hdr != NULL, "Expected to find a cert property\n");
|
|---|
| 701 | if (hdr)
|
|---|
| 702 | {
|
|---|
| 703 | ok(hdr->cb == sizeof(bigCert2),
|
|---|
| 704 | "Wrong size %d of cert property\n", hdr->cb);
|
|---|
| 705 | ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), bigCert2,
|
|---|
| 706 | hdr->cb), "Unexpected cert in cert property\n");
|
|---|
| 707 | }
|
|---|
| 708 | hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
|
|---|
| 709 | ok(hdr != NULL, "Expected to find a hash property\n");
|
|---|
| 710 | if (hdr)
|
|---|
| 711 | {
|
|---|
| 712 | ok(hdr->cb == sizeof(hash),
|
|---|
| 713 | "Wrong size %d of hash property\n", hdr->cb);
|
|---|
| 714 | ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), hash,
|
|---|
| 715 | hdr->cb), "Unexpected hash in cert property\n");
|
|---|
| 716 | }
|
|---|
| 717 | }
|
|---|
| 718 | HeapFree(GetProcessHeap(), 0, buf);
|
|---|
| 719 | }
|
|---|
| 720 | RegCloseKey(subKey);
|
|---|
| 721 | }
|
|---|
| 722 |
|
|---|
| 723 | /* Remove the existing context */
|
|---|
| 724 | context = CertEnumCertificatesInStore(store, NULL);
|
|---|
| 725 | ok(context != NULL, "Expected a cert context\n");
|
|---|
| 726 | if (context)
|
|---|
| 727 | CertDeleteCertificateFromStore(context);
|
|---|
| 728 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
|---|
| 729 | ok(ret, "CertControlStore failed: %08x\n", GetLastError());
|
|---|
| 730 |
|
|---|
| 731 | /* Add a serialized cert with a bogus hash directly to the registry */
|
|---|
| 732 | memset(hash, 0, sizeof(hash));
|
|---|
| 733 | strcpy(subKeyName, certificates);
|
|---|
| 734 | for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
|
|---|
| 735 | i < sizeof(hash); i++, ptr += 2)
|
|---|
| 736 | sprintf(ptr, "%02X", hash[i]);
|
|---|
| 737 | rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
|
|---|
| 738 | &subKey, NULL);
|
|---|
| 739 | ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
|
|---|
| 740 | if (subKey)
|
|---|
| 741 | {
|
|---|
| 742 | BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
|
|---|
| 743 | sizeof(bigCert)], *ptr;
|
|---|
| 744 | DWORD certCount = 0;
|
|---|
| 745 | struct CertPropIDHeader *hdr;
|
|---|
| 746 |
|
|---|
| 747 | hdr = (struct CertPropIDHeader *)buf;
|
|---|
| 748 | hdr->propID = CERT_HASH_PROP_ID;
|
|---|
| 749 | hdr->unknown1 = 1;
|
|---|
| 750 | hdr->cb = sizeof(hash);
|
|---|
| 751 | ptr = buf + sizeof(*hdr);
|
|---|
| 752 | memcpy(ptr, hash, sizeof(hash));
|
|---|
| 753 | ptr += sizeof(hash);
|
|---|
| 754 | hdr = (struct CertPropIDHeader *)ptr;
|
|---|
| 755 | hdr->propID = CERT_CERT_PROP_ID;
|
|---|
| 756 | hdr->unknown1 = 1;
|
|---|
| 757 | hdr->cb = sizeof(bigCert);
|
|---|
| 758 | ptr += sizeof(*hdr);
|
|---|
| 759 | memcpy(ptr, bigCert, sizeof(bigCert));
|
|---|
| 760 |
|
|---|
| 761 | rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
|
|---|
| 762 | sizeof(buf));
|
|---|
| 763 | ok(!rc, "RegSetValueExA failed: %d\n", rc);
|
|---|
| 764 |
|
|---|
| 765 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
|
|---|
| 766 | ok(ret, "CertControlStore failed: %08x\n", GetLastError());
|
|---|
| 767 |
|
|---|
| 768 | /* Make sure the bogus hash cert gets loaded. */
|
|---|
| 769 | certCount = 0;
|
|---|
| 770 | context = NULL;
|
|---|
| 771 | do {
|
|---|
| 772 | context = CertEnumCertificatesInStore(store, context);
|
|---|
| 773 | if (context)
|
|---|
| 774 | certCount++;
|
|---|
| 775 | } while (context != NULL);
|
|---|
| 776 | ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount);
|
|---|
| 777 |
|
|---|
| 778 | RegCloseKey(subKey);
|
|---|
| 779 | }
|
|---|
| 780 |
|
|---|
| 781 | /* Add another serialized cert directly to the registry, this time
|
|---|
| 782 | * under the correct key name (named with the correct hash value).
|
|---|
| 783 | */
|
|---|
| 784 | size = sizeof(hash);
|
|---|
| 785 | ret = CryptHashCertificate(0, 0, 0, bigCert2,
|
|---|
| 786 | sizeof(bigCert2), hash, &size);
|
|---|
| 787 | ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
|
|---|
| 788 | strcpy(subKeyName, certificates);
|
|---|
| 789 | for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
|
|---|
| 790 | i < sizeof(hash); i++, ptr += 2)
|
|---|
| 791 | sprintf(ptr, "%02X", hash[i]);
|
|---|
| 792 | rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
|
|---|
| 793 | &subKey, NULL);
|
|---|
| 794 | ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
|
|---|
| 795 | if (subKey)
|
|---|
| 796 | {
|
|---|
| 797 | BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
|
|---|
| 798 | sizeof(bigCert2)], *ptr;
|
|---|
| 799 | DWORD certCount = 0;
|
|---|
| 800 | PCCERT_CONTEXT context;
|
|---|
| 801 | struct CertPropIDHeader *hdr;
|
|---|
| 802 |
|
|---|
| 803 | /* First try with a bogus hash... */
|
|---|
| 804 | hdr = (struct CertPropIDHeader *)buf;
|
|---|
| 805 | hdr->propID = CERT_HASH_PROP_ID;
|
|---|
| 806 | hdr->unknown1 = 1;
|
|---|
| 807 | hdr->cb = sizeof(hash);
|
|---|
| 808 | ptr = buf + sizeof(*hdr);
|
|---|
| 809 | memset(ptr, 0, sizeof(hash));
|
|---|
| 810 | ptr += sizeof(hash);
|
|---|
| 811 | hdr = (struct CertPropIDHeader *)ptr;
|
|---|
| 812 | hdr->propID = CERT_CERT_PROP_ID;
|
|---|
| 813 | hdr->unknown1 = 1;
|
|---|
| 814 | hdr->cb = sizeof(bigCert2);
|
|---|
| 815 | ptr += sizeof(*hdr);
|
|---|
| 816 | memcpy(ptr, bigCert2, sizeof(bigCert2));
|
|---|
| 817 |
|
|---|
| 818 | rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
|
|---|
| 819 | sizeof(buf));
|
|---|
| 820 | ok(!rc, "RegSetValueExA failed: %d\n", rc);
|
|---|
| 821 |
|
|---|
| 822 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
|
|---|
| 823 | ok(ret, "CertControlStore failed: %08x\n", GetLastError());
|
|---|
| 824 |
|
|---|
| 825 | /* and make sure just one cert still gets loaded. */
|
|---|
| 826 | certCount = 0;
|
|---|
| 827 | context = NULL;
|
|---|
| 828 | do {
|
|---|
| 829 | context = CertEnumCertificatesInStore(store, context);
|
|---|
| 830 | if (context)
|
|---|
| 831 | certCount++;
|
|---|
| 832 | } while (context != NULL);
|
|---|
| 833 | ok(certCount == 1 ||
|
|---|
| 834 | broken(certCount == 2), /* win9x */
|
|---|
| 835 | "Expected 1 certificates, got %d\n", certCount);
|
|---|
| 836 |
|
|---|
| 837 | /* Try again with the correct hash... */
|
|---|
| 838 | ptr = buf + sizeof(*hdr);
|
|---|
| 839 | memcpy(ptr, hash, sizeof(hash));
|
|---|
| 840 |
|
|---|
| 841 | rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
|
|---|
| 842 | sizeof(buf));
|
|---|
| 843 | ok(!rc, "RegSetValueExA failed: %d\n", rc);
|
|---|
| 844 |
|
|---|
| 845 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
|
|---|
| 846 | ok(ret, "CertControlStore failed: %08x\n", GetLastError());
|
|---|
| 847 |
|
|---|
| 848 | /* and make sure two certs get loaded. */
|
|---|
| 849 | certCount = 0;
|
|---|
| 850 | context = NULL;
|
|---|
| 851 | do {
|
|---|
| 852 | context = CertEnumCertificatesInStore(store, context);
|
|---|
| 853 | if (context)
|
|---|
| 854 | certCount++;
|
|---|
| 855 | } while (context != NULL);
|
|---|
| 856 | ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount);
|
|---|
| 857 |
|
|---|
| 858 | RegCloseKey(subKey);
|
|---|
| 859 | }
|
|---|
| 860 | CertCloseStore(store, 0);
|
|---|
| 861 | /* Is delete allowed on a reg store? */
|
|---|
| 862 | store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
|
|---|
| 863 | CERT_STORE_DELETE_FLAG, key);
|
|---|
| 864 | ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
|
|---|
| 865 | ok(GetLastError() == 0, "CertOpenStore failed: %08x\n",
|
|---|
| 866 | GetLastError());
|
|---|
| 867 |
|
|---|
| 868 | RegCloseKey(key);
|
|---|
| 869 | }
|
|---|
| 870 | /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
|
|---|
| 871 | * contents of the key, but not the key itself.
|
|---|
| 872 | */
|
|---|
| 873 | rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
|
|---|
| 874 | NULL, &key, &disp);
|
|---|
| 875 | ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
|
|---|
| 876 | ok(disp == REG_OPENED_EXISTING_KEY,
|
|---|
| 877 | "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp);
|
|---|
| 878 | if (!rc)
|
|---|
| 879 | {
|
|---|
| 880 | RegCloseKey(key);
|
|---|
| 881 | rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
|
|---|
| 882 | if (rc)
|
|---|
| 883 | {
|
|---|
| 884 | HMODULE shlwapi = LoadLibraryA("shlwapi");
|
|---|
| 885 |
|
|---|
| 886 | /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
|
|---|
| 887 | * otherwise subsequent tests will fail.
|
|---|
| 888 | */
|
|---|
| 889 | if (shlwapi)
|
|---|
| 890 | {
|
|---|
| 891 | SHDeleteKeyAFunc pSHDeleteKeyA =
|
|---|
| 892 | (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
|
|---|
| 893 |
|
|---|
| 894 | if (pSHDeleteKeyA)
|
|---|
| 895 | pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
|
|---|
| 896 | FreeLibrary(shlwapi);
|
|---|
| 897 | }
|
|---|
| 898 | }
|
|---|
| 899 | }
|
|---|
| 900 | }
|
|---|
| 901 |
|
|---|
| 902 | static const char MyA[] = { 'M','y',0,0 };
|
|---|
| 903 | static const WCHAR MyW[] = { 'M','y',0 };
|
|---|
| 904 | static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
|
|---|
| 905 | static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
|
|---|
| 906 | 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
|
|---|
| 907 | 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
|
|---|
| 908 |
|
|---|
| 909 | static void testSystemRegStore(void)
|
|---|
| 910 | {
|
|---|
| 911 | HCERTSTORE store, memStore;
|
|---|
| 912 |
|
|---|
| 913 | /* Check with a UNICODE name */
|
|---|
| 914 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
|
|---|
| 915 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
|
|---|
| 916 | /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
|
|---|
| 917 | * testing if they don't.
|
|---|
| 918 | */
|
|---|
| 919 | if (!store)
|
|---|
| 920 | return;
|
|---|
| 921 |
|
|---|
| 922 | /* Check that it isn't a collection store */
|
|---|
| 923 | memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 924 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 925 | if (memStore)
|
|---|
| 926 | {
|
|---|
| 927 | if (pCertAddStoreToCollection)
|
|---|
| 928 | {
|
|---|
| 929 | BOOL ret = pCertAddStoreToCollection(store, memStore, 0, 0);
|
|---|
| 930 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 931 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 932 | }
|
|---|
| 933 | CertCloseStore(memStore, 0);
|
|---|
| 934 | }
|
|---|
| 935 | CertCloseStore(store, 0);
|
|---|
| 936 |
|
|---|
| 937 | /* Check opening a bogus store */
|
|---|
| 938 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
|
|---|
| 939 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
|
|---|
| 940 | ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 941 | "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 942 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
|
|---|
| 943 | CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
|
|---|
| 944 | ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 945 | if (store)
|
|---|
| 946 | CertCloseStore(store, 0);
|
|---|
| 947 | /* Now check whether deleting is allowed */
|
|---|
| 948 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
|
|---|
| 949 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
|
|---|
| 950 | RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
|
|---|
| 951 |
|
|---|
| 952 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
|
|---|
| 953 | ok(!store && GetLastError() == E_INVALIDARG,
|
|---|
| 954 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 955 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
|
|---|
| 956 | CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
|
|---|
| 957 | ok(!store && GetLastError() == E_INVALIDARG,
|
|---|
| 958 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 959 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
|
|---|
| 960 | CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
|
|---|
| 961 | ok(!store && GetLastError() == E_INVALIDARG,
|
|---|
| 962 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 963 | /* The name is expected to be UNICODE, check with an ASCII name */
|
|---|
| 964 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
|
|---|
| 965 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
|
|---|
| 966 | ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 967 | "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 968 | }
|
|---|
| 969 |
|
|---|
| 970 | static void testSystemStore(void)
|
|---|
| 971 | {
|
|---|
| 972 | static const WCHAR baskslashW[] = { '\\',0 };
|
|---|
| 973 | HCERTSTORE store;
|
|---|
| 974 | WCHAR keyName[MAX_PATH];
|
|---|
| 975 | HKEY key;
|
|---|
| 976 | LONG rc;
|
|---|
| 977 |
|
|---|
| 978 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
|
|---|
| 979 | ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 980 | "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 981 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 982 | CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
|
|---|
| 983 | ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 984 | "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 985 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 986 | CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
|
|---|
| 987 | ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 988 | "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 989 | /* The name is expected to be UNICODE, first check with an ASCII name */
|
|---|
| 990 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 991 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
|
|---|
| 992 | ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 993 | "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 994 | /* Create the expected key */
|
|---|
| 995 | lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
|
|---|
| 996 | lstrcatW(keyName, baskslashW);
|
|---|
| 997 | lstrcatW(keyName, MyW);
|
|---|
| 998 | rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
|
|---|
| 999 | NULL, &key, NULL);
|
|---|
| 1000 | ok(!rc, "RegCreateKeyEx failed: %d\n", rc);
|
|---|
| 1001 | if (!rc)
|
|---|
| 1002 | RegCloseKey(key);
|
|---|
| 1003 | /* Check opening with a UNICODE name, specifying the create new flag */
|
|---|
| 1004 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 1005 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
|
|---|
| 1006 | ok(!store && GetLastError() == ERROR_FILE_EXISTS,
|
|---|
| 1007 | "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
|
|---|
| 1008 | /* Now check opening with a UNICODE name, this time opening existing */
|
|---|
| 1009 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 1010 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
|
|---|
| 1011 | ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1012 | if (store)
|
|---|
| 1013 | {
|
|---|
| 1014 | HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 1015 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 1016 |
|
|---|
| 1017 | /* Check that it's a collection store */
|
|---|
| 1018 | if (memStore)
|
|---|
| 1019 | {
|
|---|
| 1020 | if (pCertAddStoreToCollection)
|
|---|
| 1021 | {
|
|---|
| 1022 | BOOL ret = pCertAddStoreToCollection(store, memStore, 0, 0);
|
|---|
| 1023 | /* FIXME: this'll fail on NT4, but what error will it give? */
|
|---|
| 1024 | ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
|
|---|
| 1025 | }
|
|---|
| 1026 | CertCloseStore(memStore, 0);
|
|---|
| 1027 | }
|
|---|
| 1028 | CertCloseStore(store, 0);
|
|---|
| 1029 | }
|
|---|
| 1030 |
|
|---|
| 1031 | /* Check opening a bogus store */
|
|---|
| 1032 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 1033 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
|
|---|
| 1034 | ok((!store ||
|
|---|
| 1035 | broken(store != 0)) && /* win9x */
|
|---|
| 1036 | GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 1037 | "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 1038 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 1039 | CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
|
|---|
| 1040 | ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1041 | if (store)
|
|---|
| 1042 | CertCloseStore(store, 0);
|
|---|
| 1043 | /* Now check whether deleting is allowed */
|
|---|
| 1044 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 1045 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
|
|---|
| 1046 | RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
|
|---|
| 1047 | }
|
|---|
| 1048 |
|
|---|
| 1049 | static const BYTE serializedStoreWithCert[] = {
|
|---|
| 1050 | 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
|
|---|
| 1051 | 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
|
|---|
| 1052 | 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
|
|---|
| 1053 | 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
|
|---|
| 1054 | 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
|
|---|
| 1055 | 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
|
|---|
| 1056 | 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
|
|---|
| 1057 | 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
|
|---|
| 1058 | 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
|
|---|
| 1059 | 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
|
|---|
| 1060 | 0x00,0x00,0x00,0x00,0x00,0x00 };
|
|---|
| 1061 | static const BYTE serializedStoreWithCertAndCRL[] = {
|
|---|
| 1062 | 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
|
|---|
| 1063 | 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
|
|---|
| 1064 | 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
|
|---|
| 1065 | 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
|
|---|
| 1066 | 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
|
|---|
| 1067 | 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
|
|---|
| 1068 | 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
|
|---|
| 1069 | 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
|
|---|
| 1070 | 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
|
|---|
| 1071 | 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00,
|
|---|
| 1072 | 0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,
|
|---|
| 1073 | 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
|
|---|
| 1074 | 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
|
|---|
| 1075 | 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11,
|
|---|
| 1076 | 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
|
|---|
| 1077 | 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
|---|
| 1078 |
|
|---|
| 1079 | static void compareFile(LPCWSTR filename, const BYTE *pb, DWORD cb)
|
|---|
| 1080 | {
|
|---|
| 1081 | HANDLE h;
|
|---|
| 1082 | BYTE buf[200];
|
|---|
| 1083 | BOOL ret;
|
|---|
| 1084 | DWORD cbRead = 0, totalRead = 0;
|
|---|
| 1085 |
|
|---|
| 1086 | h = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
|
|---|
| 1087 | FILE_ATTRIBUTE_NORMAL, NULL);
|
|---|
| 1088 | if (h == INVALID_HANDLE_VALUE)
|
|---|
| 1089 | return;
|
|---|
| 1090 | do {
|
|---|
| 1091 | ret = ReadFile(h, buf, sizeof(buf), &cbRead, NULL);
|
|---|
| 1092 | if (ret && cbRead)
|
|---|
| 1093 | {
|
|---|
| 1094 | ok(totalRead + cbRead <= cb, "Expected total count %d, see %d\n",
|
|---|
| 1095 | cb, totalRead + cbRead);
|
|---|
| 1096 | ok(!memcmp(pb + totalRead, buf, cbRead),
|
|---|
| 1097 | "Unexpected data in file\n");
|
|---|
| 1098 | totalRead += cbRead;
|
|---|
| 1099 | }
|
|---|
| 1100 | } while (ret && cbRead);
|
|---|
| 1101 | CloseHandle(h);
|
|---|
| 1102 | }
|
|---|
| 1103 |
|
|---|
| 1104 | static void testFileStore(void)
|
|---|
| 1105 | {
|
|---|
| 1106 | static const WCHAR szPrefix[] = { 'c','e','r',0 };
|
|---|
| 1107 | static const WCHAR szDot[] = { '.',0 };
|
|---|
| 1108 | WCHAR filename[MAX_PATH];
|
|---|
| 1109 | HCERTSTORE store;
|
|---|
| 1110 | BOOL ret;
|
|---|
| 1111 | PCCERT_CONTEXT cert;
|
|---|
| 1112 | HANDLE file;
|
|---|
| 1113 |
|
|---|
| 1114 | if (!pCertControlStore)
|
|---|
| 1115 | {
|
|---|
| 1116 | skip("CertControlStore() is not available\n");
|
|---|
| 1117 | return;
|
|---|
| 1118 | }
|
|---|
| 1119 |
|
|---|
| 1120 | store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL);
|
|---|
| 1121 | ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
|
|---|
| 1122 | "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
|
|---|
| 1123 |
|
|---|
| 1124 | if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
|
|---|
| 1125 | return;
|
|---|
| 1126 |
|
|---|
| 1127 | DeleteFileW(filename);
|
|---|
| 1128 | file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
|---|
| 1129 | CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|---|
| 1130 | if (file == INVALID_HANDLE_VALUE)
|
|---|
| 1131 | return;
|
|---|
| 1132 |
|
|---|
| 1133 | store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG,
|
|---|
| 1134 | file);
|
|---|
| 1135 | ok(!store && GetLastError() == E_INVALIDARG,
|
|---|
| 1136 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1137 | store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
|---|
| 1138 | CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file);
|
|---|
| 1139 | ok(!store && GetLastError() == E_INVALIDARG,
|
|---|
| 1140 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1141 |
|
|---|
| 1142 | /* A "read-only" file store.. */
|
|---|
| 1143 | store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
|---|
| 1144 | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file);
|
|---|
| 1145 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1146 | if (store)
|
|---|
| 1147 | {
|
|---|
| 1148 | DWORD size;
|
|---|
| 1149 |
|
|---|
| 1150 | ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
|---|
| 1151 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1152 | /* apparently allows adding certificates.. */
|
|---|
| 1153 | ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
|
|---|
| 1154 | /* but not commits.. */
|
|---|
| 1155 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
|---|
| 1156 | ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
|
|---|
| 1157 | "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
|
|---|
| 1158 | /* It still has certs in memory.. */
|
|---|
| 1159 | cert = CertEnumCertificatesInStore(store, NULL);
|
|---|
| 1160 | ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
|
|---|
| 1161 | GetLastError());
|
|---|
| 1162 | CertFreeCertificateContext(cert);
|
|---|
| 1163 | /* but the file size is still 0. */
|
|---|
| 1164 | size = GetFileSize(file, NULL);
|
|---|
| 1165 | ok(size == 0, "Expected size 0, got %d\n", size);
|
|---|
| 1166 | CertCloseStore(store, 0);
|
|---|
| 1167 | }
|
|---|
| 1168 |
|
|---|
| 1169 | /* The create new flag is allowed.. */
|
|---|
| 1170 | store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
|---|
| 1171 | CERT_STORE_CREATE_NEW_FLAG, file);
|
|---|
| 1172 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1173 | if (store)
|
|---|
| 1174 | {
|
|---|
| 1175 | /* but without the commit enable flag, commits don't happen. */
|
|---|
| 1176 | ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
|---|
| 1177 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1178 | ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
|
|---|
| 1179 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
|---|
| 1180 | ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
|
|---|
| 1181 | "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
|
|---|
| 1182 | CertCloseStore(store, 0);
|
|---|
| 1183 | }
|
|---|
| 1184 | /* as is the open existing flag. */
|
|---|
| 1185 | store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
|---|
| 1186 | CERT_STORE_OPEN_EXISTING_FLAG, file);
|
|---|
| 1187 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1188 | if (store)
|
|---|
| 1189 | {
|
|---|
| 1190 | /* but without the commit enable flag, commits don't happen. */
|
|---|
| 1191 | ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
|---|
| 1192 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1193 | ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
|
|---|
| 1194 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
|---|
| 1195 | ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
|
|---|
| 1196 | "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
|
|---|
| 1197 | CertCloseStore(store, 0);
|
|---|
| 1198 | }
|
|---|
| 1199 | store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
|---|
| 1200 | CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
|
|---|
| 1201 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1202 | if (store)
|
|---|
| 1203 | {
|
|---|
| 1204 | CloseHandle(file);
|
|---|
| 1205 | ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
|---|
| 1206 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1207 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
|
|---|
| 1208 | GetLastError());
|
|---|
| 1209 | /* with commits enabled, commit is allowed */
|
|---|
| 1210 | ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
|---|
| 1211 | ok(ret, "CertControlStore failed: %d\n", ret);
|
|---|
| 1212 | compareFile(filename, serializedStoreWithCert,
|
|---|
| 1213 | sizeof(serializedStoreWithCert));
|
|---|
| 1214 | CertCloseStore(store, 0);
|
|---|
| 1215 | }
|
|---|
| 1216 | file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
|---|
| 1217 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|---|
| 1218 | if (file == INVALID_HANDLE_VALUE)
|
|---|
| 1219 | return;
|
|---|
| 1220 | store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
|---|
| 1221 | CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
|
|---|
| 1222 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1223 | if (store)
|
|---|
| 1224 | {
|
|---|
| 1225 | CloseHandle(file);
|
|---|
| 1226 | ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
|
|---|
| 1227 | sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1228 | ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
|
|---|
| 1229 | CertCloseStore(store, 0);
|
|---|
| 1230 | compareFile(filename, serializedStoreWithCertAndCRL,
|
|---|
| 1231 | sizeof(serializedStoreWithCertAndCRL));
|
|---|
| 1232 | }
|
|---|
| 1233 |
|
|---|
| 1234 | DeleteFileW(filename);
|
|---|
| 1235 | }
|
|---|
| 1236 |
|
|---|
| 1237 | static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb)
|
|---|
| 1238 | {
|
|---|
| 1239 | HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
|---|
| 1240 | CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|---|
| 1241 | BOOL ret;
|
|---|
| 1242 |
|
|---|
| 1243 | if (file != INVALID_HANDLE_VALUE)
|
|---|
| 1244 | {
|
|---|
| 1245 | DWORD written;
|
|---|
| 1246 |
|
|---|
| 1247 | ret = WriteFile(file, pb, cb, &written, NULL);
|
|---|
| 1248 | CloseHandle(file);
|
|---|
| 1249 | }
|
|---|
| 1250 | else
|
|---|
| 1251 | ret = FALSE;
|
|---|
| 1252 | return ret;
|
|---|
| 1253 | }
|
|---|
| 1254 | static void testFileNameStore(void)
|
|---|
| 1255 | {
|
|---|
| 1256 | static const WCHAR szPrefix[] = { 'c','e','r',0 };
|
|---|
| 1257 | static const WCHAR szDot[] = { '.',0 };
|
|---|
| 1258 | WCHAR filename[MAX_PATH];
|
|---|
| 1259 | HCERTSTORE store;
|
|---|
| 1260 | BOOL ret;
|
|---|
| 1261 | DWORD GLE;
|
|---|
| 1262 |
|
|---|
| 1263 | if (0)
|
|---|
| 1264 | {
|
|---|
| 1265 | /* Crashes on NT4 */
|
|---|
| 1266 | store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
|
|---|
| 1267 | GLE = GetLastError();
|
|---|
| 1268 | ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
|
|---|
| 1269 | "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
|
|---|
| 1270 | GLE);
|
|---|
| 1271 | }
|
|---|
| 1272 |
|
|---|
| 1273 | if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
|
|---|
| 1274 | return;
|
|---|
| 1275 | DeleteFileW(filename);
|
|---|
| 1276 |
|
|---|
| 1277 | /* The two flags are mutually exclusive */
|
|---|
| 1278 | store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
|
|---|
| 1279 | CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
|
|---|
| 1280 | ok(!store && GetLastError() == E_INVALIDARG,
|
|---|
| 1281 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1282 |
|
|---|
| 1283 | /* In all of the following tests, the encoding type seems to be ignored */
|
|---|
| 1284 | if (initFileFromData(filename, bigCert, sizeof(bigCert)))
|
|---|
| 1285 | {
|
|---|
| 1286 | PCCERT_CONTEXT cert;
|
|---|
| 1287 | PCCRL_CONTEXT crl;
|
|---|
| 1288 |
|
|---|
| 1289 | store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
|
|---|
| 1290 | CERT_STORE_READONLY_FLAG, filename);
|
|---|
| 1291 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1292 |
|
|---|
| 1293 | cert = CertEnumCertificatesInStore(store, NULL);
|
|---|
| 1294 | ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
|
|---|
| 1295 | GetLastError());
|
|---|
| 1296 | cert = CertEnumCertificatesInStore(store, cert);
|
|---|
| 1297 | ok(!cert, "Expected only one cert\n");
|
|---|
| 1298 | if (pCertEnumCRLsInStore)
|
|---|
| 1299 | {
|
|---|
| 1300 | crl = pCertEnumCRLsInStore(store, NULL);
|
|---|
| 1301 | ok(!crl, "Expected no CRLs\n");
|
|---|
| 1302 | }
|
|---|
| 1303 |
|
|---|
| 1304 | CertCloseStore(store, 0);
|
|---|
| 1305 | DeleteFileW(filename);
|
|---|
| 1306 | }
|
|---|
| 1307 | if (initFileFromData(filename, serializedStoreWithCert,
|
|---|
| 1308 | sizeof(serializedStoreWithCert)))
|
|---|
| 1309 | {
|
|---|
| 1310 | PCCERT_CONTEXT cert;
|
|---|
| 1311 | PCCRL_CONTEXT crl;
|
|---|
| 1312 |
|
|---|
| 1313 | store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
|
|---|
| 1314 | CERT_STORE_READONLY_FLAG, filename);
|
|---|
| 1315 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1316 |
|
|---|
| 1317 | cert = CertEnumCertificatesInStore(store, NULL);
|
|---|
| 1318 | ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
|
|---|
| 1319 | GetLastError());
|
|---|
| 1320 | cert = CertEnumCertificatesInStore(store, cert);
|
|---|
| 1321 | ok(!cert, "Expected only one cert\n");
|
|---|
| 1322 | if (pCertEnumCRLsInStore)
|
|---|
| 1323 | {
|
|---|
| 1324 | crl = pCertEnumCRLsInStore(store, NULL);
|
|---|
| 1325 | ok(!crl, "Expected no CRLs\n");
|
|---|
| 1326 | }
|
|---|
| 1327 |
|
|---|
| 1328 | CertCloseStore(store, 0);
|
|---|
| 1329 | DeleteFileW(filename);
|
|---|
| 1330 | }
|
|---|
| 1331 | if (initFileFromData(filename, serializedStoreWithCertAndCRL,
|
|---|
| 1332 | sizeof(serializedStoreWithCertAndCRL)))
|
|---|
| 1333 | {
|
|---|
| 1334 | PCCERT_CONTEXT cert;
|
|---|
| 1335 | PCCRL_CONTEXT crl;
|
|---|
| 1336 |
|
|---|
| 1337 | store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
|
|---|
| 1338 | CERT_STORE_READONLY_FLAG, filename);
|
|---|
| 1339 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1340 |
|
|---|
| 1341 | cert = CertEnumCertificatesInStore(store, NULL);
|
|---|
| 1342 | ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
|
|---|
| 1343 | GetLastError());
|
|---|
| 1344 | cert = CertEnumCertificatesInStore(store, cert);
|
|---|
| 1345 | ok(!cert, "Expected only one cert\n");
|
|---|
| 1346 | if (pCertEnumCRLsInStore)
|
|---|
| 1347 | {
|
|---|
| 1348 | crl = pCertEnumCRLsInStore(store, NULL);
|
|---|
| 1349 | ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
|
|---|
| 1350 | crl = pCertEnumCRLsInStore(store, crl);
|
|---|
| 1351 | ok(!crl, "Expected only one CRL\n");
|
|---|
| 1352 | }
|
|---|
| 1353 |
|
|---|
| 1354 | CertCloseStore(store, 0);
|
|---|
| 1355 | /* Don't delete it this time, the next test uses it */
|
|---|
| 1356 | }
|
|---|
| 1357 | /* Now that the file exists, we can open it read-only */
|
|---|
| 1358 | store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
|
|---|
| 1359 | CERT_STORE_READONLY_FLAG, filename);
|
|---|
| 1360 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1361 | CertCloseStore(store, 0);
|
|---|
| 1362 | DeleteFileW(filename);
|
|---|
| 1363 |
|
|---|
| 1364 | store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
|
|---|
| 1365 | CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
|
|---|
| 1366 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1367 | if (store)
|
|---|
| 1368 | {
|
|---|
| 1369 | ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
|---|
| 1370 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1371 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
|
|---|
| 1372 | GetLastError());
|
|---|
| 1373 | CertCloseStore(store, 0);
|
|---|
| 1374 | compareFile(filename, serializedStoreWithCert,
|
|---|
| 1375 | sizeof(serializedStoreWithCert));
|
|---|
| 1376 | }
|
|---|
| 1377 | store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
|
|---|
| 1378 | CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
|
|---|
| 1379 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1380 | if (store)
|
|---|
| 1381 | {
|
|---|
| 1382 | ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
|
|---|
| 1383 | signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1384 | ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
|
|---|
| 1385 | CertCloseStore(store, 0);
|
|---|
| 1386 | compareFile(filename, serializedStoreWithCertAndCRL,
|
|---|
| 1387 | sizeof(serializedStoreWithCertAndCRL));
|
|---|
| 1388 | }
|
|---|
| 1389 | DeleteFileW(filename);
|
|---|
| 1390 | }
|
|---|
| 1391 |
|
|---|
| 1392 | static const BYTE signedContent[] = {
|
|---|
| 1393 | 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
|---|
| 1394 | 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
|---|
| 1395 | 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
|
|---|
| 1396 | 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
|
|---|
| 1397 | 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
|
|---|
| 1398 | 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
|---|
| 1399 | 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|---|
| 1400 | 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
|
|---|
| 1401 | 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
|
|---|
| 1402 | 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
|
|---|
| 1403 | 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
|
|---|
| 1404 | 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
|
|---|
| 1405 | 0x0d };
|
|---|
| 1406 | static const BYTE signedWithCertAndCrlBareContent[] = {
|
|---|
| 1407 | 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
|
|---|
| 1408 | 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
|
|---|
| 1409 | 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
|
|---|
| 1410 | 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
|
|---|
| 1411 | 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
|
|---|
| 1412 | 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
|
|---|
| 1413 | 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
|
|---|
| 1414 | 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
|
|---|
| 1415 | 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
|---|
| 1416 | 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
|
|---|
| 1417 | 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
|
|---|
| 1418 | 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
|
|---|
| 1419 | 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
|
|---|
| 1420 | 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
|
|---|
| 1421 | 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
|
|---|
| 1422 | 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
|
|---|
| 1423 | 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
|
|---|
| 1424 | 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
|
|---|
| 1425 | 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
|
|---|
| 1426 | 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
|
|---|
| 1427 | 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
|
|---|
| 1428 | 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
|
|---|
| 1429 | 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
|
|---|
| 1430 | static const BYTE hashContent[] = {
|
|---|
| 1431 | 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
|
|---|
| 1432 | 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|---|
| 1433 | 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
|---|
| 1434 | 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
|
|---|
| 1435 | 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
|
|---|
| 1436 | static const BYTE hashBareContent[] = {
|
|---|
| 1437 | 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
|---|
| 1438 | 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
|---|
| 1439 | 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
|
|---|
| 1440 | 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
|
|---|
| 1441 |
|
|---|
| 1442 | static void testMessageStore(void)
|
|---|
| 1443 | {
|
|---|
| 1444 | HCERTSTORE store;
|
|---|
| 1445 | HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
|
|---|
| 1446 | NULL);
|
|---|
| 1447 | CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
|
|---|
| 1448 | (LPBYTE)signedWithCertAndCrlBareContent };
|
|---|
| 1449 | DWORD count, size;
|
|---|
| 1450 | BOOL ret;
|
|---|
| 1451 |
|
|---|
| 1452 | /* Crashes
|
|---|
| 1453 | store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
|
|---|
| 1454 | */
|
|---|
| 1455 | SetLastError(0xdeadbeef);
|
|---|
| 1456 | store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
|
|---|
| 1457 | ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
|
|---|
| 1458 | "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
|
|---|
| 1459 | CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
|
|---|
| 1460 | store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
|
|---|
| 1461 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1462 | if (store)
|
|---|
| 1463 | {
|
|---|
| 1464 | PCCERT_CONTEXT cert = NULL;
|
|---|
| 1465 | PCCRL_CONTEXT crl = NULL;
|
|---|
| 1466 |
|
|---|
| 1467 | count = 0;
|
|---|
| 1468 | do {
|
|---|
| 1469 | cert = CertEnumCertificatesInStore(store, cert);
|
|---|
| 1470 | if (cert)
|
|---|
| 1471 | count++;
|
|---|
| 1472 | } while (cert);
|
|---|
| 1473 | ok(count == 0, "Expected 0 certificates, got %d\n", count);
|
|---|
| 1474 |
|
|---|
| 1475 | if (pCertEnumCRLsInStore)
|
|---|
| 1476 | {
|
|---|
| 1477 | count = 0;
|
|---|
| 1478 | do {
|
|---|
| 1479 | crl = pCertEnumCRLsInStore(store, crl);
|
|---|
| 1480 | if (crl)
|
|---|
| 1481 | count++;
|
|---|
| 1482 | } while (crl);
|
|---|
| 1483 | ok(count == 0, "Expected 0 CRLs, got %d\n", count);
|
|---|
| 1484 | }
|
|---|
| 1485 |
|
|---|
| 1486 | /* Can add certs to a message store */
|
|---|
| 1487 | ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
|
|---|
| 1488 | bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1489 | ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
|
|---|
| 1490 | GetLastError());
|
|---|
| 1491 | count = 0;
|
|---|
| 1492 | do {
|
|---|
| 1493 | cert = CertEnumCertificatesInStore(store, cert);
|
|---|
| 1494 | if (cert)
|
|---|
| 1495 | count++;
|
|---|
| 1496 | } while (cert);
|
|---|
| 1497 | ok(count == 1, "Expected 1 certificate, got %d\n", count);
|
|---|
| 1498 |
|
|---|
| 1499 | CertCloseStore(store, 0);
|
|---|
| 1500 | }
|
|---|
| 1501 | /* but the added certs weren't actually added to the message */
|
|---|
| 1502 | size = sizeof(count);
|
|---|
| 1503 | ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
|
|---|
| 1504 | ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
|
|---|
| 1505 | ok(count == 0, "Expected 0 certificates, got %d\n", count);
|
|---|
| 1506 | CryptMsgClose(msg);
|
|---|
| 1507 |
|
|---|
| 1508 | /* Crashes
|
|---|
| 1509 | store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
|
|---|
| 1510 | */
|
|---|
| 1511 | store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
|
|---|
| 1512 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1513 | if (store)
|
|---|
| 1514 | {
|
|---|
| 1515 | DWORD count = 0;
|
|---|
| 1516 | PCCERT_CONTEXT cert = NULL;
|
|---|
| 1517 | PCCRL_CONTEXT crl = NULL;
|
|---|
| 1518 |
|
|---|
| 1519 | do {
|
|---|
| 1520 | cert = CertEnumCertificatesInStore(store, cert);
|
|---|
| 1521 | if (cert)
|
|---|
| 1522 | count++;
|
|---|
| 1523 | } while (cert);
|
|---|
| 1524 | ok(count == 1, "Expected 1 certificate, got %d\n", count);
|
|---|
| 1525 |
|
|---|
| 1526 | if (pCertEnumCRLsInStore)
|
|---|
| 1527 | {
|
|---|
| 1528 | count = 0;
|
|---|
| 1529 | do {
|
|---|
| 1530 | crl = pCertEnumCRLsInStore(store, crl);
|
|---|
| 1531 | if (crl)
|
|---|
| 1532 | count++;
|
|---|
| 1533 | } while (crl);
|
|---|
| 1534 | ok(count == 1, "Expected 1 CRL, got %d\n", count);
|
|---|
| 1535 | }
|
|---|
| 1536 | CertCloseStore(store, 0);
|
|---|
| 1537 | }
|
|---|
| 1538 | /* Encoding appears to be ignored */
|
|---|
| 1539 | store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
|
|---|
| 1540 | &blob);
|
|---|
| 1541 | ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1542 | if (store)
|
|---|
| 1543 | CertCloseStore(store, 0);
|
|---|
| 1544 | /* Messages other than signed messages aren't allowed */
|
|---|
| 1545 | blob.cbData = sizeof(hashContent);
|
|---|
| 1546 | blob.pbData = (LPBYTE)hashContent;
|
|---|
| 1547 | SetLastError(0xdeadbeef);
|
|---|
| 1548 | store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
|
|---|
| 1549 | ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
|
|---|
| 1550 | "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
|
|---|
| 1551 | blob.cbData = sizeof(hashBareContent);
|
|---|
| 1552 | blob.pbData = (LPBYTE)hashBareContent;
|
|---|
| 1553 | SetLastError(0xdeadbeef);
|
|---|
| 1554 | store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
|
|---|
| 1555 | ok(!store &&
|
|---|
| 1556 | (GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
|---|
| 1557 | GetLastError() == OSS_DATA_ERROR), /* win9x */
|
|---|
| 1558 | "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
|---|
| 1559 | }
|
|---|
| 1560 |
|
|---|
| 1561 | static void testCertOpenSystemStore(void)
|
|---|
| 1562 | {
|
|---|
| 1563 | HCERTSTORE store;
|
|---|
| 1564 |
|
|---|
| 1565 | store = CertOpenSystemStoreW(0, NULL);
|
|---|
| 1566 | ok(!store && GetLastError() == E_INVALIDARG,
|
|---|
| 1567 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1568 | /* This succeeds, and on WinXP at least, the Bogus key is created under
|
|---|
| 1569 | * HKCU (but not under HKLM, even when run as an administrator.)
|
|---|
| 1570 | */
|
|---|
| 1571 | store = CertOpenSystemStoreW(0, BogusW);
|
|---|
| 1572 | ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
|
|---|
| 1573 | if (store)
|
|---|
| 1574 | CertCloseStore(store, 0);
|
|---|
| 1575 | /* Delete it so other tests succeed next time around */
|
|---|
| 1576 | store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
|---|
| 1577 | CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
|
|---|
| 1578 | RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
|
|---|
| 1579 | }
|
|---|
| 1580 |
|
|---|
| 1581 | struct EnumSystemStoreInfo
|
|---|
| 1582 | {
|
|---|
| 1583 | BOOL goOn;
|
|---|
| 1584 | DWORD storeCount;
|
|---|
| 1585 | };
|
|---|
| 1586 |
|
|---|
| 1587 | static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
|
|---|
| 1588 | PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
|
|---|
| 1589 | {
|
|---|
| 1590 | struct EnumSystemStoreInfo *info = (struct EnumSystemStoreInfo *)pvArg;
|
|---|
| 1591 |
|
|---|
| 1592 | info->storeCount++;
|
|---|
| 1593 | return info->goOn;
|
|---|
| 1594 | }
|
|---|
| 1595 |
|
|---|
| 1596 | static void testCertEnumSystemStore(void)
|
|---|
| 1597 | {
|
|---|
| 1598 | BOOL ret;
|
|---|
| 1599 | struct EnumSystemStoreInfo info = { FALSE, 0 };
|
|---|
| 1600 |
|
|---|
| 1601 | if (!pCertEnumSystemStore)
|
|---|
| 1602 | {
|
|---|
| 1603 | skip("CertEnumSystemStore() is not available\n");
|
|---|
| 1604 | return;
|
|---|
| 1605 | }
|
|---|
| 1606 |
|
|---|
| 1607 | SetLastError(0xdeadbeef);
|
|---|
| 1608 | ret = pCertEnumSystemStore(0, NULL, NULL, NULL);
|
|---|
| 1609 | ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 1610 | "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 1611 | /* Crashes
|
|---|
| 1612 | ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
|
|---|
| 1613 | NULL);
|
|---|
| 1614 | */
|
|---|
| 1615 |
|
|---|
| 1616 | SetLastError(0xdeadbeef);
|
|---|
| 1617 | ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
|
|---|
| 1618 | enumSystemStoreCB);
|
|---|
| 1619 | /* Callback returning FALSE stops enumeration */
|
|---|
| 1620 | ok(!ret, "Expected CertEnumSystemStore to stop\n");
|
|---|
| 1621 | ok(info.storeCount == 0 || info.storeCount == 1,
|
|---|
| 1622 | "Expected 0 or 1 stores\n");
|
|---|
| 1623 |
|
|---|
| 1624 | info.goOn = TRUE;
|
|---|
| 1625 | info.storeCount = 0;
|
|---|
| 1626 | ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
|
|---|
| 1627 | enumSystemStoreCB);
|
|---|
| 1628 | ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
|
|---|
| 1629 | /* There should always be at least My, Root, and CA stores */
|
|---|
| 1630 | ok(info.storeCount == 0 || info.storeCount >= 3,
|
|---|
| 1631 | "Expected at least 3 stores\n");
|
|---|
| 1632 | }
|
|---|
| 1633 |
|
|---|
| 1634 | static void testStoreProperty(void)
|
|---|
| 1635 | {
|
|---|
| 1636 | HCERTSTORE store;
|
|---|
| 1637 | BOOL ret;
|
|---|
| 1638 | DWORD propID, size = 0, state;
|
|---|
| 1639 | CRYPT_DATA_BLOB blob;
|
|---|
| 1640 |
|
|---|
| 1641 | if (!pCertGetStoreProperty || !pCertSetStoreProperty)
|
|---|
| 1642 | {
|
|---|
| 1643 | skip("CertGet/SetStoreProperty() is not available\n");
|
|---|
| 1644 | return;
|
|---|
| 1645 | }
|
|---|
| 1646 |
|
|---|
| 1647 | /* Crash
|
|---|
| 1648 | ret = pCertGetStoreProperty(NULL, 0, NULL, NULL);
|
|---|
| 1649 | ret = pCertGetStoreProperty(NULL, 0, NULL, &size);
|
|---|
| 1650 | ret = pCertGetStoreProperty(store, 0, NULL, NULL);
|
|---|
| 1651 | */
|
|---|
| 1652 |
|
|---|
| 1653 | store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 1654 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 1655 | /* Check a missing prop ID */
|
|---|
| 1656 | SetLastError(0xdeadbeef);
|
|---|
| 1657 | ret = pCertGetStoreProperty(store, 0, NULL, &size);
|
|---|
| 1658 | ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
|
|---|
| 1659 | "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 1660 | /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
|
|---|
| 1661 | size = sizeof(state);
|
|---|
| 1662 | ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
|
|---|
| 1663 | ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
|
|---|
| 1664 | GetLastError());
|
|---|
| 1665 | ok(!state, "Expected a non-persisted store\n");
|
|---|
| 1666 | /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
|
|---|
| 1667 | size = 0;
|
|---|
| 1668 | ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
|
|---|
| 1669 | &size);
|
|---|
| 1670 | ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
|
|---|
| 1671 | "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 1672 | /* Delete an arbitrary property on a store */
|
|---|
| 1673 | ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
|
|---|
| 1674 | ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
|
|---|
| 1675 | /* Set an arbitrary property on a store */
|
|---|
| 1676 | blob.pbData = (LPBYTE)&state;
|
|---|
| 1677 | blob.cbData = sizeof(state);
|
|---|
| 1678 | ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
|
|---|
| 1679 | ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
|
|---|
| 1680 | /* Get an arbitrary property that's been set */
|
|---|
| 1681 | ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
|
|---|
| 1682 | ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
|
|---|
| 1683 | ok(size == sizeof(state), "Unexpected data size %d\n", size);
|
|---|
| 1684 | ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
|
|---|
| 1685 | ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
|
|---|
| 1686 | ok(propID == state, "CertGetStoreProperty got the wrong value\n");
|
|---|
| 1687 | /* Delete it again */
|
|---|
| 1688 | ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
|
|---|
| 1689 | ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
|
|---|
| 1690 | /* And check that it's missing */
|
|---|
| 1691 | SetLastError(0xdeadbeef);
|
|---|
| 1692 | ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
|
|---|
| 1693 | ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
|
|---|
| 1694 | "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 1695 | CertCloseStore(store, 0);
|
|---|
| 1696 |
|
|---|
| 1697 | /* Recheck on the My store.. */
|
|---|
| 1698 | store = CertOpenSystemStoreW(0, MyW);
|
|---|
| 1699 | size = sizeof(state);
|
|---|
| 1700 | ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
|
|---|
| 1701 | ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
|
|---|
| 1702 | GetLastError());
|
|---|
| 1703 | ok(state, "Expected a persisted store\n");
|
|---|
| 1704 | SetLastError(0xdeadbeef);
|
|---|
| 1705 | size = 0;
|
|---|
| 1706 | ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
|
|---|
| 1707 | &size);
|
|---|
| 1708 | ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
|
|---|
| 1709 | "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
|---|
| 1710 | CertCloseStore(store, 0);
|
|---|
| 1711 | }
|
|---|
| 1712 |
|
|---|
| 1713 | static void testAddSerialized(void)
|
|---|
| 1714 | {
|
|---|
| 1715 | BOOL ret;
|
|---|
| 1716 | HCERTSTORE store;
|
|---|
| 1717 | BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
|
|---|
| 1718 | { 0 };
|
|---|
| 1719 | BYTE hash[20];
|
|---|
| 1720 | struct CertPropIDHeader *hdr;
|
|---|
| 1721 | PCCERT_CONTEXT context;
|
|---|
| 1722 |
|
|---|
| 1723 | ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
|
|---|
| 1724 | ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
|
|---|
| 1725 | "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
|
|---|
| 1726 |
|
|---|
| 1727 | store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 1728 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 1729 | ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
|
|---|
| 1730 |
|
|---|
| 1731 | ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
|
|---|
| 1732 | ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
|
|---|
| 1733 | "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
|
|---|
| 1734 |
|
|---|
| 1735 | /* Test with an empty property */
|
|---|
| 1736 | hdr = (struct CertPropIDHeader *)buf;
|
|---|
| 1737 | hdr->propID = CERT_CERT_PROP_ID;
|
|---|
| 1738 | hdr->unknown1 = 1;
|
|---|
| 1739 | hdr->cb = 0;
|
|---|
| 1740 | ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
|
|---|
| 1741 | NULL, NULL);
|
|---|
| 1742 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1743 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1744 | /* Test with a bad size in property header */
|
|---|
| 1745 | hdr->cb = sizeof(bigCert) - 1;
|
|---|
| 1746 | memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
|
|---|
| 1747 | ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
|
|---|
| 1748 | NULL, NULL);
|
|---|
| 1749 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1750 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1751 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1752 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
|
|---|
| 1753 | NULL);
|
|---|
| 1754 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1755 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1756 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1757 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
|
|---|
| 1758 | 0, 0, NULL, NULL);
|
|---|
| 1759 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1760 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1761 | /* Kosher size in property header, but no context type */
|
|---|
| 1762 | hdr->cb = sizeof(bigCert);
|
|---|
| 1763 | ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
|
|---|
| 1764 | NULL, NULL);
|
|---|
| 1765 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1766 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1767 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1768 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
|
|---|
| 1769 | NULL);
|
|---|
| 1770 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1771 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1772 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1773 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
|
|---|
| 1774 | 0, 0, NULL, NULL);
|
|---|
| 1775 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1776 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1777 | /* With a bad context type */
|
|---|
| 1778 | ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
|
|---|
| 1779 | CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1780 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1781 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1782 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1783 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
|
|---|
| 1784 | CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1785 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1786 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1787 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1788 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
|
|---|
| 1789 | 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1790 | ok(!ret && GetLastError() == E_INVALIDARG,
|
|---|
| 1791 | "Expected E_INVALIDARG, got %08x\n", GetLastError());
|
|---|
| 1792 | /* Bad unknown field, good type */
|
|---|
| 1793 | hdr->unknown1 = 2;
|
|---|
| 1794 | ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
|
|---|
| 1795 | CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1796 | ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 1797 | "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
|
|---|
| 1798 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1799 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
|
|---|
| 1800 | CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1801 | ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 1802 | "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
|
|---|
| 1803 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1804 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
|
|---|
| 1805 | 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1806 | ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
|---|
| 1807 | "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
|
|---|
| 1808 | /* Most everything okay, but bad add disposition */
|
|---|
| 1809 | hdr->unknown1 = 1;
|
|---|
| 1810 | /* This crashes
|
|---|
| 1811 | ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
|
|---|
| 1812 | CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1813 | * as does this
|
|---|
| 1814 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1815 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
|
|---|
| 1816 | CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1817 | */
|
|---|
| 1818 | /* Everything okay, but buffer's too big */
|
|---|
| 1819 | ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
|
|---|
| 1820 | CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1821 | ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
|
|---|
| 1822 | /* Everything okay, check it's not re-added */
|
|---|
| 1823 | ret = CertAddSerializedElementToStore(store, buf,
|
|---|
| 1824 | sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
|
|---|
| 1825 | 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
|
|---|
| 1826 | ok(!ret && GetLastError() == CRYPT_E_EXISTS,
|
|---|
| 1827 | "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
|
|---|
| 1828 |
|
|---|
| 1829 | context = CertEnumCertificatesInStore(store, NULL);
|
|---|
| 1830 | ok(context != NULL, "Expected a cert\n");
|
|---|
| 1831 | if (context)
|
|---|
| 1832 | CertDeleteCertificateFromStore(context);
|
|---|
| 1833 |
|
|---|
| 1834 | /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
|
|---|
| 1835 | * when queried, is the real hash rather than the bogus hash.
|
|---|
| 1836 | */
|
|---|
| 1837 | hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
|
|---|
| 1838 | sizeof(bigCert));
|
|---|
| 1839 | hdr->propID = CERT_HASH_PROP_ID;
|
|---|
| 1840 | hdr->unknown1 = 1;
|
|---|
| 1841 | hdr->cb = sizeof(hash);
|
|---|
| 1842 | memset(hash, 0xc, sizeof(hash));
|
|---|
| 1843 | memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
|
|---|
| 1844 | ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
|
|---|
| 1845 | CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
|
|---|
| 1846 | (const void **)&context);
|
|---|
| 1847 | ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
|
|---|
| 1848 | if (context)
|
|---|
| 1849 | {
|
|---|
| 1850 | BYTE hashVal[20], realHash[20];
|
|---|
| 1851 | DWORD size = sizeof(hashVal);
|
|---|
| 1852 |
|
|---|
| 1853 | ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
|
|---|
| 1854 | realHash, &size);
|
|---|
| 1855 | ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
|
|---|
| 1856 | ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
|
|---|
| 1857 | hashVal, &size);
|
|---|
| 1858 | ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
|
|---|
| 1859 | GetLastError());
|
|---|
| 1860 | ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
|
|---|
| 1861 | CertFreeCertificateContext(context);
|
|---|
| 1862 | }
|
|---|
| 1863 |
|
|---|
| 1864 | CertCloseStore(store, 0);
|
|---|
| 1865 | }
|
|---|
| 1866 |
|
|---|
| 1867 | static DWORD countCertsInStore(HCERTSTORE store)
|
|---|
| 1868 | {
|
|---|
| 1869 | PCCERT_CONTEXT cert = NULL;
|
|---|
| 1870 | DWORD certs = 0;
|
|---|
| 1871 |
|
|---|
| 1872 | do {
|
|---|
| 1873 | cert = CertEnumCertificatesInStore(store, cert);
|
|---|
| 1874 | if (cert)
|
|---|
| 1875 | certs++;
|
|---|
| 1876 | } while (cert);
|
|---|
| 1877 | return certs;
|
|---|
| 1878 | }
|
|---|
| 1879 |
|
|---|
| 1880 | static DWORD countCRLsInStore(HCERTSTORE store)
|
|---|
| 1881 | {
|
|---|
| 1882 | PCCRL_CONTEXT crl = NULL;
|
|---|
| 1883 | DWORD crls = 0;
|
|---|
| 1884 |
|
|---|
| 1885 | do {
|
|---|
| 1886 | crl = pCertEnumCRLsInStore(store, crl);
|
|---|
| 1887 | if (crl)
|
|---|
| 1888 | crls++;
|
|---|
| 1889 | } while (crl);
|
|---|
| 1890 | return crls;
|
|---|
| 1891 | }
|
|---|
| 1892 |
|
|---|
| 1893 | static void test_I_UpdateStore(void)
|
|---|
| 1894 | {
|
|---|
| 1895 | HMODULE lib = GetModuleHandleA("crypt32");
|
|---|
| 1896 | BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) =
|
|---|
| 1897 | (void *)GetProcAddress(lib, "I_CertUpdateStore");
|
|---|
| 1898 | BOOL ret;
|
|---|
| 1899 | HCERTSTORE store1, store2;
|
|---|
| 1900 | PCCERT_CONTEXT cert;
|
|---|
| 1901 | DWORD certs;
|
|---|
| 1902 |
|
|---|
| 1903 | if (!pI_CertUpdatestore)
|
|---|
| 1904 | {
|
|---|
| 1905 | skip("No I_CertUpdateStore\n");
|
|---|
| 1906 | return;
|
|---|
| 1907 | }
|
|---|
| 1908 | store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 1909 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 1910 | store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
|---|
| 1911 | CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|---|
| 1912 |
|
|---|
| 1913 | /* Crash
|
|---|
| 1914 | ret = pI_CertUpdatestore(NULL, NULL, 0, 0);
|
|---|
| 1915 | ret = pI_CertUpdatestore(store1, NULL, 0, 0);
|
|---|
| 1916 | ret = pI_CertUpdatestore(NULL, store2, 0, 0);
|
|---|
| 1917 | */
|
|---|
| 1918 | ret = pI_CertUpdatestore(store1, store2, 0, 0);
|
|---|
| 1919 | ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
|
|---|
| 1920 |
|
|---|
| 1921 | CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert,
|
|---|
| 1922 | sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
|
|---|
| 1923 | /* I_CertUpdateStore adds the contexts from store2 to store1 */
|
|---|
| 1924 | ret = pI_CertUpdatestore(store1, store2, 0, 0);
|
|---|
| 1925 | ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
|
|---|
| 1926 | certs = countCertsInStore(store1);
|
|---|
| 1927 | ok(certs == 1, "Expected 1 cert, got %d\n", certs);
|
|---|
| 1928 | /* Calling it a second time has no effect */
|
|---|
| 1929 | ret = pI_CertUpdatestore(store1, store2, 0, 0);
|
|---|
| 1930 | ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
|
|---|
| 1931 | certs = countCertsInStore(store1);
|
|---|
| 1932 | ok(certs == 1, "Expected 1 cert, got %d\n", certs);
|
|---|
| 1933 |
|
|---|
| 1934 | /* The last parameters to I_CertUpdateStore appear to be ignored */
|
|---|
| 1935 | ret = pI_CertUpdatestore(store1, store2, 1, 0);
|
|---|
| 1936 | ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
|
|---|
| 1937 | ret = pI_CertUpdatestore(store1, store2, 0, 1);
|
|---|
| 1938 | ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
|
|---|
| 1939 |
|
|---|
| 1940 | CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL,
|
|---|
| 1941 | sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
|
|---|
| 1942 |
|
|---|
| 1943 | /* I_CertUpdateStore also adds the CRLs from store2 to store1 */
|
|---|
| 1944 | ret = pI_CertUpdatestore(store1, store2, 0, 0);
|
|---|
| 1945 | ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
|
|---|
| 1946 | certs = countCertsInStore(store1);
|
|---|
| 1947 | ok(certs == 1, "Expected 1 cert, got %d\n", certs);
|
|---|
| 1948 | if (pCertEnumCRLsInStore)
|
|---|
| 1949 | {
|
|---|
| 1950 | certs = countCRLsInStore(store1);
|
|---|
| 1951 | ok(certs == 1, "Expected 1 CRL, got %d\n", certs);
|
|---|
| 1952 | }
|
|---|
| 1953 |
|
|---|
| 1954 | CertDeleteCertificateFromStore(cert);
|
|---|
| 1955 | /* If a context is deleted from store2, I_CertUpdateStore deletes it
|
|---|
| 1956 | * from store1
|
|---|
| 1957 | */
|
|---|
| 1958 | ret = pI_CertUpdatestore(store1, store2, 0, 0);
|
|---|
| 1959 | ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
|
|---|
| 1960 | certs = countCertsInStore(store1);
|
|---|
| 1961 | ok(certs == 0, "Expected 0 certs, got %d\n", certs);
|
|---|
| 1962 |
|
|---|
| 1963 | CertFreeCertificateContext(cert);
|
|---|
| 1964 | CertCloseStore(store1, 0);
|
|---|
| 1965 | CertCloseStore(store2, 0);
|
|---|
| 1966 | }
|
|---|
| 1967 |
|
|---|
| 1968 | START_TEST(store)
|
|---|
| 1969 | {
|
|---|
| 1970 | HMODULE hdll;
|
|---|
| 1971 |
|
|---|
| 1972 | hdll = GetModuleHandleA("Crypt32.dll");
|
|---|
| 1973 | pCertAddStoreToCollection = (void*)GetProcAddress(hdll, "CertAddStoreToCollection");
|
|---|
| 1974 | pCertControlStore = (void*)GetProcAddress(hdll, "CertControlStore");
|
|---|
| 1975 | pCertEnumCRLsInStore = (void*)GetProcAddress(hdll, "CertEnumCRLsInStore");
|
|---|
| 1976 | pCertEnumSystemStore = (void*)GetProcAddress(hdll, "CertEnumSystemStore");
|
|---|
| 1977 | pCertGetStoreProperty = (void*)GetProcAddress(hdll, "CertGetStoreProperty");
|
|---|
| 1978 | pCertRemoveStoreFromCollection = (void*)GetProcAddress(hdll, "CertRemoveStoreFromCollection");
|
|---|
| 1979 | pCertSetStoreProperty = (void*)GetProcAddress(hdll, "CertSetStoreProperty");
|
|---|
| 1980 |
|
|---|
| 1981 | /* various combinations of CertOpenStore */
|
|---|
| 1982 | testMemStore();
|
|---|
| 1983 | testCollectionStore();
|
|---|
| 1984 | testRegStore();
|
|---|
| 1985 | testSystemRegStore();
|
|---|
| 1986 | testSystemStore();
|
|---|
| 1987 | testFileStore();
|
|---|
| 1988 | testFileNameStore();
|
|---|
| 1989 | testMessageStore();
|
|---|
| 1990 |
|
|---|
| 1991 | testCertOpenSystemStore();
|
|---|
| 1992 | testCertEnumSystemStore();
|
|---|
| 1993 | testStoreProperty();
|
|---|
| 1994 |
|
|---|
| 1995 | testAddSerialized();
|
|---|
| 1996 |
|
|---|
| 1997 | test_I_UpdateStore();
|
|---|
| 1998 | }
|
|---|