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