Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenregstore.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2004-2007 Juan Lang 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 #include <assert.h> 00019 #include <stdarg.h> 00020 #include "windef.h" 00021 #include "winbase.h" 00022 #include "wincrypt.h" 00023 #include "winreg.h" 00024 #include "winuser.h" 00025 #include "wine/debug.h" 00026 #include "wine/list.h" 00027 #include "crypt32_private.h" 00028 00029 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00030 00031 typedef struct _WINE_HASH_TO_DELETE 00032 { 00033 BYTE hash[20]; 00034 struct list entry; 00035 } WINE_HASH_TO_DELETE, *PWINE_HASH_TO_DELETE; 00036 00037 typedef struct _WINE_REGSTOREINFO 00038 { 00039 DWORD dwOpenFlags; 00040 HCERTSTORE memStore; 00041 HKEY key; 00042 BOOL dirty; 00043 CRITICAL_SECTION cs; 00044 struct list certsToDelete; 00045 struct list crlsToDelete; 00046 struct list ctlsToDelete; 00047 } WINE_REGSTOREINFO, *PWINE_REGSTOREINFO; 00048 00049 static void CRYPT_HashToStr(const BYTE *hash, LPWSTR asciiHash) 00050 { 00051 static const WCHAR fmt[] = { '%','0','2','X',0 }; 00052 DWORD i; 00053 00054 assert(hash); 00055 assert(asciiHash); 00056 00057 for (i = 0; i < 20; i++) 00058 wsprintfW(asciiHash + i * 2, fmt, hash[i]); 00059 } 00060 00061 static const WCHAR CertsW[] = { 'C','e','r','t','i','f','i','c','a','t','e','s', 00062 0 }; 00063 static const WCHAR CRLsW[] = { 'C','R','L','s',0 }; 00064 static const WCHAR CTLsW[] = { 'C','T','L','s',0 }; 00065 static const WCHAR BlobW[] = { 'B','l','o','b',0 }; 00066 00067 static void CRYPT_RegReadSerializedFromReg(HKEY key, DWORD contextType, 00068 HCERTSTORE store) 00069 { 00070 LONG rc; 00071 DWORD index = 0; 00072 WCHAR subKeyName[MAX_PATH]; 00073 00074 do { 00075 DWORD size = sizeof(subKeyName) / sizeof(WCHAR); 00076 00077 rc = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL, NULL, 00078 NULL); 00079 if (!rc) 00080 { 00081 HKEY subKey; 00082 00083 rc = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); 00084 if (!rc) 00085 { 00086 LPBYTE buf = NULL; 00087 00088 size = 0; 00089 rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, NULL, &size); 00090 if (!rc) 00091 buf = CryptMemAlloc(size); 00092 if (buf) 00093 { 00094 rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, buf, 00095 &size); 00096 if (!rc) 00097 { 00098 const void *context; 00099 DWORD addedType; 00100 00101 TRACE("Adding cert with hash %s\n", 00102 debugstr_w(subKeyName)); 00103 context = CRYPT_ReadSerializedElement(buf, size, 00104 contextType, &addedType); 00105 if (context) 00106 { 00107 const WINE_CONTEXT_INTERFACE *contextInterface; 00108 BYTE hash[20]; 00109 00110 switch (addedType) 00111 { 00112 case CERT_STORE_CERTIFICATE_CONTEXT: 00113 contextInterface = pCertInterface; 00114 break; 00115 case CERT_STORE_CRL_CONTEXT: 00116 contextInterface = pCRLInterface; 00117 break; 00118 case CERT_STORE_CTL_CONTEXT: 00119 contextInterface = pCTLInterface; 00120 break; 00121 default: 00122 contextInterface = NULL; 00123 } 00124 if (contextInterface) 00125 { 00126 size = sizeof(hash); 00127 if (contextInterface->getProp(context, 00128 CERT_HASH_PROP_ID, hash, &size)) 00129 { 00130 WCHAR asciiHash[20 * 2 + 1]; 00131 00132 CRYPT_HashToStr(hash, asciiHash); 00133 TRACE("comparing %s\n", 00134 debugstr_w(asciiHash)); 00135 TRACE("with %s\n", debugstr_w(subKeyName)); 00136 if (!lstrcmpW(asciiHash, subKeyName)) 00137 { 00138 TRACE("hash matches, adding\n"); 00139 contextInterface->addContextToStore( 00140 store, context, 00141 CERT_STORE_ADD_REPLACE_EXISTING, NULL); 00142 } 00143 else 00144 TRACE("hash doesn't match, ignoring\n"); 00145 } 00146 contextInterface->free(context); 00147 } 00148 } 00149 } 00150 CryptMemFree(buf); 00151 } 00152 RegCloseKey(subKey); 00153 } 00154 /* Ignore intermediate errors, continue enumerating */ 00155 rc = ERROR_SUCCESS; 00156 } 00157 } while (!rc); 00158 } 00159 00160 static void CRYPT_RegReadFromReg(HKEY key, HCERTSTORE store) 00161 { 00162 static const WCHAR * const subKeys[] = { CertsW, CRLsW, CTLsW }; 00163 static const DWORD contextFlags[] = { CERT_STORE_CERTIFICATE_CONTEXT_FLAG, 00164 CERT_STORE_CRL_CONTEXT_FLAG, CERT_STORE_CTL_CONTEXT_FLAG }; 00165 DWORD i; 00166 00167 for (i = 0; i < sizeof(subKeys) / sizeof(subKeys[0]); i++) 00168 { 00169 HKEY hKey; 00170 LONG rc; 00171 00172 rc = RegCreateKeyExW(key, subKeys[i], 0, NULL, 0, KEY_READ, NULL, 00173 &hKey, NULL); 00174 if (!rc) 00175 { 00176 CRYPT_RegReadSerializedFromReg(hKey, contextFlags[i], store); 00177 RegCloseKey(hKey); 00178 } 00179 } 00180 } 00181 00182 /* Hash is assumed to be 20 bytes in length (a SHA-1 hash) */ 00183 static BOOL CRYPT_WriteSerializedToReg(HKEY key, const BYTE *hash, const BYTE *buf, 00184 DWORD len) 00185 { 00186 WCHAR asciiHash[20 * 2 + 1]; 00187 LONG rc; 00188 HKEY subKey; 00189 BOOL ret; 00190 00191 CRYPT_HashToStr(hash, asciiHash); 00192 rc = RegCreateKeyExW(key, asciiHash, 0, NULL, 0, KEY_ALL_ACCESS, NULL, 00193 &subKey, NULL); 00194 if (!rc) 00195 { 00196 rc = RegSetValueExW(subKey, BlobW, 0, REG_BINARY, buf, len); 00197 RegCloseKey(subKey); 00198 } 00199 if (!rc) 00200 ret = TRUE; 00201 else 00202 { 00203 SetLastError(rc); 00204 ret = FALSE; 00205 } 00206 return ret; 00207 } 00208 00209 static BOOL CRYPT_SerializeContextsToReg(HKEY key, 00210 const WINE_CONTEXT_INTERFACE *contextInterface, HCERTSTORE memStore) 00211 { 00212 const void *context = NULL; 00213 BOOL ret; 00214 00215 do { 00216 context = contextInterface->enumContextsInStore(memStore, context); 00217 if (context) 00218 { 00219 BYTE hash[20]; 00220 DWORD hashSize = sizeof(hash); 00221 00222 ret = contextInterface->getProp(context, CERT_HASH_PROP_ID, hash, 00223 &hashSize); 00224 if (ret) 00225 { 00226 DWORD size = 0; 00227 LPBYTE buf = NULL; 00228 00229 ret = contextInterface->serialize(context, 0, NULL, &size); 00230 if (size) 00231 buf = CryptMemAlloc(size); 00232 if (buf) 00233 { 00234 ret = contextInterface->serialize(context, 0, buf, &size); 00235 if (ret) 00236 ret = CRYPT_WriteSerializedToReg(key, hash, buf, size); 00237 } 00238 CryptMemFree(buf); 00239 } 00240 } 00241 else 00242 ret = TRUE; 00243 } while (ret && context != NULL); 00244 if (context) 00245 contextInterface->free(context); 00246 return ret; 00247 } 00248 00249 static BOOL CRYPT_RegWriteToReg(PWINE_REGSTOREINFO store) 00250 { 00251 static const WCHAR * const subKeys[] = { CertsW, CRLsW, CTLsW }; 00252 const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface, 00253 pCRLInterface, pCTLInterface }; 00254 struct list *listToDelete[] = { &store->certsToDelete, &store->crlsToDelete, 00255 &store->ctlsToDelete }; 00256 BOOL ret = TRUE; 00257 DWORD i; 00258 00259 for (i = 0; ret && i < sizeof(subKeys) / sizeof(subKeys[0]); i++) 00260 { 00261 HKEY key; 00262 LONG rc = RegCreateKeyExW(store->key, subKeys[i], 0, NULL, 0, 00263 KEY_ALL_ACCESS, NULL, &key, NULL); 00264 00265 if (!rc) 00266 { 00267 if (listToDelete[i]) 00268 { 00269 PWINE_HASH_TO_DELETE toDelete, next; 00270 WCHAR asciiHash[20 * 2 + 1]; 00271 00272 EnterCriticalSection(&store->cs); 00273 LIST_FOR_EACH_ENTRY_SAFE(toDelete, next, listToDelete[i], 00274 WINE_HASH_TO_DELETE, entry) 00275 { 00276 LONG rc; 00277 00278 CRYPT_HashToStr(toDelete->hash, asciiHash); 00279 TRACE("Removing %s\n", debugstr_w(asciiHash)); 00280 rc = RegDeleteKeyW(key, asciiHash); 00281 if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND) 00282 { 00283 SetLastError(rc); 00284 ret = FALSE; 00285 } 00286 list_remove(&toDelete->entry); 00287 CryptMemFree(toDelete); 00288 } 00289 LeaveCriticalSection(&store->cs); 00290 } 00291 ret = CRYPT_SerializeContextsToReg(key, interfaces[i], 00292 store->memStore); 00293 RegCloseKey(key); 00294 } 00295 else 00296 { 00297 SetLastError(rc); 00298 ret = FALSE; 00299 } 00300 } 00301 return ret; 00302 } 00303 00304 /* If force is true or the registry store is dirty, writes the contents of the 00305 * store to the registry. 00306 */ 00307 static BOOL CRYPT_RegFlushStore(PWINE_REGSTOREINFO store, BOOL force) 00308 { 00309 BOOL ret; 00310 00311 TRACE("(%p, %d)\n", store, force); 00312 00313 if (store->dirty || force) 00314 ret = CRYPT_RegWriteToReg(store); 00315 else 00316 ret = TRUE; 00317 return ret; 00318 } 00319 00320 static void WINAPI CRYPT_RegCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) 00321 { 00322 PWINE_REGSTOREINFO store = hCertStore; 00323 00324 TRACE("(%p, %08x)\n", store, dwFlags); 00325 if (dwFlags) 00326 FIXME("Unimplemented flags: %08x\n", dwFlags); 00327 00328 CRYPT_RegFlushStore(store, FALSE); 00329 RegCloseKey(store->key); 00330 store->cs.DebugInfo->Spare[0] = 0; 00331 DeleteCriticalSection(&store->cs); 00332 CryptMemFree(store); 00333 } 00334 00335 static BOOL CRYPT_RegWriteContext(PWINE_REGSTOREINFO store, 00336 const void *context, DWORD dwFlags) 00337 { 00338 BOOL ret; 00339 00340 if (dwFlags & CERT_STORE_PROV_WRITE_ADD_FLAG) 00341 { 00342 store->dirty = TRUE; 00343 ret = TRUE; 00344 } 00345 else 00346 ret = FALSE; 00347 return ret; 00348 } 00349 00350 static BOOL CRYPT_RegDeleteContext(PWINE_REGSTOREINFO store, 00351 struct list *deleteList, const void *context, 00352 PCWINE_CONTEXT_INTERFACE contextInterface) 00353 { 00354 BOOL ret; 00355 00356 if (store->dwOpenFlags & CERT_STORE_READONLY_FLAG) 00357 { 00358 SetLastError(ERROR_ACCESS_DENIED); 00359 ret = FALSE; 00360 } 00361 else 00362 { 00363 PWINE_HASH_TO_DELETE toDelete = 00364 CryptMemAlloc(sizeof(WINE_HASH_TO_DELETE)); 00365 00366 if (toDelete) 00367 { 00368 DWORD size = sizeof(toDelete->hash); 00369 00370 ret = contextInterface->getProp(context, CERT_HASH_PROP_ID, 00371 toDelete->hash, &size); 00372 if (ret) 00373 { 00374 EnterCriticalSection(&store->cs); 00375 list_add_tail(deleteList, &toDelete->entry); 00376 LeaveCriticalSection(&store->cs); 00377 } 00378 else 00379 { 00380 CryptMemFree(toDelete); 00381 ret = FALSE; 00382 } 00383 } 00384 else 00385 ret = FALSE; 00386 if (ret) 00387 store->dirty = TRUE; 00388 } 00389 return ret; 00390 } 00391 00392 static BOOL WINAPI CRYPT_RegWriteCert(HCERTSTORE hCertStore, 00393 PCCERT_CONTEXT cert, DWORD dwFlags) 00394 { 00395 PWINE_REGSTOREINFO store = hCertStore; 00396 00397 TRACE("(%p, %p, %d)\n", hCertStore, cert, dwFlags); 00398 00399 return CRYPT_RegWriteContext(store, cert, dwFlags); 00400 } 00401 00402 static BOOL WINAPI CRYPT_RegDeleteCert(HCERTSTORE hCertStore, 00403 PCCERT_CONTEXT pCertContext, DWORD dwFlags) 00404 { 00405 PWINE_REGSTOREINFO store = hCertStore; 00406 00407 TRACE("(%p, %p, %08x)\n", store, pCertContext, dwFlags); 00408 00409 return CRYPT_RegDeleteContext(store, &store->certsToDelete, pCertContext, 00410 pCertInterface); 00411 } 00412 00413 static BOOL WINAPI CRYPT_RegWriteCRL(HCERTSTORE hCertStore, 00414 PCCRL_CONTEXT crl, DWORD dwFlags) 00415 { 00416 PWINE_REGSTOREINFO store = hCertStore; 00417 00418 TRACE("(%p, %p, %d)\n", hCertStore, crl, dwFlags); 00419 00420 return CRYPT_RegWriteContext(store, crl, dwFlags); 00421 } 00422 00423 static BOOL WINAPI CRYPT_RegDeleteCRL(HCERTSTORE hCertStore, 00424 PCCRL_CONTEXT pCrlContext, DWORD dwFlags) 00425 { 00426 PWINE_REGSTOREINFO store = hCertStore; 00427 00428 TRACE("(%p, %p, %08x)\n", store, pCrlContext, dwFlags); 00429 00430 return CRYPT_RegDeleteContext(store, &store->crlsToDelete, pCrlContext, 00431 pCRLInterface); 00432 } 00433 00434 static BOOL WINAPI CRYPT_RegWriteCTL(HCERTSTORE hCertStore, 00435 PCCTL_CONTEXT ctl, DWORD dwFlags) 00436 { 00437 PWINE_REGSTOREINFO store = hCertStore; 00438 00439 TRACE("(%p, %p, %d)\n", hCertStore, ctl, dwFlags); 00440 00441 return CRYPT_RegWriteContext(store, ctl, dwFlags); 00442 } 00443 00444 static BOOL WINAPI CRYPT_RegDeleteCTL(HCERTSTORE hCertStore, 00445 PCCTL_CONTEXT pCtlContext, DWORD dwFlags) 00446 { 00447 PWINE_REGSTOREINFO store = hCertStore; 00448 00449 TRACE("(%p, %p, %08x)\n", store, pCtlContext, dwFlags); 00450 00451 return CRYPT_RegDeleteContext(store, &store->ctlsToDelete, pCtlContext, 00452 pCTLInterface); 00453 } 00454 00455 static BOOL WINAPI CRYPT_RegControl(HCERTSTORE hCertStore, DWORD dwFlags, 00456 DWORD dwCtrlType, void const *pvCtrlPara) 00457 { 00458 PWINE_REGSTOREINFO store = hCertStore; 00459 BOOL ret; 00460 00461 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType, 00462 pvCtrlPara); 00463 00464 switch (dwCtrlType) 00465 { 00466 case CERT_STORE_CTRL_RESYNC: 00467 { 00468 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 00469 CERT_STORE_CREATE_NEW_FLAG, NULL); 00470 00471 CRYPT_RegFlushStore(store, FALSE); 00472 CRYPT_RegReadFromReg(store->key, memStore); 00473 I_CertUpdateStore(store->memStore, memStore, 0, 0); 00474 CertCloseStore(memStore, 0); 00475 ret = TRUE; 00476 break; 00477 } 00478 case CERT_STORE_CTRL_COMMIT: 00479 ret = CRYPT_RegFlushStore(store, 00480 dwFlags & CERT_STORE_CTRL_COMMIT_FORCE_FLAG); 00481 break; 00482 case CERT_STORE_CTRL_AUTO_RESYNC: 00483 FIXME("CERT_STORE_CTRL_AUTO_RESYNC: stub\n"); 00484 ret = TRUE; 00485 break; 00486 default: 00487 FIXME("%d: stub\n", dwCtrlType); 00488 ret = FALSE; 00489 } 00490 return ret; 00491 } 00492 00493 static void *regProvFuncs[] = { 00494 CRYPT_RegCloseStore, 00495 NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */ 00496 CRYPT_RegWriteCert, 00497 CRYPT_RegDeleteCert, 00498 NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */ 00499 NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */ 00500 CRYPT_RegWriteCRL, 00501 CRYPT_RegDeleteCRL, 00502 NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */ 00503 NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */ 00504 CRYPT_RegWriteCTL, 00505 CRYPT_RegDeleteCTL, 00506 NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */ 00507 CRYPT_RegControl, 00508 }; 00509 00510 PWINECRYPT_CERTSTORE CRYPT_RegOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags, 00511 const void *pvPara) 00512 { 00513 PWINECRYPT_CERTSTORE store = NULL; 00514 00515 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara); 00516 00517 if (dwFlags & CERT_STORE_DELETE_FLAG) 00518 { 00519 DWORD rc = RegDeleteTreeW((HKEY)pvPara, CertsW); 00520 00521 if (rc == ERROR_SUCCESS || rc == ERROR_NO_MORE_ITEMS) 00522 rc = RegDeleteTreeW((HKEY)pvPara, CRLsW); 00523 if (rc == ERROR_SUCCESS || rc == ERROR_NO_MORE_ITEMS) 00524 rc = RegDeleteTreeW((HKEY)pvPara, CTLsW); 00525 if (rc == ERROR_NO_MORE_ITEMS) 00526 rc = ERROR_SUCCESS; 00527 SetLastError(rc); 00528 } 00529 else 00530 { 00531 HKEY key; 00532 00533 if (DuplicateHandle(GetCurrentProcess(), (HANDLE)pvPara, 00534 GetCurrentProcess(), (LPHANDLE)&key, 00535 dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ : KEY_ALL_ACCESS, 00536 TRUE, 0)) 00537 { 00538 PWINECRYPT_CERTSTORE memStore; 00539 00540 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, hCryptProv, 00541 CERT_STORE_CREATE_NEW_FLAG, NULL); 00542 if (memStore) 00543 { 00544 PWINE_REGSTOREINFO regInfo = CryptMemAlloc( 00545 sizeof(WINE_REGSTOREINFO)); 00546 00547 if (regInfo) 00548 { 00549 CERT_STORE_PROV_INFO provInfo = { 0 }; 00550 00551 regInfo->dwOpenFlags = dwFlags; 00552 regInfo->memStore = memStore; 00553 regInfo->key = key; 00554 InitializeCriticalSection(®Info->cs); 00555 regInfo->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PWINE_REGSTOREINFO->cs"); 00556 list_init(®Info->certsToDelete); 00557 list_init(®Info->crlsToDelete); 00558 list_init(®Info->ctlsToDelete); 00559 CRYPT_RegReadFromReg(regInfo->key, regInfo->memStore); 00560 regInfo->dirty = FALSE; 00561 provInfo.cbSize = sizeof(provInfo); 00562 provInfo.cStoreProvFunc = sizeof(regProvFuncs) / 00563 sizeof(regProvFuncs[0]); 00564 provInfo.rgpvStoreProvFunc = regProvFuncs; 00565 provInfo.hStoreProv = regInfo; 00566 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo); 00567 /* Reg store doesn't need crypto provider, so close it */ 00568 if (hCryptProv && 00569 !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) 00570 CryptReleaseContext(hCryptProv, 0); 00571 } 00572 } 00573 } 00574 } 00575 TRACE("returning %p\n", store); 00576 return store; 00577 } Generated on Sun May 27 2012 04:23:18 for ReactOS by
1.7.6.1
|