1 /* 2 * Copyright 2004-2007 Juan Lang 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "crypt32_private.h" 20 21 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 22 23 typedef struct _WINE_PROVIDERSTORE 24 { 25 WINECRYPT_CERTSTORE hdr; 26 DWORD dwStoreProvFlags; 27 WINECRYPT_CERTSTORE *memStore; 28 HCERTSTOREPROV hStoreProv; 29 PFN_CERT_STORE_PROV_CLOSE provCloseStore; 30 PFN_CERT_STORE_PROV_WRITE_CERT provWriteCert; 31 PFN_CERT_STORE_PROV_DELETE_CERT provDeleteCert; 32 PFN_CERT_STORE_PROV_WRITE_CRL provWriteCrl; 33 PFN_CERT_STORE_PROV_DELETE_CRL provDeleteCrl; 34 PFN_CERT_STORE_PROV_WRITE_CTL provWriteCtl; 35 PFN_CERT_STORE_PROV_DELETE_CTL provDeleteCtl; 36 PFN_CERT_STORE_PROV_CONTROL provControl; 37 } WINE_PROVIDERSTORE; 38 39 static void ProvStore_addref(WINECRYPT_CERTSTORE *store) 40 { 41 LONG ref = InterlockedIncrement(&store->ref); 42 TRACE("ref = %d\n", ref); 43 } 44 45 static DWORD ProvStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags) 46 { 47 WINE_PROVIDERSTORE *store = (WINE_PROVIDERSTORE*)cert_store; 48 LONG ref; 49 50 if(flags) 51 FIXME("Unimplemented flags %x\n", flags); 52 53 ref = InterlockedDecrement(&store->hdr.ref); 54 TRACE("(%p) ref=%d\n", store, ref); 55 56 if(ref) 57 return ERROR_SUCCESS; 58 59 if (store->provCloseStore) 60 store->provCloseStore(store->hStoreProv, flags); 61 if (!(store->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG)) 62 store->memStore->vtbl->release(store->memStore, flags); 63 CRYPT_FreeStore(&store->hdr); 64 return ERROR_SUCCESS; 65 } 66 67 static void ProvStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context) 68 { 69 /* As long as we don't have contexts properly stored (and hack around hCertStore 70 in add* and enum* functions), this function should never be called. */ 71 assert(0); 72 } 73 74 static BOOL ProvStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert, 75 context_t *toReplace, context_t **ppStoreContext, BOOL use_link) 76 { 77 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 78 BOOL ret; 79 80 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext); 81 82 if (toReplace) 83 ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, toReplace, 84 ppStoreContext, TRUE); 85 else 86 { 87 ret = TRUE; 88 if (ps->provWriteCert) 89 ret = ps->provWriteCert(ps->hStoreProv, context_ptr(cert), CERT_STORE_PROV_WRITE_ADD_FLAG); 90 if (ret) 91 ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, NULL, 92 ppStoreContext, TRUE); 93 } 94 /* dirty trick: replace the returned context's hCertStore with 95 * store. 96 */ 97 if (ret && ppStoreContext) 98 (*(cert_t**)ppStoreContext)->ctx.hCertStore = store; 99 return ret; 100 } 101 102 static context_t *ProvStore_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev) 103 { 104 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 105 cert_t *ret; 106 107 ret = (cert_t*)ps->memStore->vtbl->certs.enumContext(ps->memStore, prev); 108 if (!ret) 109 return NULL; 110 111 /* same dirty trick: replace the returned context's hCertStore with 112 * store. 113 */ 114 ret->ctx.hCertStore = store; 115 return &ret->base; 116 } 117 118 static BOOL ProvStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context) 119 { 120 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 121 BOOL ret = TRUE; 122 123 TRACE("(%p, %p)\n", store, context); 124 125 if (ps->provDeleteCert) 126 ret = ps->provDeleteCert(ps->hStoreProv, context_ptr(context), 0); 127 if (ret) 128 ret = ps->memStore->vtbl->certs.delete(ps->memStore, context); 129 return ret; 130 } 131 132 static BOOL ProvStore_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl, 133 context_t *toReplace, context_t **ppStoreContext, BOOL use_link) 134 { 135 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 136 BOOL ret; 137 138 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext); 139 140 if (toReplace) 141 ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, toReplace, 142 ppStoreContext, TRUE); 143 else 144 { 145 if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG) 146 { 147 SetLastError(ERROR_ACCESS_DENIED); 148 ret = FALSE; 149 } 150 else 151 { 152 ret = TRUE; 153 if (ps->provWriteCrl) 154 ret = ps->provWriteCrl(ps->hStoreProv, context_ptr(crl), 155 CERT_STORE_PROV_WRITE_ADD_FLAG); 156 if (ret) 157 ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, NULL, 158 ppStoreContext, TRUE); 159 } 160 } 161 /* dirty trick: replace the returned context's hCertStore with 162 * store. 163 */ 164 if (ret && ppStoreContext) 165 (*(crl_t**)ppStoreContext)->ctx.hCertStore = store; 166 return ret; 167 } 168 169 static context_t *ProvStore_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev) 170 { 171 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 172 crl_t *ret; 173 174 ret = (crl_t*)ps->memStore->vtbl->crls.enumContext(ps->memStore, prev); 175 if (!ret) 176 return NULL; 177 178 /* same dirty trick: replace the returned context's hCertStore with 179 * store. 180 */ 181 ret->ctx.hCertStore = store; 182 return &ret->base; 183 } 184 185 static BOOL ProvStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *crl) 186 { 187 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 188 BOOL ret = TRUE; 189 190 TRACE("(%p, %p)\n", store, crl); 191 192 if (ps->provDeleteCrl) 193 ret = ps->provDeleteCrl(ps->hStoreProv, context_ptr(crl), 0); 194 if (ret) 195 ret = ps->memStore->vtbl->crls.delete(ps->memStore, crl); 196 return ret; 197 } 198 199 static BOOL ProvStore_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl, 200 context_t *toReplace, context_t **ppStoreContext, BOOL use_link) 201 { 202 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 203 BOOL ret; 204 205 TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext); 206 207 if (toReplace) 208 ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, toReplace, 209 ppStoreContext, TRUE); 210 else 211 { 212 if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG) 213 { 214 SetLastError(ERROR_ACCESS_DENIED); 215 ret = FALSE; 216 } 217 else 218 { 219 ret = TRUE; 220 if (ps->provWriteCtl) 221 ret = ps->provWriteCtl(ps->hStoreProv, context_ptr(ctl), 222 CERT_STORE_PROV_WRITE_ADD_FLAG); 223 if (ret) 224 ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, NULL, 225 ppStoreContext, TRUE); 226 } 227 } 228 /* dirty trick: replace the returned context's hCertStore with 229 * store. 230 */ 231 if (ret && ppStoreContext) 232 (*(ctl_t**)ppStoreContext)->ctx.hCertStore = store; 233 return ret; 234 } 235 236 static context_t *ProvStore_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev) 237 { 238 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 239 ctl_t *ret; 240 241 ret = (ctl_t*)ps->memStore->vtbl->ctls.enumContext(ps->memStore, prev); 242 if (!ret) 243 return NULL; 244 245 /* same dirty trick: replace the returned context's hCertStore with 246 * store. 247 */ 248 ret->ctx.hCertStore = store; 249 return &ret->base; 250 } 251 252 static BOOL ProvStore_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *ctl) 253 { 254 WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store; 255 BOOL ret = TRUE; 256 257 TRACE("(%p, %p)\n", store, ctl); 258 259 if (ps->provDeleteCtl) 260 ret = ps->provDeleteCtl(ps->hStoreProv, context_ptr(ctl), 0); 261 if (ret) 262 ret = ps->memStore->vtbl->ctls.delete(ps->memStore, ctl); 263 return ret; 264 } 265 266 static BOOL ProvStore_control(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags, DWORD dwCtrlType, void const *pvCtrlPara) 267 { 268 WINE_PROVIDERSTORE *store = (WINE_PROVIDERSTORE*)cert_store; 269 BOOL ret = TRUE; 270 271 TRACE("(%p, %08x, %d, %p)\n", store, dwFlags, dwCtrlType, 272 pvCtrlPara); 273 274 if (store->provControl) 275 ret = store->provControl(store->hStoreProv, dwFlags, dwCtrlType, 276 pvCtrlPara); 277 return ret; 278 } 279 280 static const store_vtbl_t ProvStoreVtbl = { 281 ProvStore_addref, 282 ProvStore_release, 283 ProvStore_releaseContext, 284 ProvStore_control, 285 { 286 ProvStore_addCert, 287 ProvStore_enumCert, 288 ProvStore_deleteCert 289 }, { 290 ProvStore_addCRL, 291 ProvStore_enumCRL, 292 ProvStore_deleteCRL 293 }, { 294 ProvStore_addCTL, 295 ProvStore_enumCTL, 296 ProvStore_deleteCTL 297 } 298 }; 299 300 WINECRYPT_CERTSTORE *CRYPT_ProvCreateStore(DWORD dwFlags, 301 WINECRYPT_CERTSTORE *memStore, const CERT_STORE_PROV_INFO *pProvInfo) 302 { 303 WINE_PROVIDERSTORE *ret = CryptMemAlloc(sizeof(WINE_PROVIDERSTORE)); 304 305 if (ret) 306 { 307 CRYPT_InitStore(&ret->hdr, dwFlags, StoreTypeProvider, &ProvStoreVtbl); 308 ret->dwStoreProvFlags = pProvInfo->dwStoreProvFlags; 309 if (ret->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG) 310 { 311 CertCloseStore(memStore, 0); 312 ret->memStore = NULL; 313 } 314 else 315 ret->memStore = memStore; 316 ret->hStoreProv = pProvInfo->hStoreProv; 317 if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC) 318 ret->provCloseStore = 319 pProvInfo->rgpvStoreProvFunc[CERT_STORE_PROV_CLOSE_FUNC]; 320 else 321 ret->provCloseStore = NULL; 322 if (pProvInfo->cStoreProvFunc > 323 CERT_STORE_PROV_WRITE_CERT_FUNC) 324 ret->provWriteCert = pProvInfo->rgpvStoreProvFunc[ 325 CERT_STORE_PROV_WRITE_CERT_FUNC]; 326 else 327 ret->provWriteCert = NULL; 328 if (pProvInfo->cStoreProvFunc > 329 CERT_STORE_PROV_DELETE_CERT_FUNC) 330 ret->provDeleteCert = pProvInfo->rgpvStoreProvFunc[ 331 CERT_STORE_PROV_DELETE_CERT_FUNC]; 332 else 333 ret->provDeleteCert = NULL; 334 if (pProvInfo->cStoreProvFunc > 335 CERT_STORE_PROV_WRITE_CRL_FUNC) 336 ret->provWriteCrl = pProvInfo->rgpvStoreProvFunc[ 337 CERT_STORE_PROV_WRITE_CRL_FUNC]; 338 else 339 ret->provWriteCrl = NULL; 340 if (pProvInfo->cStoreProvFunc > 341 CERT_STORE_PROV_DELETE_CRL_FUNC) 342 ret->provDeleteCrl = pProvInfo->rgpvStoreProvFunc[ 343 CERT_STORE_PROV_DELETE_CRL_FUNC]; 344 else 345 ret->provDeleteCrl = NULL; 346 if (pProvInfo->cStoreProvFunc > 347 CERT_STORE_PROV_WRITE_CTL_FUNC) 348 ret->provWriteCtl = pProvInfo->rgpvStoreProvFunc[ 349 CERT_STORE_PROV_WRITE_CTL_FUNC]; 350 else 351 ret->provWriteCtl = NULL; 352 if (pProvInfo->cStoreProvFunc > 353 CERT_STORE_PROV_DELETE_CTL_FUNC) 354 ret->provDeleteCtl = pProvInfo->rgpvStoreProvFunc[ 355 CERT_STORE_PROV_DELETE_CTL_FUNC]; 356 else 357 ret->provDeleteCtl = NULL; 358 if (pProvInfo->cStoreProvFunc > 359 CERT_STORE_PROV_CONTROL_FUNC) 360 ret->provControl = pProvInfo->rgpvStoreProvFunc[ 361 CERT_STORE_PROV_CONTROL_FUNC]; 362 else 363 ret->provControl = NULL; 364 } 365 return (WINECRYPT_CERTSTORE*)ret; 366 } 367 368 WINECRYPT_CERTSTORE *CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider, 369 DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) 370 { 371 static HCRYPTOIDFUNCSET set = NULL; 372 PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc; 373 HCRYPTOIDFUNCADDR hFunc; 374 WINECRYPT_CERTSTORE *ret = NULL; 375 376 if (!set) 377 set = CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0); 378 CryptGetOIDFunctionAddress(set, dwEncodingType, lpszStoreProvider, 0, 379 (void **)&provOpenFunc, &hFunc); 380 if (provOpenFunc) 381 { 382 CERT_STORE_PROV_INFO provInfo = { 0 }; 383 384 provInfo.cbSize = sizeof(provInfo); 385 if (dwFlags & CERT_STORE_DELETE_FLAG) 386 provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv, 387 dwFlags, pvPara, NULL, &provInfo); 388 else 389 { 390 HCERTSTORE memStore; 391 392 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 393 CERT_STORE_CREATE_NEW_FLAG, NULL); 394 if (memStore) 395 { 396 if (provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv, 397 dwFlags, pvPara, memStore, &provInfo)) 398 ret = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo); 399 else 400 CertCloseStore(memStore, 0); 401 } 402 } 403 CryptFreeOIDFunctionAddress(hFunc, 0); 404 } 405 else 406 SetLastError(ERROR_FILE_NOT_FOUND); 407 return ret; 408 } 409