ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

regstore.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(&regInfo->cs);
00555                     regInfo->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PWINE_REGSTOREINFO->cs");
00556                     list_init(&regInfo->certsToDelete);
00557                     list_init(&regInfo->crlsToDelete);
00558                     list_init(&regInfo->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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.