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 "precomp.h" 22 23 #include <shlobj.h> 24 #include <shlwapi.h> 25 26 /* The following aren't defined in wincrypt.h, as they're "reserved" */ 27 #define CERT_CERT_PROP_ID 32 28 #define CERT_CRL_PROP_ID 33 29 #define CERT_CTL_PROP_ID 34 30 31 struct CertPropIDHeader 32 { 33 DWORD propID; 34 DWORD unknown1; 35 DWORD cb; 36 }; 37 38 static const BYTE emptyCert[] = { 0x30, 0x00 }; 39 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 40 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 41 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 42 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 43 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 44 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 45 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 46 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 47 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 48 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; 49 static const BYTE signedBigCert[] = { 50 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 51 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 52 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 53 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 54 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 55 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 56 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 57 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 58 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 59 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 60 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 61 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; 62 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00, 63 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01, 64 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 65 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 66 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 67 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 68 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 69 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 70 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 71 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 72 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 73 0x01, 0x01 }; 74 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06, 75 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 76 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 77 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 78 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 79 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; 80 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 81 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 82 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 83 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 84 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 85 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 86 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 87 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 88 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 89 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; 90 static const BYTE signedCTLWithCTLInnerContent[] = { 91 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, 92 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06, 93 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09, 94 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00, 95 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30, 96 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05, 97 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31, 98 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20, 99 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48, 100 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86, 101 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04, 102 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, 103 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9, 104 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04, 105 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf, 106 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1, 107 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f, 108 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23, 109 0x57,0x6c,0x0b,0x47,0xb8 }; 110 111 static BOOL (WINAPI *pCertControlStore)(HCERTSTORE,DWORD,DWORD,void const*); 112 static PCCRL_CONTEXT (WINAPI *pCertEnumCRLsInStore)(HCERTSTORE,PCCRL_CONTEXT); 113 static BOOL (WINAPI *pCertEnumSystemStore)(DWORD,void*,void*,PFN_CERT_ENUM_SYSTEM_STORE); 114 static BOOL (WINAPI *pCertGetStoreProperty)(HCERTSTORE,DWORD,void*,DWORD*); 115 static void (WINAPI *pCertRemoveStoreFromCollection)(HCERTSTORE,HCERTSTORE); 116 static BOOL (WINAPI *pCertSetStoreProperty)(HCERTSTORE,DWORD,DWORD,const void*); 117 static BOOL (WINAPI *pCertAddCertificateLinkToStore)(HCERTSTORE,PCCERT_CONTEXT,DWORD,PCCERT_CONTEXT*); 118 static BOOL (WINAPI *pCertRegisterSystemStore)(const void*,DWORD,void*,void*); 119 static BOOL (WINAPI *pCertUnregisterSystemStore)(const void*,DWORD); 120 121 #define test_store_is_empty(store) _test_store_is_empty(__LINE__,store) 122 static void _test_store_is_empty(unsigned line, HCERTSTORE store) 123 { 124 const CERT_CONTEXT *cert; 125 126 cert = CertEnumCertificatesInStore(store, NULL); 127 ok_(__FILE__,line)(!cert && GetLastError() == CRYPT_E_NOT_FOUND, "store is not empty\n"); 128 } 129 130 static void testMemStore(void) 131 { 132 HCERTSTORE store1, store2; 133 PCCERT_CONTEXT context; 134 BOOL ret; 135 DWORD GLE; 136 137 /* NULL provider */ 138 store1 = CertOpenStore(0, 0, 0, 0, NULL); 139 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND, 140 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); 141 /* weird flags */ 142 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 143 CERT_STORE_DELETE_FLAG, NULL); 144 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, 145 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError()); 146 147 /* normal */ 148 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 149 CERT_STORE_CREATE_NEW_FLAG, NULL); 150 ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError()); 151 /* open existing doesn't */ 152 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 153 CERT_STORE_OPEN_EXISTING_FLAG, NULL); 154 ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError()); 155 ok(store1 != store2, "Expected different stores\n"); 156 157 /* add a bogus (empty) cert */ 158 context = NULL; 159 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert, 160 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context); 161 /* Windows returns CRYPT_E_ASN1_EOD or OSS_DATA_ERROR, but accept 162 * CRYPT_E_ASN1_CORRUPT as well (because matching errors is tough in this 163 * case) 164 */ 165 GLE = GetLastError(); 166 ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == CRYPT_E_ASN1_CORRUPT || 167 GLE == OSS_DATA_ERROR), 168 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 169 GLE); 170 /* add a "signed" cert--the signature isn't a real signature, so this adds 171 * without any check of the signature's validity 172 */ 173 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, 174 signedBigCert, sizeof(signedBigCert), 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 ok(context->cbCertEncoded == sizeof(signedBigCert), 180 "Wrong cert size %d\n", context->cbCertEncoded); 181 ok(!memcmp(context->pbCertEncoded, signedBigCert, 182 sizeof(signedBigCert)), "Unexpected encoded cert in context\n"); 183 /* remove it, the rest of the tests will work on an unsigned cert */ 184 ret = CertDeleteCertificateFromStore(context); 185 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n", 186 GetLastError()); 187 } 188 /* try adding a "signed" CRL as a cert */ 189 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, 190 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context); 191 GLE = GetLastError(); 192 ok(!ret && (GLE == CRYPT_E_ASN1_BADTAG || GLE == CRYPT_E_ASN1_CORRUPT || 193 GLE == OSS_DATA_ERROR), 194 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 195 GLE); 196 /* add a cert to store1 */ 197 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert, 198 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context); 199 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); 200 ok(context != NULL, "Expected a valid cert context\n"); 201 if (context) 202 { 203 DWORD size; 204 BYTE *buf; 205 206 ok(context->cbCertEncoded == sizeof(bigCert), 207 "Wrong cert size %d\n", context->cbCertEncoded); 208 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)), 209 "Unexpected encoded cert in context\n"); 210 ok(context->hCertStore == store1, "Unexpected store\n"); 211 212 /* check serializing this element */ 213 /* These crash 214 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL); 215 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL); 216 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size); 217 */ 218 /* apparently flags are ignored */ 219 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size); 220 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", 221 GetLastError()); 222 buf = HeapAlloc(GetProcessHeap(), 0, size); 223 if (buf) 224 { 225 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size); 226 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError()); 227 ok(size == sizeof(serializedCert), "Wrong size %d\n", size); 228 ok(!memcmp(serializedCert, buf, size), 229 "Unexpected serialized cert\n"); 230 HeapFree(GetProcessHeap(), 0, buf); 231 } 232 233 ret = CertFreeCertificateContext(context); 234 ok(ret, "CertFreeCertificateContext failed: %08x\n", GetLastError()); 235 } 236 /* verify the cert's in store1 */ 237 context = CertEnumCertificatesInStore(store1, NULL); 238 ok(context != NULL, "Expected a valid context\n"); 239 context = CertEnumCertificatesInStore(store1, context); 240 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND, 241 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); 242 /* verify store2 (the "open existing" mem store) is still empty */ 243 context = CertEnumCertificatesInStore(store2, NULL); 244 ok(!context, "Expected an empty store\n"); 245 /* delete the cert from store1, and check it's empty */ 246 context = CertEnumCertificatesInStore(store1, NULL); 247 if (context) 248 { 249 /* Deleting a bitwise copy crashes with an access to an uninitialized 250 * pointer, so a cert context has some special data out there in memory 251 * someplace 252 CERT_CONTEXT copy; 253 memcpy(©, context, sizeof(copy)); 254 ret = CertDeleteCertificateFromStore(©); 255 */ 256 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context); 257 258 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08x\n", 259 GetLastError()); 260 ret = CertDeleteCertificateFromStore(context); 261 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n", 262 GetLastError()); 263 /* try deleting a copy */ 264 ret = CertDeleteCertificateFromStore(copy); 265 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n", 266 GetLastError()); 267 /* check that the store is empty */ 268 context = CertEnumCertificatesInStore(store1, NULL); 269 ok(!context, "Expected an empty store\n"); 270 } 271 272 /* close an empty store */ 273 ret = CertCloseStore(NULL, 0); 274 ok(ret, "CertCloseStore failed: %d\n", GetLastError()); 275 ret = CertCloseStore(store1, 0); 276 ok(ret, "CertCloseStore failed: %d\n", GetLastError()); 277 ret = CertCloseStore(store2, 0); 278 ok(ret, "CertCloseStore failed: %d\n", GetLastError()); 279 280 /* This seems nonsensical, but you can open a read-only mem store, only 281 * it isn't read-only 282 */ 283 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 284 CERT_STORE_READONLY_FLAG, NULL); 285 ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError()); 286 /* yep, this succeeds */ 287 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert, 288 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context); 289 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); 290 ok(context != NULL, "Expected a valid cert context\n"); 291 if (context) 292 { 293 ok(context->cbCertEncoded == sizeof(bigCert), 294 "Wrong cert size %d\n", context->cbCertEncoded); 295 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)), 296 "Unexpected encoded cert in context\n"); 297 ok(context->hCertStore == store1, "Unexpected store\n"); 298 ret = CertDeleteCertificateFromStore(context); 299 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n", 300 GetLastError()); 301 } 302 CertCloseStore(store1, 0); 303 } 304 305 static void compareStore(HCERTSTORE store, LPCSTR name, const BYTE *pb, 306 DWORD cb, BOOL todo) 307 { 308 BOOL ret; 309 CRYPT_DATA_BLOB blob = { 0, NULL }; 310 311 ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE, 312 CERT_STORE_SAVE_TO_MEMORY, &blob, 0); 313 ok(ret, "CertSaveStore failed: %08x\n", GetLastError()); 314 todo_wine_if (todo) 315 ok(blob.cbData == cb, "%s: expected size %d, got %d\n", name, cb, 316 blob.cbData); 317 blob.pbData = HeapAlloc(GetProcessHeap(), 0, blob.cbData); 318 if (blob.pbData) 319 { 320 ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE, 321 CERT_STORE_SAVE_TO_MEMORY, &blob, 0); 322 ok(ret, "CertSaveStore failed: %08x\n", GetLastError()); 323 todo_wine_if (todo) 324 ok(!memcmp(pb, blob.pbData, cb), "%s: unexpected value\n", name); 325 HeapFree(GetProcessHeap(), 0, blob.pbData); 326 } 327 } 328 329 static const BYTE serializedStoreWithCert[] = { 330 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00, 331 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30, 332 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61, 333 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31, 334 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36, 335 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15, 336 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, 337 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00, 338 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04, 339 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00, 340 0x00,0x00,0x00,0x00,0x00,0x00 }; 341 342 static const struct 343 { 344 HKEY key; 345 DWORD cert_store; 346 BOOL appdata_file; 347 WCHAR store_name[16]; 348 const WCHAR *base_reg_path; 349 } reg_store_saved_certs[] = { 350 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE, 351 {'R','O','O','T',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }, 352 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE, 353 {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }, 354 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE, 355 {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }, 356 /* Adding to HKCU\Root triggers safety warning. */ 357 { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, TRUE, 358 {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }, 359 { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, FALSE, 360 {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH } 361 }; 362 363 /* Testing whether system stores are available for adding new certs 364 * and checking directly in the registry whether they are actually saved or deleted. 365 * Windows treats HKCU\My (at least) as a special case and uses AppData directory 366 * for storing certs, not registry. 367 */ 368 static void testRegStoreSavedCerts(void) 369 { 370 static const WCHAR fmt[] = 371 { '%','s','\\','%','s','\\','%','s','\\','%','s',0}, 372 ms_certs[] = 373 { 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0}, 374 certs[] = 375 {'C','e','r','t','i','f','i','c','a','t','e','s',0}, 376 bigCert_hash[] = { 377 '6','E','3','0','9','0','7','1','5','F','D','9','2','3', 378 '5','6','E','B','A','E','2','5','4','0','E','6','2','2', 379 'D','A','1','9','2','6','0','2','A','6','0','8',0}; 380 PCCERT_CONTEXT cert1, cert2; 381 HCERTSTORE store; 382 HANDLE cert_file; 383 HRESULT pathres; 384 WCHAR key_name[MAX_PATH], appdata_path[MAX_PATH]; 385 HKEY key; 386 BOOL ret; 387 DWORD res,i; 388 389 for (i = 0; i < sizeof(reg_store_saved_certs) / sizeof(reg_store_saved_certs[0]); i++) 390 { 391 DWORD err; 392 393 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 394 reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name); 395 396 err = GetLastError(); 397 if (!store) 398 { 399 ok (err == ERROR_ACCESS_DENIED, "Failed to create store at %d (%08x)\n", i, err); 400 skip("Insufficient privileges for the test %d\n", i); 401 continue; 402 } 403 ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError()); 404 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert)); 405 ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError()); 406 ret = CertAddCertificateContextToStore(store, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL); 407 /* Addittional skip per Win7, it allows opening HKLM store, but disallows adding certs */ 408 err = GetLastError(); 409 if (!ret) 410 { 411 ok (err == ERROR_ACCESS_DENIED, "Failed to add certificate to store at %d (%08x)\n", i, err); 412 skip("Insufficient privileges for the test %d\n", i); 413 continue; 414 } 415 ok (ret, "Adding to the store failed at %d, %x\n", i, err); 416 CertFreeCertificateContext(cert1); 417 CertCloseStore(store, 0); 418 419 wsprintfW(key_name, fmt, reg_store_saved_certs[i].base_reg_path, 420 reg_store_saved_certs[i].store_name, certs, bigCert_hash); 421 422 if (!reg_store_saved_certs[i].appdata_file) 423 { 424 res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key); 425 ok (!res, "The cert hasn't been saved at %d, %x\n", i, GetLastError()); 426 if (!res) RegCloseKey(key); 427 } else 428 { 429 pathres = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, appdata_path); 430 ok (pathres == S_OK, 431 "Failed to get app data path at %d (%x)\n", pathres, GetLastError()); 432 if (pathres == S_OK) 433 { 434 PathAppendW(appdata_path, ms_certs); 435 PathAppendW(appdata_path, reg_store_saved_certs[i].store_name); 436 PathAppendW(appdata_path, certs); 437 PathAppendW(appdata_path, bigCert_hash); 438 439 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL, 440 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 441 todo_wine ok (cert_file != INVALID_HANDLE_VALUE, 442 "Cert was not saved in AppData at %d (%x)\n", i, GetLastError()); 443 CloseHandle(cert_file); 444 } 445 } 446 447 /* deleting cert from store */ 448 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 449 reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name); 450 ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError()); 451 452 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert)); 453 ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError()); 454 455 cert2 = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0, 456 CERT_FIND_EXISTING, cert1, NULL); 457 ok (cert2 != NULL, "Failed to find cert in the store at %d, %x\n", i, GetLastError()); 458 459 ret = CertDeleteCertificateFromStore(cert2); 460 ok (ret, "Failed to delete certificate from store at %d, %x\n", i, GetLastError()); 461 462 CertFreeCertificateContext(cert1); 463 CertFreeCertificateContext(cert2); 464 CertCloseStore(store, 0); 465 466 res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key); 467 ok (res, "The cert's registry entry should be absent at %i, %x\n", i, GetLastError()); 468 if (!res) RegCloseKey(key); 469 470 if (reg_store_saved_certs[i].appdata_file) 471 { 472 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL, 473 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 474 ok (cert_file == INVALID_HANDLE_VALUE, 475 "Cert should have been absent in AppData %d\n", i); 476 477 CloseHandle(cert_file); 478 } 479 } 480 } 481 482 /** 483 * This test checks that certificate falls into correct store of a collection 484 * depending on the access flags and priorities. 485 */ 486 static void testStoresInCollection(void) 487 { 488 PCCERT_CONTEXT cert1, cert2, tcert1; 489 HCERTSTORE collection, ro_store, rw_store, rw_store_2, tstore; 490 static const WCHAR WineTestRO_W[] = { 'W','i','n','e','T','e','s','t','_','R','O',0 }, 491 WineTestRW_W[] = { 'W','i','n','e','T','e','s','t','_','R','W',0 }, 492 WineTestRW2_W[]= { 'W','i','n','e','T','e','s','t','_','R','W','2',0 }; 493 BOOL ret; 494 495 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 496 CERT_STORE_CREATE_NEW_FLAG, NULL); 497 ok(collection != NULL, "Failed to init collection store, last error %x\n", GetLastError()); 498 /* Add read-only store to collection with very high priority*/ 499 ro_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, 500 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRO_W); 501 ok(ro_store != NULL, "Failed to init ro store %x\n", GetLastError()); 502 503 ret = CertAddStoreToCollection(collection, ro_store, 0, 1000); 504 ok (ret, "Failed to add read-only store to collection %x\n", GetLastError()); 505 506 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert)); 507 ok (cert1 != NULL, "Create cert context failed %x\n", GetLastError()); 508 ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_ALWAYS, NULL); 509 ok (!ret, "Added cert to collection with single read-only store %x\n", GetLastError()); 510 511 /* Add read-write store to collection with the lowest priority*/ 512 rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, 513 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W); 514 ok (rw_store != NULL, "Failed to open rw store %x\n", GetLastError()); 515 ret = CertAddStoreToCollection(collection, rw_store, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 516 ok (ret, "Failed to add rw store to collection %x\n", GetLastError()); 517 /** Adding certificate to collection should fall into rw store, 518 * even though prioirty of the ro_store is higher */ 519 ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL); 520 ok (ret, "Failed to add cert to the collection %x\n", GetLastError()); 521 522 tcert1 = CertEnumCertificatesInStore(ro_store, NULL); 523 ok (!tcert1, "Read-only ro_store contains cert\n"); 524 525 tcert1 = CertEnumCertificatesInStore(rw_store, NULL); 526 ok (cert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, 527 "Unexpected cert in the rw store\n"); 528 CertFreeCertificateContext(tcert1); 529 530 tcert1 = CertEnumCertificatesInStore(collection, NULL); 531 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, 532 "Unexpected cert in the collection\n"); 533 CertFreeCertificateContext(tcert1); 534 535 /** adding one more rw store with higher priority*/ 536 rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, 537 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W); 538 ok (rw_store_2 != NULL, "Failed to init second rw store %x\n", GetLastError()); 539 ret = CertAddStoreToCollection(collection, rw_store_2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 50); 540 ok (ret, "Failed to add rw_store_2 to collection %x\n",GetLastError()); 541 542 cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, signedBigCert, sizeof(signedBigCert)); 543 ok (cert2 != NULL, "Failed to create cert context %x\n", GetLastError()); 544 ret = CertAddCertificateContextToStore(collection, cert2, CERT_STORE_ADD_REPLACE_EXISTING, NULL); 545 ok (ret, "Failed to add cert3 to the store %x\n",GetLastError()); 546 547 /** checking certificates in the stores */ 548 tcert1 = CertEnumCertificatesInStore(ro_store, 0); 549 ok (tcert1 == NULL, "Read-only store not empty\n"); 550 551 tcert1 = CertEnumCertificatesInStore(rw_store, NULL); 552 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, 553 "Unexpected cert in the rw_store\n"); 554 CertFreeCertificateContext(tcert1); 555 556 tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL); 557 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, 558 "Unexpected cert in the rw_store_2\n"); 559 CertFreeCertificateContext(tcert1); 560 561 /** checking certificates in the collection */ 562 tcert1 = CertEnumCertificatesInStore(collection, NULL); 563 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, 564 "cert2 expected in the collection got %p, %x\n",tcert1, GetLastError()); 565 tcert1 = CertEnumCertificatesInStore(collection, tcert1); 566 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, 567 "cert1 expected in the collection got %p, %x\n",tcert1, GetLastError()); 568 tcert1 = CertEnumCertificatesInStore(collection, tcert1); 569 ok (tcert1==NULL,"Unexpected cert in the collection %p %x\n",tcert1, GetLastError()); 570 571 /* checking whether certs had been saved */ 572 tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 573 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW_W); 574 ok (tstore!=NULL, "Failed to open existing rw store\n"); 575 tcert1 = CertEnumCertificatesInStore(tstore, NULL); 576 todo_wine 577 ok(tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, "cert1 wasn't saved\n"); 578 CertFreeCertificateContext(tcert1); 579 CertCloseStore(tstore,0); 580 581 tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 582 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW2_W); 583 ok (tstore!=NULL, "Failed to open existing rw2 store\n"); 584 tcert1 = CertEnumCertificatesInStore(tstore, NULL); 585 todo_wine 586 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, "cert2 wasn't saved\n"); 587 CertFreeCertificateContext(tcert1); 588 CertCloseStore(tstore,0); 589 590 CertCloseStore(collection,0); 591 CertCloseStore(ro_store,0); 592 CertCloseStore(rw_store,0); 593 CertCloseStore(rw_store_2,0); 594 595 /* reopening registry stores to check whether certs had been saved */ 596 rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 597 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W); 598 tcert1 = CertEnumCertificatesInStore(rw_store, NULL); 599 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, 600 "Unexpected cert in store %p\n", tcert1); 601 CertFreeCertificateContext(tcert1); 602 CertCloseStore(rw_store,0); 603 604 rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 605 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W); 606 tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL); 607 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, 608 "Unexpected cert in store %p\n", tcert1); 609 CertFreeCertificateContext(tcert1); 610 CertCloseStore(rw_store_2,0); 611 612 CertFreeCertificateContext(cert1); 613 CertFreeCertificateContext(cert2); 614 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 615 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRO_W); 616 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 617 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW_W); 618 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, 619 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW2_W); 620 621 } 622 623 static void testCollectionStore(void) 624 { 625 HCERTSTORE store1, store2, collection, collection2; 626 PCCERT_CONTEXT context; 627 BOOL ret; 628 static const WCHAR szPrefix[] = { 'c','e','r',0 }; 629 static const WCHAR szDot[] = { '.',0 }; 630 WCHAR filename[MAX_PATH]; 631 HANDLE file; 632 633 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 634 CERT_STORE_CREATE_NEW_FLAG, NULL); 635 636 /* Try adding a cert to any empty collection */ 637 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING, 638 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 639 ok(!ret && GetLastError() == E_ACCESSDENIED, 640 "Expected E_ACCESSDENIED, got %08x\n", GetLastError()); 641 642 /* Create and add a cert to a memory store */ 643 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 644 CERT_STORE_CREATE_NEW_FLAG, NULL); 645 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, 646 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 647 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); 648 /* Add the memory store to the collection, without allowing adding */ 649 ret = CertAddStoreToCollection(collection, store1, 0, 0); 650 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError()); 651 /* Verify the cert is in the collection */ 652 context = CertEnumCertificatesInStore(collection, NULL); 653 ok(context != NULL, "Expected a valid context\n"); 654 if (context) 655 { 656 ok(context->hCertStore == collection, "Unexpected store\n"); 657 CertFreeCertificateContext(context); 658 } 659 /* Check that adding to the collection isn't allowed */ 660 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING, 661 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL); 662 ok(!ret && GetLastError() == E_ACCESSDENIED, 663 "Expected E_ACCESSDENIED, got %08x\n", GetLastError()); 664 665 /* Create a new memory store */ 666 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 667 CERT_STORE_CREATE_NEW_FLAG, NULL); 668 /* Try adding a store to a non-collection store */ 669 ret = CertAddStoreToCollection(store1, store2, 670 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 671 ok(!ret && GetLastError() == E_INVALIDARG, 672 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 673 /* Try adding some bogus stores */ 674 /* This crashes in Windows 675 ret = pCertAddStoreToCollection(0, store2, 676 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 677 */ 678 /* This "succeeds"... */ 679 ret = CertAddStoreToCollection(collection, 0, 680 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 681 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError()); 682 /* while this crashes. 683 ret = pCertAddStoreToCollection(collection, 1, 684 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 685 */ 686 687 /* Add it to the collection, this time allowing adding */ 688 ret = CertAddStoreToCollection(collection, store2, 689 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 690 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError()); 691 /* Check that adding to the collection is allowed */ 692 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING, 693 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL); 694 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); 695 /* Now check that it was actually added to store2 */ 696 context = CertEnumCertificatesInStore(store2, NULL); 697 ok(context != NULL, "Expected a valid context\n"); 698 if (context) 699 { 700 ok(context->hCertStore == store2, "Unexpected store\n"); 701 CertFreeCertificateContext(context); 702 } 703 /* Check that the collection has both bigCert and bigCert2. bigCert comes 704 * first because store1 was added first. 705 */ 706 context = CertEnumCertificatesInStore(collection, NULL); 707 ok(context != NULL, "Expected a valid context\n"); 708 if (context) 709 { 710 ok(context->hCertStore == collection, "Unexpected store\n"); 711 ok(context->cbCertEncoded == sizeof(bigCert), 712 "Wrong size %d\n", context->cbCertEncoded); 713 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded), 714 "Unexpected cert\n"); 715 context = CertEnumCertificatesInStore(collection, context); 716 ok(context != NULL, "Expected a valid context\n"); 717 if (context) 718 { 719 ok(context->hCertStore == collection, "Unexpected store\n"); 720 ok(context->cbCertEncoded == sizeof(bigCert2), 721 "Wrong size %d\n", context->cbCertEncoded); 722 ok(!memcmp(context->pbCertEncoded, bigCert2, 723 context->cbCertEncoded), "Unexpected cert\n"); 724 context = CertEnumCertificatesInStore(collection, context); 725 ok(!context, "Unexpected cert\n"); 726 } 727 } 728 /* close store2, and check that the collection is unmodified */ 729 CertCloseStore(store2, 0); 730 context = CertEnumCertificatesInStore(collection, NULL); 731 ok(context != NULL, "Expected a valid context\n"); 732 if (context) 733 { 734 ok(context->hCertStore == collection, "Unexpected store\n"); 735 ok(context->cbCertEncoded == sizeof(bigCert), 736 "Wrong size %d\n", context->cbCertEncoded); 737 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded), 738 "Unexpected cert\n"); 739 context = CertEnumCertificatesInStore(collection, context); 740 ok(context != NULL, "Expected a valid context\n"); 741 if (context) 742 { 743 ok(context->hCertStore == collection, "Unexpected store\n"); 744 ok(context->cbCertEncoded == sizeof(bigCert2), 745 "Wrong size %d\n", context->cbCertEncoded); 746 ok(!memcmp(context->pbCertEncoded, bigCert2, 747 context->cbCertEncoded), "Unexpected cert\n"); 748 context = CertEnumCertificatesInStore(collection, context); 749 ok(!context, "Unexpected cert\n"); 750 } 751 } 752 753 /* Adding a collection to a collection is legal */ 754 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 755 CERT_STORE_CREATE_NEW_FLAG, NULL); 756 ret = CertAddStoreToCollection(collection2, collection, 757 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 758 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError()); 759 /* check the contents of collection2 */ 760 context = CertEnumCertificatesInStore(collection2, NULL); 761 ok(context != NULL, "Expected a valid context\n"); 762 if (context) 763 { 764 ok(context->hCertStore == collection2, "Unexpected store\n"); 765 ok(context->cbCertEncoded == sizeof(bigCert), 766 "Wrong size %d\n", context->cbCertEncoded); 767 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded), 768 "Unexpected cert\n"); 769 context = CertEnumCertificatesInStore(collection2, context); 770 ok(context != NULL, "Expected a valid context\n"); 771 if (context) 772 { 773 ok(context->hCertStore == collection2, "Unexpected store\n"); 774 ok(context->cbCertEncoded == sizeof(bigCert2), 775 "Wrong size %d\n", context->cbCertEncoded); 776 ok(!memcmp(context->pbCertEncoded, bigCert2, 777 context->cbCertEncoded), "Unexpected cert\n"); 778 context = CertEnumCertificatesInStore(collection2, context); 779 ok(!context, "Unexpected cert\n"); 780 } 781 } 782 783 /* I'd like to test closing the collection in the middle of enumeration, 784 * but my tests have been inconsistent. The first time calling 785 * CertEnumCertificatesInStore on a closed collection succeeded, while the 786 * second crashed. So anything appears to be fair game. 787 * I'd also like to test removing a store from a collection in the middle 788 * of an enumeration, but my tests in Windows have been inconclusive. 789 * In one scenario it worked. In another scenario, about a third of the 790 * time this leads to "random" crashes elsewhere in the code. This 791 * probably means this is not allowed. 792 */ 793 794 CertCloseStore(store1, 0); 795 CertCloseStore(collection, 0); 796 CertCloseStore(collection2, 0); 797 798 /* Add the same cert to two memory stores, then put them in a collection */ 799 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 800 CERT_STORE_CREATE_NEW_FLAG, NULL); 801 ok(store1 != 0, "CertOpenStore failed: %08x\n", GetLastError()); 802 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 803 CERT_STORE_CREATE_NEW_FLAG, NULL); 804 ok(store2 != 0, "CertOpenStore failed: %08x\n", GetLastError()); 805 806 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, 807 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 808 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); 809 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, 810 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 811 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); 812 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 813 CERT_STORE_CREATE_NEW_FLAG, NULL); 814 ok(collection != 0, "CertOpenStore failed: %08x\n", GetLastError()); 815 816 ret = CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 817 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError()); 818 ret = CertAddStoreToCollection(collection, store2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 819 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError()); 820 821 /* Check that the collection has two copies of the same cert */ 822 context = CertEnumCertificatesInStore(collection, NULL); 823 ok(context != NULL, "Expected a valid context\n"); 824 if (context) 825 { 826 ok(context->hCertStore == collection, "Unexpected store\n"); 827 ok(context->cbCertEncoded == sizeof(bigCert), 828 "Wrong size %d\n", context->cbCertEncoded); 829 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded), 830 "Unexpected cert\n"); 831 context = CertEnumCertificatesInStore(collection, context); 832 ok(context != NULL, "Expected a valid context\n"); 833 if (context) 834 { 835 ok(context->hCertStore == collection, "Unexpected store\n"); 836 ok(context->cbCertEncoded == sizeof(bigCert), 837 "Wrong size %d\n", context->cbCertEncoded); 838 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded), 839 "Unexpected cert\n"); 840 context = CertEnumCertificatesInStore(collection, context); 841 ok(context == NULL, "Unexpected cert\n"); 842 } 843 } 844 845 /* The following would check whether I can delete an identical cert, rather 846 * than one enumerated from the store. It crashes, so that means I must 847 * only call CertDeleteCertificateFromStore with contexts enumerated from 848 * the store. 849 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, 850 sizeof(bigCert)); 851 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n", 852 GetLastError()); 853 if (context) 854 { 855 ret = CertDeleteCertificateFromStore(collection, context); 856 printf("ret is %d, GetLastError is %08x\n", ret, GetLastError()); 857 CertFreeCertificateContext(context); 858 } 859 */ 860 861 /* Now check deleting from the collection. */ 862 context = CertEnumCertificatesInStore(collection, NULL); 863 ok(context != NULL, "Expected a valid context\n"); 864 if (context) 865 { 866 CertDeleteCertificateFromStore(context); 867 /* store1 should now be empty */ 868 context = CertEnumCertificatesInStore(store1, NULL); 869 ok(!context, "Unexpected cert\n"); 870 /* and there should be one certificate in the collection */ 871 context = CertEnumCertificatesInStore(collection, NULL); 872 ok(context != NULL, "Expected a valid cert\n"); 873 if (context) 874 { 875 ok(context->hCertStore == collection, "Unexpected store\n"); 876 ok(context->cbCertEncoded == sizeof(bigCert), 877 "Wrong size %d\n", context->cbCertEncoded); 878 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded), 879 "Unexpected cert\n"); 880 } 881 context = CertEnumCertificatesInStore(collection, context); 882 ok(context == NULL, "Unexpected cert\n"); 883 } 884 885 if (!pCertRemoveStoreFromCollection) 886 { 887 win_skip("CertRemoveStoreFromCollection() is not available\n"); 888 } 889 else 890 { 891 /* Finally, test removing stores from the collection. No return 892 * value, so it's a bit funny to test. 893 */ 894 /* This crashes 895 * pCertRemoveStoreFromCollection(NULL, NULL); 896 */ 897 /* This "succeeds," no crash, no last error set */ 898 SetLastError(0xdeadbeef); 899 pCertRemoveStoreFromCollection(store2, collection); 900 ok(GetLastError() == 0xdeadbeef, 901 "Didn't expect an error to be set: %08x\n", GetLastError()); 902 903 /* After removing store2, the collection should be empty */ 904 SetLastError(0xdeadbeef); 905 pCertRemoveStoreFromCollection(collection, store2); 906 ok(GetLastError() == 0xdeadbeef, 907 "Didn't expect an error to be set: %08x\n", GetLastError()); 908 context = CertEnumCertificatesInStore(collection, NULL); 909 ok(!context, "Unexpected cert\n"); 910 } 911 912 CertCloseStore(collection, 0); 913 CertCloseStore(store2, 0); 914 CertCloseStore(store1, 0); 915 916 /* Test adding certificates to and deleting certificates from collections. 917 */ 918 store1 = CertOpenSystemStoreA(0, "My"); 919 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 920 CERT_STORE_CREATE_NEW_FLAG, NULL); 921 922 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, 923 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context); 924 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); 925 CertDeleteCertificateFromStore(context); 926 927 CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 928 929 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING, 930 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context); 931 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); 932 CertDeleteCertificateFromStore(context); 933 934 CertCloseStore(collection, 0); 935 CertCloseStore(store1, 0); 936 937 /* Test whether a collection store can be committed */ 938 if (!pCertControlStore) 939 { 940 win_skip("CertControlStore() is not available\n"); 941 return; 942 } 943 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 944 CERT_STORE_CREATE_NEW_FLAG, NULL); 945 946 SetLastError(0xdeadbeef); 947 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL); 948 ok(ret, "CertControlStore failed: %08x\n", GetLastError()); 949 950 /* Adding a mem store that can't be committed prevents a successful commit. 951 */ 952 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 953 CERT_STORE_CREATE_NEW_FLAG, NULL); 954 CertAddStoreToCollection(collection, store1, 0, 0); 955 SetLastError(0xdeadbeef); 956 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL); 957 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, 958 "expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError()); 959 pCertRemoveStoreFromCollection(collection, store1); 960 CertCloseStore(store1, 0); 961 962 /* Test adding a cert to a collection with a file store, committing the 963 * change to the collection, and comparing the resulting file. 964 */ 965 if (!GetTempFileNameW(szDot, szPrefix, 0, filename)) 966 return; 967 968 DeleteFileW(filename); 969 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 970 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 971 if (file == INVALID_HANDLE_VALUE) 972 return; 973 974 store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 975 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file); 976 ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 977 CloseHandle(file); 978 CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 979 CertCloseStore(store1, 0); 980 981 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING, 982 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 983 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", 984 GetLastError()); 985 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL); 986 ok(ret, "CertControlStore failed: %d\n", ret); 987 compareStore(collection, "serialized store with cert", 988 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE); 989 CertCloseStore(collection, 0); 990 991 DeleteFileW(filename); 992 } 993 994 /* Looks for the property with ID propID in the buffer buf. Returns a pointer 995 * to its header if found, NULL if not. 996 */ 997 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size, 998 DWORD propID) 999 { 1000 const struct CertPropIDHeader *ret = NULL; 1001 BOOL failed = FALSE; 1002 1003 while (size && !ret && !failed) 1004 { 1005 if (size < sizeof(struct CertPropIDHeader)) 1006 failed = TRUE; 1007 else 1008 { 1009 const struct CertPropIDHeader *hdr = 1010 (const struct CertPropIDHeader *)buf; 1011 1012 size -= sizeof(struct CertPropIDHeader); 1013 buf += sizeof(struct CertPropIDHeader); 1014 if (size < hdr->cb) 1015 failed = TRUE; 1016 else if (hdr->propID == propID) 1017 ret = hdr; 1018 else 1019 { 1020 buf += hdr->cb; 1021 size -= hdr->cb; 1022 } 1023 } 1024 } 1025 return ret; 1026 } 1027 1028 static void testRegStore(void) 1029 { 1030 static const char tempKey[] = "Software\\Wine\\CryptTemp"; 1031 HCERTSTORE store; 1032 LONG rc; 1033 HKEY key = NULL; 1034 DWORD disp, GLE; 1035 1036 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL); 1037 GLE = GetLastError(); 1038 ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY), 1039 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE); 1040 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key); 1041 GLE = GetLastError(); 1042 ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY), 1043 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE); 1044 1045 /* Opening up any old key works.. */ 1046 key = HKEY_CURRENT_USER; 1047 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key); 1048 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now 1049 */ 1050 todo_wine ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError()); 1051 CertCloseStore(store, 0); 1052 1053 /* It looks like the remainder pretty much needs CertControlStore() */ 1054 if (!pCertControlStore) 1055 { 1056 win_skip("CertControlStore() is not available\n"); 1057 return; 1058 } 1059 1060 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS, 1061 NULL, &key, NULL); 1062 ok(!rc, "RegCreateKeyExA failed: %d\n", rc); 1063 if (key) 1064 { 1065 BOOL ret; 1066 BYTE hash[20]; 1067 DWORD size, i; 1068 static const char certificates[] = "Certificates\\"; 1069 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr; 1070 HKEY subKey; 1071 PCCERT_CONTEXT context; 1072 1073 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key); 1074 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError()); 1075 /* Add a certificate. It isn't persisted right away, since it's only 1076 * added to the cache.. 1077 */ 1078 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 1079 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL); 1080 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", 1081 GetLastError()); 1082 /* so flush the cache to force a commit.. */ 1083 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL); 1084 ok(ret, "CertControlStore failed: %08x\n", GetLastError()); 1085 /* and check that the expected subkey was written. */ 1086 size = sizeof(hash); 1087 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2), 1088 hash, &size); 1089 ok(ret, "CryptHashCertificate failed: %d\n", GetLastError()); 1090 strcpy(subKeyName, certificates); 1091 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size; 1092 i++, ptr += 2) 1093 sprintf(ptr, "%02X", hash[i]); 1094 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, 1095 &subKey, NULL); 1096 ok(!rc, "RegCreateKeyExA failed: %d\n", rc); 1097 if (subKey) 1098 { 1099 LPBYTE buf; 1100 1101 size = 0; 1102 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size); 1103 buf = HeapAlloc(GetProcessHeap(), 0, size); 1104 if (buf) 1105 { 1106 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size); 1107 ok(!rc, "RegQueryValueExA failed: %d\n", rc); 1108 if (!rc) 1109 { 1110 const struct CertPropIDHeader *hdr; 1111 1112 /* Both the hash and the cert should be present */ 1113 hdr = findPropID(buf, size, CERT_CERT_PROP_ID); 1114 ok(hdr != NULL, "Expected to find a cert property\n"); 1115 if (hdr) 1116 { 1117 ok(hdr->cb == sizeof(bigCert2), 1118 "Wrong size %d of cert property\n", hdr->cb); 1119 ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), bigCert2, 1120 hdr->cb), "Unexpected cert in cert property\n"); 1121 } 1122 hdr = findPropID(buf, size, CERT_HASH_PROP_ID); 1123 ok(hdr != NULL, "Expected to find a hash property\n"); 1124 if (hdr) 1125 { 1126 ok(hdr->cb == sizeof(hash), 1127 "Wrong size %d of hash property\n", hdr->cb); 1128 ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), hash, 1129 hdr->cb), "Unexpected hash in cert property\n"); 1130 } 1131 } 1132 HeapFree(GetProcessHeap(), 0, buf); 1133 } 1134 RegCloseKey(subKey); 1135 } 1136 1137 /* Remove the existing context */ 1138 context = CertEnumCertificatesInStore(store, NULL); 1139 ok(context != NULL, "Expected a cert context\n"); 1140 if (context) 1141 CertDeleteCertificateFromStore(context); 1142 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL); 1143 ok(ret, "CertControlStore failed: %08x\n", GetLastError()); 1144 1145 /* Add a serialized cert with a bogus hash directly to the registry */ 1146 memset(hash, 0, sizeof(hash)); 1147 strcpy(subKeyName, certificates); 1148 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; 1149 i < sizeof(hash); i++, ptr += 2) 1150 sprintf(ptr, "%02X", hash[i]); 1151 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, 1152 &subKey, NULL); 1153 ok(!rc, "RegCreateKeyExA failed: %d\n", rc); 1154 if (subKey) 1155 { 1156 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) + 1157 sizeof(bigCert)], *ptr; 1158 DWORD certCount = 0; 1159 struct CertPropIDHeader *hdr; 1160 1161 hdr = (struct CertPropIDHeader *)buf; 1162 hdr->propID = CERT_HASH_PROP_ID; 1163 hdr->unknown1 = 1; 1164 hdr->cb = sizeof(hash); 1165 ptr = buf + sizeof(*hdr); 1166 memcpy(ptr, hash, sizeof(hash)); 1167 ptr += sizeof(hash); 1168 hdr = (struct CertPropIDHeader *)ptr; 1169 hdr->propID = CERT_CERT_PROP_ID; 1170 hdr->unknown1 = 1; 1171 hdr->cb = sizeof(bigCert); 1172 ptr += sizeof(*hdr); 1173 memcpy(ptr, bigCert, sizeof(bigCert)); 1174 1175 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf, 1176 sizeof(buf)); 1177 ok(!rc, "RegSetValueExA failed: %d\n", rc); 1178 1179 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL); 1180 ok(ret, "CertControlStore failed: %08x\n", GetLastError()); 1181 1182 /* Make sure the bogus hash cert gets loaded. */ 1183 certCount = 0; 1184 context = NULL; 1185 do { 1186 context = CertEnumCertificatesInStore(store, context); 1187 if (context) 1188 certCount++; 1189 } while (context != NULL); 1190 ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount); 1191 1192 RegCloseKey(subKey); 1193 } 1194 1195 /* Add another serialized cert directly to the registry, this time 1196 * under the correct key name (named with the correct hash value). 1197 */ 1198 size = sizeof(hash); 1199 ret = CryptHashCertificate(0, 0, 0, bigCert2, 1200 sizeof(bigCert2), hash, &size); 1201 ok(ret, "CryptHashCertificate failed: %d\n", GetLastError()); 1202 strcpy(subKeyName, certificates); 1203 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; 1204 i < sizeof(hash); i++, ptr += 2) 1205 sprintf(ptr, "%02X", hash[i]); 1206 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, 1207 &subKey, NULL); 1208 ok(!rc, "RegCreateKeyExA failed: %d\n", rc); 1209 if (subKey) 1210 { 1211 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) + 1212 sizeof(bigCert2)], *ptr; 1213 DWORD certCount = 0; 1214 PCCERT_CONTEXT context; 1215 struct CertPropIDHeader *hdr; 1216 1217 /* First try with a bogus hash... */ 1218 hdr = (struct CertPropIDHeader *)buf; 1219 hdr->propID = CERT_HASH_PROP_ID; 1220 hdr->unknown1 = 1; 1221 hdr->cb = sizeof(hash); 1222 ptr = buf + sizeof(*hdr); 1223 memset(ptr, 0, sizeof(hash)); 1224 ptr += sizeof(hash); 1225 hdr = (struct CertPropIDHeader *)ptr; 1226 hdr->propID = CERT_CERT_PROP_ID; 1227 hdr->unknown1 = 1; 1228 hdr->cb = sizeof(bigCert2); 1229 ptr += sizeof(*hdr); 1230 memcpy(ptr, bigCert2, sizeof(bigCert2)); 1231 1232 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf, 1233 sizeof(buf)); 1234 ok(!rc, "RegSetValueExA failed: %d\n", rc); 1235 1236 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL); 1237 ok(ret, "CertControlStore failed: %08x\n", GetLastError()); 1238 1239 /* and make sure just one cert still gets loaded. */ 1240 certCount = 0; 1241 context = NULL; 1242 do { 1243 context = CertEnumCertificatesInStore(store, context); 1244 if (context) 1245 certCount++; 1246 } while (context != NULL); 1247 ok(certCount == 1 || 1248 broken(certCount == 2) /* NT4 */ , 1249 "Expected 1 certificates, got %d\n", certCount); 1250 1251 /* Try again with the correct hash... */ 1252 ptr = buf + sizeof(*hdr); 1253 memcpy(ptr, hash, sizeof(hash)); 1254 1255 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf, 1256 sizeof(buf)); 1257 ok(!rc, "RegSetValueExA failed: %d\n", rc); 1258 1259 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL); 1260 ok(ret, "CertControlStore failed: %08x\n", GetLastError()); 1261 1262 /* and make sure two certs get loaded. */ 1263 certCount = 0; 1264 context = NULL; 1265 do { 1266 context = CertEnumCertificatesInStore(store, context); 1267 if (context) 1268 certCount++; 1269 } while (context != NULL); 1270 ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount); 1271 1272 RegCloseKey(subKey); 1273 } 1274 CertCloseStore(store, 0); 1275 /* Is delete allowed on a reg store? */ 1276 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 1277 CERT_STORE_DELETE_FLAG, key); 1278 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n"); 1279 ok(GetLastError() == 0, "CertOpenStore failed: %08x\n", 1280 GetLastError()); 1281 1282 RegCloseKey(key); 1283 } 1284 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the 1285 * contents of the key, but not the key itself. 1286 */ 1287 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS, 1288 NULL, &key, &disp); 1289 ok(!rc, "RegCreateKeyExA failed: %d\n", rc); 1290 ok(disp == REG_OPENED_EXISTING_KEY, 1291 "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp); 1292 if (!rc) 1293 { 1294 RegCloseKey(key); 1295 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey); 1296 if (rc) 1297 { 1298 HMODULE shlwapi = LoadLibraryA("shlwapi"); 1299 1300 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key, 1301 * otherwise subsequent tests will fail. 1302 */ 1303 if (shlwapi) 1304 { 1305 DWORD (WINAPI *pSHDeleteKeyA)(HKEY, LPCSTR); 1306 1307 pSHDeleteKeyA = (void*)GetProcAddress(shlwapi, "SHDeleteKeyA"); 1308 if (pSHDeleteKeyA) 1309 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey); 1310 FreeLibrary(shlwapi); 1311 } 1312 } 1313 } 1314 } 1315 1316 static const char MyA[] = { 'M','y',0,0 }; 1317 static const WCHAR MyW[] = { 'M','y',0 }; 1318 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 }; 1319 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\', 1320 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r', 1321 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 }; 1322 1323 static void testSystemRegStore(void) 1324 { 1325 HCERTSTORE store, memStore; 1326 1327 /* Check with a UNICODE name */ 1328 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 1329 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW); 1330 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue 1331 * testing if they don't. 1332 */ 1333 if (!store) 1334 return; 1335 1336 /* Check that it isn't a collection store */ 1337 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 1338 CERT_STORE_CREATE_NEW_FLAG, NULL); 1339 if (memStore) 1340 { 1341 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0); 1342 ok(!ret && GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", GetLastError()); 1343 CertCloseStore(memStore, 0); 1344 } 1345 CertCloseStore(store, 0); 1346 1347 /* Check opening a bogus store */ 1348 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 1349 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW); 1350 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND, 1351 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 1352 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 1353 CERT_SYSTEM_STORE_CURRENT_USER, BogusW); 1354 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError()); 1355 if (store) 1356 CertCloseStore(store, 0); 1357 /* Now check whether deleting is allowed */ 1358 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 1359 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW); 1360 ok(!store, "CertOpenStore failed: %08x\n", GetLastError()); 1361 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW); 1362 1363 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL); 1364 ok(!store && GetLastError() == E_INVALIDARG, 1365 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 1366 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 1367 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA); 1368 ok(!store && GetLastError() == E_INVALIDARG, 1369 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 1370 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 1371 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW); 1372 ok(!store && GetLastError() == E_INVALIDARG, 1373 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 1374 /* The name is expected to be UNICODE, check with an ASCII name */ 1375 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 1376 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA); 1377 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND, 1378 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 1379 } 1380 1381 static void testSystemStore(void) 1382 { 1383 static const WCHAR baskslashW[] = { '\\',0 }; 1384 HCERTSTORE store; 1385 WCHAR keyName[MAX_PATH]; 1386 HKEY key; 1387 LONG rc; 1388 1389 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL); 1390 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND, 1391 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 1392 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 1393 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA); 1394 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND, 1395 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 1396 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 1397 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW); 1398 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND, 1399 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 1400 /* The name is expected to be UNICODE, first check with an ASCII name */ 1401 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 1402 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA); 1403 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND, 1404 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 1405 /* Create the expected key */ 1406 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH); 1407 lstrcatW(keyName, baskslashW); 1408 lstrcatW(keyName, MyW); 1409 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ, 1410 NULL, &key, NULL); 1411 ok(!rc, "RegCreateKeyEx failed: %d\n", rc); 1412 if (!rc) 1413 RegCloseKey(key); 1414 /* Check opening with a UNICODE name, specifying the create new flag */ 1415 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 1416 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW); 1417 ok(!store && GetLastError() == ERROR_FILE_EXISTS, 1418 "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError()); 1419 /* Now check opening with a UNICODE name, this time opening existing */ 1420 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 1421 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW); 1422 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError()); 1423 if (store) 1424 { 1425 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 1426 CERT_STORE_CREATE_NEW_FLAG, NULL); 1427 1428 /* Check that it's a collection store */ 1429 if (memStore) 1430 { 1431 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0); 1432 /* FIXME: this'll fail on NT4, but what error will it give? */ 1433 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError()); 1434 CertCloseStore(memStore, 0); 1435 } 1436 CertCloseStore(store, 0); 1437 } 1438 1439 /* Check opening a bogus store */ 1440 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 1441 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW); 1442 ok(!store, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 1443 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 1444 CERT_SYSTEM_STORE_CURRENT_USER, BogusW); 1445 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError()); 1446 if (store) 1447 CertCloseStore(store, 0); 1448 /* Now check whether deleting is allowed */ 1449 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 1450 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW); 1451 ok(!store, "Didn't expect a store to be returned when deleting\n"); 1452 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW); 1453 } 1454 1455 static const BYTE serializedStoreWithCertAndCRL[] = { 1456 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00, 1457 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30, 1458 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61, 1459 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31, 1460 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36, 1461 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15, 1462 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, 1463 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00, 1464 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04, 1465 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00, 1466 0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30, 1467 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61, 1468 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 1469 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11, 1470 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02, 1471 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; 1472 1473 static void testFileStore(void) 1474 { 1475 static const WCHAR szPrefix[] = { 'c','e','r',0 }; 1476 static const WCHAR szDot[] = { '.',0 }; 1477 WCHAR filename[MAX_PATH]; 1478 HCERTSTORE store; 1479 BOOL ret; 1480 PCCERT_CONTEXT cert; 1481 HANDLE file; 1482 1483 if (!pCertControlStore) 1484 { 1485 win_skip("CertControlStore() is not available\n"); 1486 return; 1487 } 1488 1489 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL); 1490 ok(!store && GetLastError() == ERROR_INVALID_HANDLE, 1491 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError()); 1492 1493 if (!GetTempFileNameW(szDot, szPrefix, 0, filename)) 1494 return; 1495 1496 DeleteFileW(filename); 1497 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 1498 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1499 if (file == INVALID_HANDLE_VALUE) 1500 return; 1501 1502 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG, 1503 file); 1504 ok(!store && GetLastError() == E_INVALIDARG, 1505 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 1506 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 1507 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file); 1508 ok(!store && GetLastError() == E_INVALIDARG, 1509 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 1510 1511 /* A "read-only" file store.. */ 1512 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 1513 CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file); 1514 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1515 if (store) 1516 { 1517 DWORD size; 1518 1519 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 1520 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 1521 /* apparently allows adding certificates.. */ 1522 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret); 1523 /* but not commits.. */ 1524 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL); 1525 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, 1526 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError()); 1527 /* It still has certs in memory.. */ 1528 cert = CertEnumCertificatesInStore(store, NULL); 1529 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n", 1530 GetLastError()); 1531 CertFreeCertificateContext(cert); 1532 /* but the file size is still 0. */ 1533 size = GetFileSize(file, NULL); 1534 ok(size == 0, "Expected size 0, got %d\n", size); 1535 CertCloseStore(store, 0); 1536 } 1537 1538 /* The create new flag is allowed.. */ 1539 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 1540 CERT_STORE_CREATE_NEW_FLAG, file); 1541 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1542 if (store) 1543 { 1544 /* but without the commit enable flag, commits don't happen. */ 1545 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 1546 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 1547 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret); 1548 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL); 1549 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, 1550 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError()); 1551 CertCloseStore(store, 0); 1552 } 1553 /* as is the open existing flag. */ 1554 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 1555 CERT_STORE_OPEN_EXISTING_FLAG, file); 1556 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1557 if (store) 1558 { 1559 /* but without the commit enable flag, commits don't happen. */ 1560 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 1561 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 1562 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret); 1563 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL); 1564 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, 1565 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError()); 1566 CertCloseStore(store, 0); 1567 } 1568 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 1569 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file); 1570 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1571 if (store) 1572 { 1573 CloseHandle(file); 1574 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 1575 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 1576 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", 1577 GetLastError()); 1578 /* with commits enabled, commit is allowed */ 1579 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL); 1580 ok(ret, "CertControlStore failed: %d\n", ret); 1581 compareStore(store, "serialized store with cert", 1582 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE); 1583 CertCloseStore(store, 0); 1584 } 1585 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 1586 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1587 if (file == INVALID_HANDLE_VALUE) 1588 return; 1589 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 1590 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file); 1591 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1592 if (store) 1593 { 1594 CloseHandle(file); 1595 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL, 1596 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL); 1597 ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError()); 1598 compareStore(store, "serialized store with cert and CRL", 1599 serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL), 1600 FALSE); 1601 CertCloseStore(store, 0); 1602 } 1603 1604 DeleteFileW(filename); 1605 } 1606 1607 static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb) 1608 { 1609 HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 1610 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1611 BOOL ret; 1612 1613 if (file != INVALID_HANDLE_VALUE) 1614 { 1615 DWORD written; 1616 1617 ret = WriteFile(file, pb, cb, &written, NULL); 1618 CloseHandle(file); 1619 } 1620 else 1621 ret = FALSE; 1622 return ret; 1623 } 1624 1625 static const BYTE base64SPC[] = 1626 "MIICJQYJKoZIhvcNAQcCoIICFjCCAhICAQExADALBgkqhkiG9w0BBwGgggH6MIIB" 1627 "9jCCAV+gAwIBAgIQnP8+EF4opr9OxH7h4uBPWTANBgkqhkiG9w0BAQQFADAUMRIw" 1628 "EAYDVQQDEwlKdWFuIExhbmcwHhcNMDgxMjEyMTcxMDE0WhcNMzkxMjMxMjM1OTU5" 1629 "WjAUMRIwEAYDVQQDEwlKdWFuIExhbmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ" 1630 "AoGBALCgNjyNvOic0FOfjxvi43HbM+D5joDkhiGSXe+gbZlf8f16k07kkObFEunz" 1631 "mdB5coscmA7gyqiWNN4ZUyr2cA3lCbnpGPA/0IblyyOcuGIFmmCzeZaVa5ZG6xZP" 1632 "K7L7o+73Qo6jXVbGhBGnMZ7Q9sAn6s2933olnStnejnqwV0NAgMBAAGjSTBHMEUG" 1633 "A1UdAQQ+MDyAEFKbKEdXYyx+CWKcV6vxM6ShFjAUMRIwEAYDVQQDEwlKdWFuIExh" 1634 "bmeCEJz/PhBeKKa/TsR+4eLgT1kwDQYJKoZIhvcNAQEEBQADgYEALpkgLgW3mEaK" 1635 "idPQ3iPJYLG0Ub1wraqEl9bd42hrhzIdcDzlQgxnm8/5cHYVxIF/C20x/HJplb1R" 1636 "G6U1ipFe/q8byWD/9JpiBKMGPi9YlUTgXHfS9d4S/QWO1h9Z7KeipBYhoslQpHXu" 1637 "y9bUr8Adqi6SzgHpCnMu53dxgxUD1r4xAA=="; 1638 /* Same as base64SPC, but as a wide-char string */ 1639 static const WCHAR utf16Base64SPC[] = { 1640 'M','I','I','C','J','Q','Y','J','K','o','Z','I','h','v','c','N','A', 1641 'Q','c','C','o','I','I','C','F','j','C','C','A','h','I','C','A','Q', 1642 'E','x','A','D','A','L','B','g','k','q','h','k','i','G','9','w','0', 1643 'B','B','w','G','g','g','g','H','6','M','I','I','B','9','j','C','C', 1644 'A','V','+','g','A','w','I','B','A','g','I','Q','n','P','8','+','E', 1645 'F','4','o','p','r','9','O','x','H','7','h','4','u','B','P','W','T', 1646 'A','N','B','g','k','q','h','k','i','G','9','w','0','B','A','Q','Q', 1647 'F','A','D','A','U','M','R','I','w','E','A','Y','D','V','Q','Q','D', 1648 'E','w','l','K','d','W','F','u','I','E','x','h','b','m','c','w','H', 1649 'h','c','N','M','D','g','x','M','j','E','y','M','T','c','x','M','D', 1650 'E','0','W','h','c','N','M','z','k','x','M','j','M','x','M','j','M', 1651 '1','O','T','U','5','W','j','A','U','M','R','I','w','E','A','Y','D', 1652 'V','Q','Q','D','E','w','l','K','d','W','F','u','I','E','x','h','b', 1653 'm','c','w','g','Z','8','w','D','Q','Y','J','K','o','Z','I','h','v', 1654 'c','N','A','Q','E','B','B','Q','A','D','g','Y','0','A','M','I','G', 1655 'J','A','o','G','B','A','L','C','g','N','j','y','N','v','O','i','c', 1656 '0','F','O','f','j','x','v','i','4','3','H','b','M','+','D','5','j', 1657 'o','D','k','h','i','G','S','X','e','+','g','b','Z','l','f','8','f', 1658 '1','6','k','0','7','k','k','O','b','F','E','u','n','z','m','d','B', 1659 '5','c','o','s','c','m','A','7','g','y','q','i','W','N','N','4','Z', 1660 'U','y','r','2','c','A','3','l','C','b','n','p','G','P','A','/','0', 1661 'I','b','l','y','y','O','c','u','G','I','F','m','m','C','z','e','Z', 1662 'a','V','a','5','Z','G','6','x','Z','P','K','7','L','7','o','+','7', 1663 '3','Q','o','6','j','X','V','b','G','h','B','G','n','M','Z','7','Q', 1664 '9','s','A','n','6','s','2','9','3','3','o','l','n','S','t','n','e', 1665 'j','n','q','w','V','0','N','A','g','M','B','A','A','G','j','S','T', 1666 'B','H','M','E','U','G','A','1','U','d','A','Q','Q','+','M','D','y', 1667 'A','E','F','K','b','K','E','d','X','Y','y','x','+','C','W','K','c', 1668 'V','6','v','x','M','6','S','h','F','j','A','U','M','R','I','w','E', 1669 'A','Y','D','V','Q','Q','D','E','w','l','K','d','W','F','u','I','E', 1670 'x','h','b','m','e','C','E','J','z','/','P','h','B','e','K','K','a', 1671 '/','T','s','R','+','4','e','L','g','T','1','k','w','D','Q','Y','J', 1672 'K','o','Z','I','h','v','c','N','A','Q','E','E','B','Q','A','D','g', 1673 'Y','E','A','L','p','k','g','L','g','W','3','m','E','a','K','i','d', 1674 'P','Q','3','i','P','J','Y','L','G','0','U','b','1','w','r','a','q', 1675 'E','l','9','b','d','4','2','h','r','h','z','I','d','c','D','z','l', 1676 'Q','g','x','n','m','8','/','5','c','H','Y','V','x','I','F','/','C', 1677 '2','0','x','/','H','J','p','l','b','1','R','G','6','U','1','i','p', 1678 'F','e','/','q','8','b','y','W','D','/','9','J','p','i','B','K','M', 1679 'G','P','i','9','Y','l','U','T','g','X','H','f','S','9','d','4','S', 1680 '/','Q','W','O','1','h','9','Z','7','K','e','i','p','B','Y','h','o', 1681 's','l','Q','p','H','X','u','y','9','b','U','r','8','A','d','q','i', 1682 '6','S','z','g','H','p','C','n','M','u','5','3','d','x','g','x','U', 1683 'D','1','r','4','x','A','A','=','=',0 }; 1684 1685 static void testFileNameStore(void) 1686 { 1687 static const WCHAR szPrefix[] = { 'c','e','r',0 }; 1688 static const WCHAR spcPrefix[] = { 's','p','c',0 }; 1689 static const WCHAR szDot[] = { '.',0 }; 1690 WCHAR filename[MAX_PATH]; 1691 HCERTSTORE store; 1692 BOOL ret; 1693 DWORD GLE; 1694 1695 if (0) 1696 { 1697 /* Crashes on NT4 */ 1698 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL); 1699 GLE = GetLastError(); 1700 ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER), 1701 "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n", 1702 GLE); 1703 } 1704 1705 if (!GetTempFileNameW(szDot, szPrefix, 0, filename)) 1706 return; 1707 DeleteFileW(filename); 1708 1709 /* The two flags are mutually exclusive */ 1710 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1711 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename); 1712 ok(!store && GetLastError() == E_INVALIDARG, 1713 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 1714 1715 /* In all of the following tests, the encoding type seems to be ignored */ 1716 if (initFileFromData(filename, bigCert, sizeof(bigCert))) 1717 { 1718 PCCERT_CONTEXT cert; 1719 PCCRL_CONTEXT crl; 1720 1721 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1722 CERT_STORE_READONLY_FLAG, filename); 1723 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1724 1725 cert = CertEnumCertificatesInStore(store, NULL); 1726 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n", 1727 GetLastError()); 1728 cert = CertEnumCertificatesInStore(store, cert); 1729 ok(!cert, "Expected only one cert\n"); 1730 if (pCertEnumCRLsInStore) 1731 { 1732 crl = pCertEnumCRLsInStore(store, NULL); 1733 ok(!crl, "Expected no CRLs\n"); 1734 } 1735 1736 CertCloseStore(store, 0); 1737 DeleteFileW(filename); 1738 } 1739 if (initFileFromData(filename, serializedStoreWithCert, 1740 sizeof(serializedStoreWithCert))) 1741 { 1742 PCCERT_CONTEXT cert; 1743 PCCRL_CONTEXT crl; 1744 1745 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1746 CERT_STORE_READONLY_FLAG, filename); 1747 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1748 1749 cert = CertEnumCertificatesInStore(store, NULL); 1750 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n", 1751 GetLastError()); 1752 cert = CertEnumCertificatesInStore(store, cert); 1753 ok(!cert, "Expected only one cert\n"); 1754 if (pCertEnumCRLsInStore) 1755 { 1756 crl = pCertEnumCRLsInStore(store, NULL); 1757 ok(!crl, "Expected no CRLs\n"); 1758 } 1759 1760 CertCloseStore(store, 0); 1761 DeleteFileW(filename); 1762 } 1763 if (initFileFromData(filename, serializedStoreWithCertAndCRL, 1764 sizeof(serializedStoreWithCertAndCRL))) 1765 { 1766 PCCERT_CONTEXT cert; 1767 PCCRL_CONTEXT crl; 1768 1769 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1770 CERT_STORE_READONLY_FLAG, filename); 1771 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1772 1773 cert = CertEnumCertificatesInStore(store, NULL); 1774 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n", 1775 GetLastError()); 1776 cert = CertEnumCertificatesInStore(store, cert); 1777 ok(!cert, "Expected only one cert\n"); 1778 if (pCertEnumCRLsInStore) 1779 { 1780 crl = pCertEnumCRLsInStore(store, NULL); 1781 ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError()); 1782 crl = pCertEnumCRLsInStore(store, crl); 1783 ok(!crl, "Expected only one CRL\n"); 1784 } 1785 1786 CertCloseStore(store, 0); 1787 /* Don't delete it this time, the next test uses it */ 1788 } 1789 /* Now that the file exists, we can open it read-only */ 1790 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1791 CERT_STORE_READONLY_FLAG, filename); 1792 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1793 CertCloseStore(store, 0); 1794 DeleteFileW(filename); 1795 1796 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1797 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename); 1798 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1799 if (store) 1800 { 1801 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 1802 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 1803 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", 1804 GetLastError()); 1805 compareStore(store, "serialized store with cert", 1806 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE); 1807 CertCloseStore(store, 0); 1808 } 1809 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1810 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename); 1811 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1812 if (store) 1813 { 1814 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, 1815 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL); 1816 ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError()); 1817 compareStore(store, "serialized store with cert and CRL", 1818 serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL), 1819 FALSE); 1820 CertCloseStore(store, 0); 1821 } 1822 DeleteFileW(filename); 1823 1824 if (!GetTempFileNameW(szDot, spcPrefix, 0, filename)) 1825 return; 1826 DeleteFileW(filename); 1827 1828 if (initFileFromData(filename, base64SPC, sizeof(base64SPC))) 1829 { 1830 PCCERT_CONTEXT cert; 1831 PCCRL_CONTEXT crl; 1832 1833 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1834 CERT_STORE_READONLY_FLAG, filename); 1835 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1836 1837 cert = CertEnumCertificatesInStore(store, NULL); 1838 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n", 1839 GetLastError()); 1840 cert = CertEnumCertificatesInStore(store, cert); 1841 ok(!cert, "Expected only one cert\n"); 1842 if (pCertEnumCRLsInStore) 1843 { 1844 crl = pCertEnumCRLsInStore(store, NULL); 1845 ok(!crl, "Expected no CRLs\n"); 1846 } 1847 1848 CertCloseStore(store, 0); 1849 DeleteFileW(filename); 1850 } 1851 if (initFileFromData(filename, (BYTE *)utf16Base64SPC, 1852 sizeof(utf16Base64SPC))) 1853 { 1854 PCCERT_CONTEXT cert; 1855 PCCRL_CONTEXT crl; 1856 1857 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 1858 CERT_STORE_READONLY_FLAG, filename); 1859 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1860 1861 cert = CertEnumCertificatesInStore(store, NULL); 1862 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n", 1863 GetLastError()); 1864 cert = CertEnumCertificatesInStore(store, cert); 1865 ok(!cert, "Expected only one cert\n"); 1866 if (pCertEnumCRLsInStore) 1867 { 1868 crl = pCertEnumCRLsInStore(store, NULL); 1869 ok(!crl, "Expected no CRLs\n"); 1870 } 1871 1872 CertCloseStore(store, 0); 1873 DeleteFileW(filename); 1874 } 1875 } 1876 1877 static const BYTE signedContent[] = { 1878 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, 1879 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a, 1880 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86, 1881 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04, 1882 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11, 1883 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 1884 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, 1885 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70, 1886 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d, 1887 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe, 1888 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29, 1889 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8, 1890 0x0d }; 1891 static const BYTE signedWithCertAndCrlBareContent[] = { 1892 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86, 1893 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48, 1894 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0, 1895 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30, 1896 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, 1897 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31, 1898 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 1899 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11, 1900 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 1901 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14, 1902 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01, 1903 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15, 1904 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, 1905 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, 1906 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01, 1907 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a, 1908 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c, 1909 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06, 1910 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b, 1911 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c, 1912 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d, 1913 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39, 1914 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d }; 1915 static const BYTE hashContent[] = { 1916 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a, 1917 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, 1918 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, 1919 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0, 1920 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f }; 1921 static const BYTE hashBareContent[] = { 1922 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, 1923 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, 1924 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0, 1925 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f }; 1926 1927 static void testMessageStore(void) 1928 { 1929 HCERTSTORE store; 1930 HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, 1931 NULL); 1932 CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent), 1933 (LPBYTE)signedWithCertAndCrlBareContent }; 1934 DWORD count, size; 1935 BOOL ret; 1936 1937 /* Crashes 1938 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL); 1939 */ 1940 SetLastError(0xdeadbeef); 1941 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg); 1942 ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, 1943 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError()); 1944 CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE); 1945 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg); 1946 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1947 if (store) 1948 { 1949 PCCERT_CONTEXT cert = NULL; 1950 PCCRL_CONTEXT crl = NULL; 1951 1952 count = 0; 1953 do { 1954 cert = CertEnumCertificatesInStore(store, cert); 1955 if (cert) 1956 count++; 1957 } while (cert); 1958 ok(count == 0, "Expected 0 certificates, got %d\n", count); 1959 1960 if (pCertEnumCRLsInStore) 1961 { 1962 count = 0; 1963 do { 1964 crl = pCertEnumCRLsInStore(store, crl); 1965 if (crl) 1966 count++; 1967 } while (crl); 1968 ok(count == 0, "Expected 0 CRLs, got %d\n", count); 1969 } 1970 1971 /* Can add certs to a message store */ 1972 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, 1973 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL); 1974 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", 1975 GetLastError()); 1976 count = 0; 1977 do { 1978 cert = CertEnumCertificatesInStore(store, cert); 1979 if (cert) 1980 count++; 1981 } while (cert); 1982 ok(count == 1, "Expected 1 certificate, got %d\n", count); 1983 1984 CertCloseStore(store, 0); 1985 } 1986 /* but the added certs weren't actually added to the message */ 1987 size = sizeof(count); 1988 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size); 1989 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError()); 1990 ok(count == 0, "Expected 0 certificates, got %d\n", count); 1991 CryptMsgClose(msg); 1992 1993 /* Crashes 1994 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL); 1995 */ 1996 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob); 1997 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 1998 if (store) 1999 { 2000 DWORD count = 0; 2001 PCCERT_CONTEXT cert = NULL; 2002 PCCRL_CONTEXT crl = NULL; 2003 2004 do { 2005 cert = CertEnumCertificatesInStore(store, cert); 2006 if (cert) 2007 count++; 2008 } while (cert); 2009 ok(count == 1, "Expected 1 certificate, got %d\n", count); 2010 2011 if (pCertEnumCRLsInStore) 2012 { 2013 count = 0; 2014 do { 2015 crl = pCertEnumCRLsInStore(store, crl); 2016 if (crl) 2017 count++; 2018 } while (crl); 2019 ok(count == 1, "Expected 1 CRL, got %d\n", count); 2020 } 2021 CertCloseStore(store, 0); 2022 } 2023 /* Encoding appears to be ignored */ 2024 store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0, 2025 &blob); 2026 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 2027 if (store) 2028 CertCloseStore(store, 0); 2029 /* Messages other than signed messages aren't allowed */ 2030 blob.cbData = sizeof(hashContent); 2031 blob.pbData = (LPBYTE)hashContent; 2032 SetLastError(0xdeadbeef); 2033 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob); 2034 ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, 2035 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError()); 2036 blob.cbData = sizeof(hashBareContent); 2037 blob.pbData = (LPBYTE)hashBareContent; 2038 SetLastError(0xdeadbeef); 2039 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob); 2040 ok(!store && 2041 (GetLastError() == CRYPT_E_ASN1_BADTAG || 2042 broken(GetLastError() == OSS_DATA_ERROR)), /* NT4 */ 2043 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); 2044 } 2045 2046 static void testSerializedStore(void) 2047 { 2048 HCERTSTORE store; 2049 CRYPT_DATA_BLOB blob; 2050 2051 if (0) 2052 { 2053 /* Crash */ 2054 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, NULL); 2055 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 2056 CERT_STORE_DELETE_FLAG, NULL); 2057 } 2058 blob.cbData = sizeof(serializedStoreWithCert); 2059 blob.pbData = (BYTE *)serializedStoreWithCert; 2060 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 2061 CERT_STORE_DELETE_FLAG, &blob); 2062 ok(!store && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, 2063 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError()); 2064 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob); 2065 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 2066 if (store) 2067 { 2068 PCCERT_CONTEXT cert; 2069 PCCRL_CONTEXT crl; 2070 2071 cert = CertEnumCertificatesInStore(store, NULL); 2072 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n", 2073 GetLastError()); 2074 cert = CertEnumCertificatesInStore(store, cert); 2075 ok(!cert, "Expected only one cert\n"); 2076 if (pCertEnumCRLsInStore) 2077 { 2078 crl = pCertEnumCRLsInStore(store, NULL); 2079 ok(!crl, "Expected no CRLs\n"); 2080 } 2081 CertCloseStore(store, 0); 2082 } 2083 blob.cbData = sizeof(serializedStoreWithCertAndCRL); 2084 blob.pbData = (BYTE *)serializedStoreWithCertAndCRL; 2085 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob); 2086 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 2087 if (store) 2088 { 2089 PCCERT_CONTEXT cert; 2090 PCCRL_CONTEXT crl; 2091 2092 cert = CertEnumCertificatesInStore(store, NULL); 2093 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n", 2094 GetLastError()); 2095 cert = CertEnumCertificatesInStore(store, cert); 2096 ok(!cert, "Expected only one cert\n"); 2097 if (pCertEnumCRLsInStore) 2098 { 2099 crl = pCertEnumCRLsInStore(store, NULL); 2100 ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", 2101 GetLastError()); 2102 crl = pCertEnumCRLsInStore(store, crl); 2103 ok(!crl, "Expected only one CRL\n"); 2104 } 2105 CertCloseStore(store, 0); 2106 } 2107 } 2108 2109 static void testCertOpenSystemStore(void) 2110 { 2111 HCERTSTORE store; 2112 2113 store = CertOpenSystemStoreW(0, NULL); 2114 ok(!store && GetLastError() == E_INVALIDARG, 2115 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2116 /* This succeeds, and on WinXP at least, the Bogus key is created under 2117 * HKCU (but not under HKLM, even when run as an administrator.) 2118 */ 2119 store = CertOpenSystemStoreW(0, BogusW); 2120 ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError()); 2121 if (store) 2122 CertCloseStore(store, 0); 2123 /* Delete it so other tests succeed next time around */ 2124 CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 2125 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW); 2126 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW); 2127 } 2128 2129 static const struct 2130 { 2131 DWORD cert_store; 2132 BOOL expected; 2133 BOOL todo; 2134 } reg_system_store_test_data[] = { 2135 { CERT_SYSTEM_STORE_CURRENT_USER, TRUE, 0}, 2136 /* Following tests could require administrator privileges and thus could be skipped */ 2137 { CERT_SYSTEM_STORE_CURRENT_SERVICE, TRUE, 1}, 2138 { CERT_SYSTEM_STORE_LOCAL_MACHINE, TRUE, 0}, 2139 { CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, TRUE, 0}, 2140 { CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, TRUE, 0}, 2141 { CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, TRUE, 1} 2142 }; 2143 2144 static void testCertRegisterSystemStore(void) 2145 { 2146 BOOL ret, cur_flag; 2147 DWORD err = 0; 2148 HCERTSTORE hstore; 2149 static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0}; 2150 const CERT_CONTEXT *cert, *cert2; 2151 unsigned int i; 2152 2153 if (!pCertRegisterSystemStore || !pCertUnregisterSystemStore) 2154 { 2155 win_skip("CertRegisterSystemStore() or CertUnregisterSystemStore() is not available\n"); 2156 return; 2157 } 2158 2159 for (i = 0; i < sizeof(reg_system_store_test_data) / sizeof(reg_system_store_test_data[0]); i++) { 2160 cur_flag = reg_system_store_test_data[i].cert_store; 2161 ret = pCertRegisterSystemStore(WineTestW, cur_flag, NULL, NULL); 2162 if (!ret) 2163 { 2164 err = GetLastError(); 2165 if (err == ERROR_ACCESS_DENIED) 2166 { 2167 win_skip("Insufficient privileges for the flag %08x test\n", cur_flag); 2168 continue; 2169 } 2170 } 2171 todo_wine_if (reg_system_store_test_data[i].todo) 2172 ok (ret == reg_system_store_test_data[i].expected, 2173 "Store registration (dwFlags=%08x) failed, last error %x\n", cur_flag, err); 2174 if (!ret) 2175 { 2176 skip("Nothing to test without registered store at %08x\n", cur_flag); 2177 continue; 2178 } 2179 2180 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | cur_flag, WineTestW); 2181 ok (hstore != NULL, "Opening just registered store at %08x failed, last error %x\n", cur_flag, GetLastError()); 2182 2183 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert)); 2184 ok (cert != NULL, "Failed creating cert at %08x, last error: %x\n", cur_flag, GetLastError()); 2185 if (cert) 2186 { 2187 ret = CertAddCertificateContextToStore(hstore, cert, CERT_STORE_ADD_NEW, NULL); 2188 ok (ret, "Failed to add cert at %08x, last error: %x\n", cur_flag, GetLastError()); 2189 2190 cert2 = CertEnumCertificatesInStore(hstore, NULL); 2191 ok (cert2 != NULL && cert2->cbCertEncoded == cert->cbCertEncoded, 2192 "Unexpected cert encoded size at %08x, last error: %x\n", cur_flag, GetLastError()); 2193 2194 ret = CertDeleteCertificateFromStore(cert2); 2195 ok (ret, "Failed to delete certificate from the new store at %08x, last error: %x\n", cur_flag, GetLastError()); 2196 2197 CertFreeCertificateContext(cert); 2198 } 2199 2200 ret = CertCloseStore(hstore, 0); 2201 ok (ret, "CertCloseStore failed at %08x, last error %x\n", cur_flag, GetLastError()); 2202 2203 ret = pCertUnregisterSystemStore(WineTestW, cur_flag ); 2204 todo_wine_if (reg_system_store_test_data[i].todo) 2205 ok( ret == reg_system_store_test_data[i].expected, 2206 "Unregistering failed at %08x, last error %d\n", cur_flag, GetLastError()); 2207 } 2208 2209 } 2210 2211 struct EnumSystemStoreInfo 2212 { 2213 BOOL goOn; 2214 DWORD storeCount; 2215 }; 2216 2217 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags, 2218 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg) 2219 { 2220 struct EnumSystemStoreInfo *info = pvArg; 2221 2222 info->storeCount++; 2223 return info->goOn; 2224 } 2225 2226 static void testCertEnumSystemStore(void) 2227 { 2228 BOOL ret; 2229 struct EnumSystemStoreInfo info = { FALSE, 0 }; 2230 2231 if (!pCertEnumSystemStore) 2232 { 2233 win_skip("CertEnumSystemStore() is not available\n"); 2234 return; 2235 } 2236 2237 SetLastError(0xdeadbeef); 2238 ret = pCertEnumSystemStore(0, NULL, NULL, NULL); 2239 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 2240 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 2241 /* Crashes 2242 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL, 2243 NULL); 2244 */ 2245 2246 SetLastError(0xdeadbeef); 2247 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info, 2248 enumSystemStoreCB); 2249 /* Callback returning FALSE stops enumeration */ 2250 ok(!ret, "Expected CertEnumSystemStore to stop\n"); 2251 ok(info.storeCount == 0 || info.storeCount == 1, 2252 "Expected 0 or 1 stores\n"); 2253 2254 info.goOn = TRUE; 2255 info.storeCount = 0; 2256 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info, 2257 enumSystemStoreCB); 2258 ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError()); 2259 /* There should always be at least My, Root, and CA stores */ 2260 ok(info.storeCount == 0 || info.storeCount >= 3, 2261 "Expected at least 3 stores\n"); 2262 } 2263 2264 static void testStoreProperty(void) 2265 { 2266 HCERTSTORE store; 2267 BOOL ret; 2268 DWORD propID, size = 0, state; 2269 CRYPT_DATA_BLOB blob; 2270 2271 if (!pCertGetStoreProperty || !pCertSetStoreProperty) 2272 { 2273 win_skip("CertGet/SetStoreProperty() is not available\n"); 2274 return; 2275 } 2276 2277 /* Crash 2278 ret = pCertGetStoreProperty(NULL, 0, NULL, NULL); 2279 ret = pCertGetStoreProperty(NULL, 0, NULL, &size); 2280 ret = pCertGetStoreProperty(store, 0, NULL, NULL); 2281 */ 2282 2283 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 2284 CERT_STORE_CREATE_NEW_FLAG, NULL); 2285 /* Check a missing prop ID */ 2286 SetLastError(0xdeadbeef); 2287 ret = pCertGetStoreProperty(store, 0, NULL, &size); 2288 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, 2289 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); 2290 /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */ 2291 size = sizeof(state); 2292 ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size); 2293 ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n", 2294 GetLastError()); 2295 ok(!state, "Expected a non-persisted store\n"); 2296 /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */ 2297 size = 0; 2298 ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL, 2299 &size); 2300 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, 2301 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); 2302 /* Delete an arbitrary property on a store */ 2303 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL); 2304 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError()); 2305 /* Set an arbitrary property on a store */ 2306 blob.pbData = (LPBYTE)&state; 2307 blob.cbData = sizeof(state); 2308 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob); 2309 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError()); 2310 /* Get an arbitrary property that's been set */ 2311 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size); 2312 ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError()); 2313 ok(size == sizeof(state), "Unexpected data size %d\n", size); 2314 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size); 2315 ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError()); 2316 ok(propID == state, "CertGetStoreProperty got the wrong value\n"); 2317 /* Delete it again */ 2318 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL); 2319 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError()); 2320 /* And check that it's missing */ 2321 SetLastError(0xdeadbeef); 2322 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size); 2323 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, 2324 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); 2325 CertCloseStore(store, 0); 2326 2327 /* Recheck on the My store.. */ 2328 store = CertOpenSystemStoreW(0, MyW); 2329 size = sizeof(state); 2330 ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size); 2331 ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n", 2332 GetLastError()); 2333 ok(state, "Expected a persisted store\n"); 2334 SetLastError(0xdeadbeef); 2335 size = 0; 2336 ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL, 2337 &size); 2338 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, 2339 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); 2340 CertCloseStore(store, 0); 2341 } 2342 2343 static void testAddSerialized(void) 2344 { 2345 BOOL ret; 2346 HCERTSTORE store; 2347 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] = 2348 { 0 }; 2349 BYTE hash[20]; 2350 struct CertPropIDHeader *hdr; 2351 PCCERT_CONTEXT context; 2352 2353 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL); 2354 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA, 2355 "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError()); 2356 2357 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 2358 CERT_STORE_CREATE_NEW_FLAG, NULL); 2359 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError()); 2360 2361 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL); 2362 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA, 2363 "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError()); 2364 2365 /* Test with an empty property */ 2366 hdr = (struct CertPropIDHeader *)buf; 2367 hdr->propID = CERT_CERT_PROP_ID; 2368 hdr->unknown1 = 1; 2369 hdr->cb = 0; 2370 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0, 2371 NULL, NULL); 2372 ok(!ret && GetLastError() == E_INVALIDARG, 2373 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2374 /* Test with a bad size in property header */ 2375 hdr->cb = sizeof(bigCert) - 1; 2376 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert)); 2377 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0, 2378 NULL, NULL); 2379 ok(!ret && GetLastError() == E_INVALIDARG, 2380 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2381 ret = CertAddSerializedElementToStore(store, buf, 2382 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL, 2383 NULL); 2384 ok(!ret && GetLastError() == E_INVALIDARG, 2385 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2386 ret = CertAddSerializedElementToStore(store, buf, 2387 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW, 2388 0, 0, NULL, NULL); 2389 ok(!ret && GetLastError() == E_INVALIDARG, 2390 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2391 /* Kosher size in property header, but no context type */ 2392 hdr->cb = sizeof(bigCert); 2393 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0, 2394 NULL, NULL); 2395 ok(!ret && GetLastError() == E_INVALIDARG, 2396 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2397 ret = CertAddSerializedElementToStore(store, buf, 2398 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL, 2399 NULL); 2400 ok(!ret && GetLastError() == E_INVALIDARG, 2401 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2402 ret = CertAddSerializedElementToStore(store, buf, 2403 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW, 2404 0, 0, NULL, NULL); 2405 ok(!ret && GetLastError() == E_INVALIDARG, 2406 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2407 /* With a bad context type */ 2408 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 2409 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL); 2410 ok(!ret && GetLastError() == E_INVALIDARG, 2411 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2412 ret = CertAddSerializedElementToStore(store, buf, 2413 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 2414 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL); 2415 ok(!ret && GetLastError() == E_INVALIDARG, 2416 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2417 ret = CertAddSerializedElementToStore(store, buf, 2418 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW, 2419 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL); 2420 ok(!ret && GetLastError() == E_INVALIDARG, 2421 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2422 /* Bad unknown field, good type */ 2423 hdr->unknown1 = 2; 2424 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 2425 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL); 2426 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 2427 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError()); 2428 ret = CertAddSerializedElementToStore(store, buf, 2429 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 2430 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL); 2431 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 2432 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError()); 2433 ret = CertAddSerializedElementToStore(store, buf, 2434 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW, 2435 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL); 2436 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 2437 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError()); 2438 /* Most everything okay, but bad add disposition */ 2439 hdr->unknown1 = 1; 2440 /* This crashes 2441 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 2442 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL); 2443 * as does this 2444 ret = CertAddSerializedElementToStore(store, buf, 2445 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 2446 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL); 2447 */ 2448 /* Everything okay, but buffer's too big */ 2449 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 2450 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL); 2451 ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError()); 2452 /* Everything okay, check it's not re-added */ 2453 ret = CertAddSerializedElementToStore(store, buf, 2454 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW, 2455 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL); 2456 ok(!ret && GetLastError() == CRYPT_E_EXISTS, 2457 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError()); 2458 2459 context = CertEnumCertificatesInStore(store, NULL); 2460 ok(context != NULL, "Expected a cert\n"); 2461 if (context) 2462 CertDeleteCertificateFromStore(context); 2463 2464 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash, 2465 * when queried, is the real hash rather than the bogus hash. 2466 */ 2467 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) + 2468 sizeof(bigCert)); 2469 hdr->propID = CERT_HASH_PROP_ID; 2470 hdr->unknown1 = 1; 2471 hdr->cb = sizeof(hash); 2472 memset(hash, 0xc, sizeof(hash)); 2473 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash)); 2474 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 2475 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, 2476 (const void **)&context); 2477 ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError()); 2478 if (context) 2479 { 2480 BYTE hashVal[20], realHash[20]; 2481 DWORD size = sizeof(hashVal); 2482 2483 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert), 2484 realHash, &size); 2485 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError()); 2486 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID, 2487 hashVal, &size); 2488 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", 2489 GetLastError()); 2490 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n"); 2491 CertFreeCertificateContext(context); 2492 } 2493 2494 CertCloseStore(store, 0); 2495 } 2496 2497 static const BYTE serializedCertWithFriendlyName[] = { 2498 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69, 2499 0x00,0x6e,0x00,0x65,0x00,0x54,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00, 2500 0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02, 2501 0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55, 2502 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30, 2503 0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30, 2504 0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30, 2505 0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, 2506 0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07, 2507 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03, 2508 0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01, 2509 0x01 }; 2510 static const BYTE serializedStoreWithCertWithFriendlyName[] = { 2511 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x0b,0x00,0x00,0x00,0x01,0x00,0x00, 2512 0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,0x00,0x6e,0x00,0x65,0x00,0x54,0x00, 2513 0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00, 2514 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30, 2515 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61, 2516 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31, 2517 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36, 2518 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15, 2519 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, 2520 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00, 2521 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04, 2522 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00, 2523 0x00,0x00,0x00,0x00,0x00,0x00 }; 2524 static const BYTE serializedStoreWithCertAndHash[] = { 2525 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x03,0x00,0x00,0x00,0x01,0x00,0x00, 2526 0x00,0x14,0x00,0x00,0x00,0x6e,0x30,0x90,0x71,0x5f,0xd9,0x23,0x56,0xeb,0xae, 2527 0x25,0x40,0xe6,0x22,0xda,0x19,0x26,0x02,0xa6,0x08,0x20,0x00,0x00,0x00,0x01, 2528 0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06, 2529 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a, 2530 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36, 2531 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f, 2532 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a, 2533 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75, 2534 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03, 2535 0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01, 2536 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00, 2537 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; 2538 2539 static void delete_test_key(void) 2540 { 2541 HKEY root_key, test_key; 2542 static const WCHAR SysCertW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 2543 'S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0}; 2544 static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0}; 2545 WCHAR subkey_name[32]; 2546 DWORD num_subkeys, subkey_name_len; 2547 int idx; 2548 2549 if (RegOpenKeyExW(HKEY_CURRENT_USER, SysCertW, 0, KEY_READ, &root_key)) 2550 return; 2551 if (RegOpenKeyExW(root_key, WineTestW, 0, KEY_READ, &test_key)) 2552 { 2553 RegCloseKey(root_key); 2554 return; 2555 } 2556 RegQueryInfoKeyW(test_key, NULL, NULL, NULL, &num_subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 2557 for (idx = num_subkeys; idx-- > 0;) 2558 { 2559 subkey_name_len = sizeof(subkey_name)/sizeof(WCHAR); 2560 RegEnumKeyExW(test_key, idx, subkey_name, &subkey_name_len, NULL, NULL, NULL, NULL); 2561 RegDeleteKeyW(test_key, subkey_name); 2562 } 2563 RegCloseKey(test_key); 2564 RegDeleteKeyW(root_key, WineTestW); 2565 RegCloseKey(root_key); 2566 } 2567 2568 static void testAddCertificateLink(void) 2569 { 2570 BOOL ret; 2571 HCERTSTORE store1, store2; 2572 PCCERT_CONTEXT source, linked; 2573 DWORD size; 2574 LPBYTE buf; 2575 CERT_NAME_BLOB blob; 2576 static const WCHAR szPrefix[] = { 'c','e','r',0 }; 2577 static const WCHAR szDot[] = { '.',0 }; 2578 static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 }; 2579 WCHAR filename1[MAX_PATH], filename2[MAX_PATH]; 2580 HANDLE file; 2581 2582 if (!pCertAddCertificateLinkToStore) 2583 { 2584 win_skip("CertAddCertificateLinkToStore not found\n"); 2585 return; 2586 } 2587 2588 if (0) 2589 { 2590 /* Crashes, i.e. the store is dereferenced without checking. */ 2591 ret = pCertAddCertificateLinkToStore(NULL, NULL, 0, NULL); 2592 } 2593 2594 /* Adding a certificate link to a store requires a valid add disposition */ 2595 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 2596 CERT_STORE_CREATE_NEW_FLAG, NULL); 2597 SetLastError(0xdeadbeef); 2598 ret = pCertAddCertificateLinkToStore(store1, NULL, 0, NULL); 2599 ok(!ret && GetLastError() == E_INVALIDARG, 2600 "expected E_INVALIDARG, got %08x\n", GetLastError()); 2601 source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, 2602 sizeof(bigCert)); 2603 SetLastError(0xdeadbeef); 2604 ret = pCertAddCertificateLinkToStore(store1, source, 0, NULL); 2605 ok(!ret && GetLastError() == E_INVALIDARG, 2606 "expected E_INVALIDARG, got %08x\n", GetLastError()); 2607 ret = pCertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS, 2608 NULL); 2609 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError()); 2610 if (0) 2611 { 2612 /* Crashes, i.e. the source certificate is dereferenced without 2613 * checking when a valid add disposition is given. 2614 */ 2615 ret = pCertAddCertificateLinkToStore(store1, NULL, CERT_STORE_ADD_ALWAYS, 2616 NULL); 2617 } 2618 CertCloseStore(store1, 0); 2619 2620 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 2621 CERT_STORE_CREATE_NEW_FLAG, NULL); 2622 ret = pCertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS, 2623 &linked); 2624 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError()); 2625 if (ret) 2626 { 2627 ok(linked->hCertStore == store1, "unexpected store\n"); 2628 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size); 2629 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", 2630 GetLastError()); 2631 buf = HeapAlloc(GetProcessHeap(), 0, size); 2632 if (buf) 2633 { 2634 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size); 2635 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", 2636 GetLastError()); 2637 /* The serialized linked certificate is identical to the serialized 2638 * original certificate. 2639 */ 2640 ok(size == sizeof(serializedCert), "Wrong size %d\n", size); 2641 ok(!memcmp(serializedCert, buf, size), 2642 "Unexpected serialized cert\n"); 2643 HeapFree(GetProcessHeap(), 0, buf); 2644 } 2645 /* Set a friendly name on the source certificate... */ 2646 blob.pbData = (LPBYTE)WineTestW; 2647 blob.cbData = sizeof(WineTestW); 2648 ret = CertSetCertificateContextProperty(source, 2649 CERT_FRIENDLY_NAME_PROP_ID, 0, &blob); 2650 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", 2651 GetLastError()); 2652 /* and the linked certificate has the same friendly name. */ 2653 ret = CertGetCertificateContextProperty(linked, 2654 CERT_FRIENDLY_NAME_PROP_ID, NULL, &size); 2655 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", 2656 GetLastError()); 2657 buf = HeapAlloc(GetProcessHeap(), 0, size); 2658 if (buf) 2659 { 2660 ret = CertGetCertificateContextProperty(linked, 2661 CERT_FRIENDLY_NAME_PROP_ID, buf, &size); 2662 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", 2663 GetLastError()); 2664 ok(!lstrcmpW((LPCWSTR)buf, WineTestW), 2665 "unexpected friendly name\n"); 2666 HeapFree(GetProcessHeap(), 0, buf); 2667 } 2668 CertFreeCertificateContext(linked); 2669 } 2670 CertFreeCertificateContext(source); 2671 CertCloseStore(store1, 0); 2672 2673 /* Test adding a cert to a file store, committing the change to the store, 2674 * and creating a link to the resulting cert. 2675 */ 2676 if (!GetTempFileNameW(szDot, szPrefix, 0, filename1)) 2677 return; 2678 2679 DeleteFileW(filename1); 2680 file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL, 2681 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 2682 if (file == INVALID_HANDLE_VALUE) 2683 return; 2684 2685 store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 2686 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file); 2687 ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 2688 CloseHandle(file); 2689 2690 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, 2691 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source); 2692 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", 2693 GetLastError()); 2694 2695 /* Test adding a link to a memory store. */ 2696 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 2697 CERT_STORE_CREATE_NEW_FLAG, NULL); 2698 ret = pCertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS, 2699 &linked); 2700 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError()); 2701 if (ret) 2702 { 2703 ok(linked->hCertStore == store2, "unexpected store\n"); 2704 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size); 2705 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", 2706 GetLastError()); 2707 buf = HeapAlloc(GetProcessHeap(), 0, size); 2708 if (buf) 2709 { 2710 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size); 2711 /* The serialized linked certificate is identical to the serialized 2712 * original certificate. 2713 */ 2714 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError()); 2715 ok(size == sizeof(serializedCert), "Wrong size %d\n", size); 2716 ok(!memcmp(serializedCert, buf, size), 2717 "Unexpected serialized cert\n"); 2718 HeapFree(GetProcessHeap(), 0, buf); 2719 } 2720 /* Set a friendly name on the source certificate... */ 2721 blob.pbData = (LPBYTE)WineTestW; 2722 blob.cbData = sizeof(WineTestW); 2723 ret = CertSetCertificateContextProperty(source, 2724 CERT_FRIENDLY_NAME_PROP_ID, 0, &blob); 2725 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", 2726 GetLastError()); 2727 /* and the linked certificate has the same friendly name. */ 2728 ret = CertGetCertificateContextProperty(linked, 2729 CERT_FRIENDLY_NAME_PROP_ID, NULL, &size); 2730 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", 2731 GetLastError()); 2732 buf = HeapAlloc(GetProcessHeap(), 0, size); 2733 if (buf) 2734 { 2735 ret = CertGetCertificateContextProperty(linked, 2736 CERT_FRIENDLY_NAME_PROP_ID, buf, &size); 2737 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError()); 2738 ok(!lstrcmpW((LPCWSTR)buf, WineTestW), 2739 "unexpected friendly name\n"); 2740 HeapFree(GetProcessHeap(), 0, buf); 2741 } 2742 CertFreeCertificateContext(linked); 2743 } 2744 CertCloseStore(store2, 0); 2745 2746 if (!GetTempFileNameW(szDot, szPrefix, 0, filename2)) 2747 return; 2748 2749 DeleteFileW(filename2); 2750 file = CreateFileW(filename2, GENERIC_READ | GENERIC_WRITE, 0, NULL, 2751 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 2752 if (file == INVALID_HANDLE_VALUE) 2753 return; 2754 2755 store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 2756 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file); 2757 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 2758 CloseHandle(file); 2759 /* Test adding a link to a file store. */ 2760 ret = pCertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS, 2761 &linked); 2762 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError()); 2763 if (ret) 2764 { 2765 ok(linked->hCertStore == store2, "unexpected store\n"); 2766 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size); 2767 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", 2768 GetLastError()); 2769 buf = HeapAlloc(GetProcessHeap(), 0, size); 2770 if (buf) 2771 { 2772 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size); 2773 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", 2774 GetLastError()); 2775 /* The serialized linked certificate now contains the friendly 2776 * name property. 2777 */ 2778 ok(size == sizeof(serializedCertWithFriendlyName), 2779 "Wrong size %d\n", size); 2780 ok(!memcmp(serializedCertWithFriendlyName, buf, size), 2781 "Unexpected serialized cert\n"); 2782 HeapFree(GetProcessHeap(), 0, buf); 2783 } 2784 CertFreeCertificateContext(linked); 2785 compareStore(store2, "file store -> file store", 2786 serializedStoreWithCertWithFriendlyName, 2787 sizeof(serializedStoreWithCertWithFriendlyName), FALSE); 2788 } 2789 CertCloseStore(store2, 0); 2790 DeleteFileW(filename2); 2791 2792 CertFreeCertificateContext(source); 2793 2794 CertCloseStore(store1, 0); 2795 DeleteFileW(filename1); 2796 2797 /* Test adding a link to a system store (which is a collection store.) */ 2798 store1 = CertOpenSystemStoreA(0, "My"); 2799 source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, 2800 sizeof(bigCert)); 2801 SetLastError(0xdeadbeef); 2802 ret = pCertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS, 2803 &linked); 2804 ok(!ret && GetLastError() == E_INVALIDARG, 2805 "expected E_INVALIDARG, got %08x\n", GetLastError()); 2806 CertFreeCertificateContext(source); 2807 2808 /* Test adding a link to a file store, where the linked certificate is 2809 * in a system store. 2810 */ 2811 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, 2812 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source); 2813 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", 2814 GetLastError()); 2815 if (!GetTempFileNameW(szDot, szPrefix, 0, filename1)) 2816 return; 2817 2818 DeleteFileW(filename1); 2819 file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL, 2820 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 2821 if (file == INVALID_HANDLE_VALUE) 2822 return; 2823 2824 store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 2825 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file); 2826 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 2827 CloseHandle(file); 2828 2829 ret = pCertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS, 2830 &linked); 2831 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError()); 2832 if (ret) 2833 { 2834 ok(linked->hCertStore == store2, "unexpected store\n"); 2835 ret = pCertControlStore(store2, 0, CERT_STORE_CTRL_COMMIT, NULL); 2836 ok(ret, "CertControlStore failed: %d\n", ret); 2837 compareStore(store2, "file store -> system store", 2838 serializedStoreWithCertAndHash, 2839 sizeof(serializedStoreWithCertAndHash), TRUE); 2840 CertFreeCertificateContext(linked); 2841 } 2842 2843 CertCloseStore(store2, 0); 2844 DeleteFileW(filename1); 2845 2846 /* Test adding a link to a registry store, where the linked certificate is 2847 * in a system store. 2848 */ 2849 store2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 2850 CERT_SYSTEM_STORE_CURRENT_USER, WineTestW); 2851 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError()); 2852 ret = pCertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS, 2853 &linked); 2854 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError()); 2855 if (ret) 2856 { 2857 ok(linked->hCertStore == store2, "unexpected store\n"); 2858 CertDeleteCertificateFromStore(linked); 2859 } 2860 CertCloseStore(store2, 0); 2861 2862 CertFreeCertificateContext(source); 2863 CertCloseStore(store1, 0); 2864 2865 delete_test_key(); 2866 } 2867 2868 static DWORD countCertsInStore(HCERTSTORE store) 2869 { 2870 PCCERT_CONTEXT cert = NULL; 2871 DWORD certs = 0; 2872 2873 do { 2874 cert = CertEnumCertificatesInStore(store, cert); 2875 if (cert) 2876 certs++; 2877 } while (cert); 2878 return certs; 2879 } 2880 2881 static DWORD countCRLsInStore(HCERTSTORE store) 2882 { 2883 PCCRL_CONTEXT crl = NULL; 2884 DWORD crls = 0; 2885 2886 do { 2887 crl = pCertEnumCRLsInStore(store, crl); 2888 if (crl) 2889 crls++; 2890 } while (crl); 2891 return crls; 2892 } 2893 2894 static void testEmptyStore(void) 2895 { 2896 const CERT_CONTEXT *cert, *cert2, *cert3; 2897 const CRL_CONTEXT *crl; 2898 const CTL_CONTEXT *ctl; 2899 HCERTSTORE store; 2900 BOOL res; 2901 2902 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert)); 2903 ok(cert != NULL, "CertCreateCertificateContext failed\n"); 2904 ok(cert->hCertStore != NULL, "cert->hCertStore == NULL\n"); 2905 if(!cert->hCertStore) { 2906 CertFreeCertificateContext(cert); 2907 return; 2908 } 2909 2910 test_store_is_empty(cert->hCertStore); 2911 2912 cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2, sizeof(bigCert2)); 2913 ok(cert2 != NULL, "CertCreateCertificateContext failed\n"); 2914 ok(cert2->hCertStore == cert->hCertStore, "Unexpected hCertStore\n"); 2915 2916 test_store_is_empty(cert2->hCertStore); 2917 2918 res = CertAddCertificateContextToStore(cert->hCertStore, cert2, CERT_STORE_ADD_NEW, &cert3); 2919 ok(res, "CertAddCertificateContextToStore failed\n"); 2920 todo_wine 2921 ok(cert3 && cert3 != cert2, "Unexpected cert3\n"); 2922 ok(cert3->hCertStore == cert->hCertStore, "Unexpected hCertStore\n"); 2923 2924 test_store_is_empty(cert->hCertStore); 2925 2926 res = CertDeleteCertificateFromStore(cert3); 2927 ok(res, "CertDeleteCertificateContextFromStore failed\n"); 2928 ok(cert3->hCertStore == cert->hCertStore, "Unexpected hCertStore\n"); 2929 2930 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); 2931 ok(store != NULL, "CertOpenStore failed\n"); 2932 2933 res = CertAddCertificateContextToStore(store, cert2, CERT_STORE_ADD_NEW, &cert3); 2934 ok(res, "CertAddCertificateContextToStore failed\n"); 2935 ok(cert3 && cert3 != cert2, "Unexpected cert3\n"); 2936 ok(cert3->hCertStore == store, "Unexpected hCertStore\n"); 2937 2938 res = CertDeleteCertificateFromStore(cert3); 2939 ok(res, "CertDeleteCertificateContextFromStore failed\n"); 2940 ok(cert3->hCertStore == store, "Unexpected hCertStore\n"); 2941 2942 CertCloseStore(store, 0); 2943 2944 res = CertCloseStore(cert->hCertStore, CERT_CLOSE_STORE_CHECK_FLAG); 2945 ok(!res && GetLastError() == E_UNEXPECTED, "CertCloseStore returned: %x(%x)\n", res, GetLastError()); 2946 2947 res = CertCloseStore(cert->hCertStore, 0); 2948 ok(!res && GetLastError() == E_UNEXPECTED, "CertCloseStore returned: %x(%x)\n", res, GetLastError()); 2949 2950 CertFreeCertificateContext(cert2); 2951 2952 crl = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL, sizeof(signedCRL)); 2953 ok(crl != NULL, "CertCreateCRLContext failed\n"); 2954 ok(crl->hCertStore == cert->hCertStore, "unexpected hCertStore\n"); 2955 2956 CertFreeCRLContext(crl); 2957 2958 ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent)); 2959 ok(ctl != NULL, "CertCreateCTLContext failed\n"); 2960 ok(ctl->hCertStore == cert->hCertStore, "unexpected hCertStore\n"); 2961 2962 CertFreeCTLContext(ctl); 2963 2964 CertFreeCertificateContext(cert); 2965 } 2966 2967 static void testCloseStore(void) 2968 { 2969 const CERT_CONTEXT *cert; 2970 const CRL_CONTEXT *crl; 2971 const CTL_CONTEXT *ctl; 2972 HCERTSTORE store, store2; 2973 BOOL res; 2974 2975 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); 2976 ok(store != NULL, "CertOpenStore failed\n"); 2977 2978 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); 2979 ok(res, "CertCloseStore failed\n"); 2980 2981 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); 2982 ok(store != NULL, "CertOpenStore failed\n"); 2983 2984 store2 = CertDuplicateStore(store); 2985 ok(store2 != NULL, "CertCloneStore failed\n"); 2986 ok(store2 == store, "unexpected store2\n"); 2987 2988 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); 2989 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n"); 2990 2991 res = CertCloseStore(store2, CERT_CLOSE_STORE_CHECK_FLAG); 2992 ok(res, "CertCloseStore failed\n"); 2993 2994 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); 2995 ok(store != NULL, "CertOpenStore failed\n"); 2996 2997 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert, 2998 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert); 2999 ok(res, "CertAddEncodedCertificateToStore failed\n"); 3000 3001 /* There is still a reference from cert */ 3002 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); 3003 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n"); 3004 3005 res = CertFreeCertificateContext(cert); 3006 ok(res, "CertFreeCertificateContext failed\n"); 3007 3008 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); 3009 ok(store != NULL, "CertOpenStore failed\n"); 3010 3011 res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL, 3012 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl); 3013 ok(res, "CertAddEncodedCRLToStore failed\n"); 3014 3015 /* There is still a reference from CRL */ 3016 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); 3017 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n"); 3018 3019 res = CertFreeCRLContext(crl); 3020 ok(res, "CertFreeCRLContext failed\n"); 3021 3022 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); 3023 ok(store != NULL, "CertOpenStore failed\n"); 3024 3025 res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent, 3026 sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl); 3027 ok(res, "CertAddEncodedCTLToStore failed\n"); 3028 3029 /* There is still a reference from CTL */ 3030 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); 3031 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore returned: %x(%u)\n", res, GetLastError()); 3032 3033 res = CertFreeCTLContext(ctl); 3034 ok(res, "CertFreeCTLContext failed\n"); 3035 3036 /* Add all kinds of contexts, then release external references and make sure that store is properly closed. */ 3037 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); 3038 ok(store != NULL, "CertOpenStore failed\n"); 3039 3040 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert, 3041 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert); 3042 ok(res, "CertAddEncodedCertificateToStore failed\n"); 3043 3044 res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL, 3045 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl); 3046 ok(res, "CertAddEncodedCRLToStore failed\n"); 3047 3048 res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent, 3049 sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl); 3050 ok(res, "CertAddEncodedCTLToStore failed\n"); 3051 3052 CertFreeCertificateContext(cert); 3053 CertFreeCRLContext(crl); 3054 CertFreeCTLContext(ctl); 3055 3056 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); 3057 ok(res, "CertCloseStore failed\n"); 3058 } 3059 3060 static void test_I_UpdateStore(void) 3061 { 3062 HMODULE lib = GetModuleHandleA("crypt32"); 3063 BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) = 3064 (void *)GetProcAddress(lib, "I_CertUpdateStore"); 3065 BOOL ret; 3066 HCERTSTORE store1, store2; 3067 PCCERT_CONTEXT cert; 3068 DWORD certs; 3069 3070 if (!pI_CertUpdatestore) 3071 { 3072 win_skip("No I_CertUpdateStore\n"); 3073 return; 3074 } 3075 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 3076 CERT_STORE_CREATE_NEW_FLAG, NULL); 3077 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 3078 CERT_STORE_CREATE_NEW_FLAG, NULL); 3079 3080 /* Crash 3081 ret = pI_CertUpdatestore(NULL, NULL, 0, 0); 3082 ret = pI_CertUpdatestore(store1, NULL, 0, 0); 3083 ret = pI_CertUpdatestore(NULL, store2, 0, 0); 3084 */ 3085 ret = pI_CertUpdatestore(store1, store2, 0, 0); 3086 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError()); 3087 3088 CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert, 3089 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert); 3090 /* I_CertUpdateStore adds the contexts from store2 to store1 */ 3091 ret = pI_CertUpdatestore(store1, store2, 0, 0); 3092 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError()); 3093 certs = countCertsInStore(store1); 3094 ok(certs == 1, "Expected 1 cert, got %d\n", certs); 3095 /* Calling it a second time has no effect */ 3096 ret = pI_CertUpdatestore(store1, store2, 0, 0); 3097 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError()); 3098 certs = countCertsInStore(store1); 3099 ok(certs == 1, "Expected 1 cert, got %d\n", certs); 3100 3101 /* The last parameters to I_CertUpdateStore appear to be ignored */ 3102 ret = pI_CertUpdatestore(store1, store2, 1, 0); 3103 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError()); 3104 ret = pI_CertUpdatestore(store1, store2, 0, 1); 3105 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError()); 3106 3107 CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL, 3108 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL); 3109 3110 /* I_CertUpdateStore also adds the CRLs from store2 to store1 */ 3111 ret = pI_CertUpdatestore(store1, store2, 0, 0); 3112 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError()); 3113 certs = countCertsInStore(store1); 3114 ok(certs == 1, "Expected 1 cert, got %d\n", certs); 3115 if (pCertEnumCRLsInStore) 3116 { 3117 certs = countCRLsInStore(store1); 3118 ok(certs == 1, "Expected 1 CRL, got %d\n", certs); 3119 } 3120 3121 CertDeleteCertificateFromStore(cert); 3122 /* If a context is deleted from store2, I_CertUpdateStore deletes it 3123 * from store1 3124 */ 3125 ret = pI_CertUpdatestore(store1, store2, 0, 0); 3126 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError()); 3127 certs = countCertsInStore(store1); 3128 ok(certs == 0, "Expected 0 certs, got %d\n", certs); 3129 3130 CertCloseStore(store1, 0); 3131 CertCloseStore(store2, 0); 3132 } 3133 3134 START_TEST(store) 3135 { 3136 HMODULE hdll; 3137 3138 hdll = GetModuleHandleA("Crypt32.dll"); 3139 pCertControlStore = (void*)GetProcAddress(hdll, "CertControlStore"); 3140 pCertEnumCRLsInStore = (void*)GetProcAddress(hdll, "CertEnumCRLsInStore"); 3141 pCertEnumSystemStore = (void*)GetProcAddress(hdll, "CertEnumSystemStore"); 3142 pCertGetStoreProperty = (void*)GetProcAddress(hdll, "CertGetStoreProperty"); 3143 pCertRemoveStoreFromCollection = (void*)GetProcAddress(hdll, "CertRemoveStoreFromCollection"); 3144 pCertSetStoreProperty = (void*)GetProcAddress(hdll, "CertSetStoreProperty"); 3145 pCertAddCertificateLinkToStore = (void*)GetProcAddress(hdll, "CertAddCertificateLinkToStore"); 3146 pCertRegisterSystemStore = (void*)GetProcAddress(hdll, "CertRegisterSystemStore"); 3147 pCertUnregisterSystemStore = (void*)GetProcAddress(hdll, "CertUnregisterSystemStore"); 3148 3149 /* various combinations of CertOpenStore */ 3150 testMemStore(); 3151 testCollectionStore(); 3152 testStoresInCollection(); 3153 3154 testRegStore(); 3155 testRegStoreSavedCerts(); 3156 3157 testSystemRegStore(); 3158 testSystemStore(); 3159 testFileStore(); 3160 testFileNameStore(); 3161 testMessageStore(); 3162 testSerializedStore(); 3163 testCloseStore(); 3164 3165 testCertRegisterSystemStore(); 3166 3167 testCertOpenSystemStore(); 3168 testCertEnumSystemStore(); 3169 testStoreProperty(); 3170 3171 testAddSerialized(); 3172 testAddCertificateLink(); 3173 3174 testEmptyStore(); 3175 3176 test_I_UpdateStore(); 3177 } 3178