provstore.c 12.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright 2004-2007 Juan Lang
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */
18

19
#include <stdarg.h>
20 21
#include <assert.h>

22 23 24 25 26 27 28 29 30 31 32 33
#include "windef.h"
#include "winbase.h"
#include "wincrypt.h"
#include "wine/debug.h"
#include "crypt32_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(crypt);

typedef struct _WINE_PROVIDERSTORE
{
    WINECRYPT_CERTSTORE             hdr;
    DWORD                           dwStoreProvFlags;
34
    WINECRYPT_CERTSTORE            *memStore;
35 36 37 38 39 40
    HCERTSTOREPROV                  hStoreProv;
    PFN_CERT_STORE_PROV_CLOSE       provCloseStore;
    PFN_CERT_STORE_PROV_WRITE_CERT  provWriteCert;
    PFN_CERT_STORE_PROV_DELETE_CERT provDeleteCert;
    PFN_CERT_STORE_PROV_WRITE_CRL   provWriteCrl;
    PFN_CERT_STORE_PROV_DELETE_CRL  provDeleteCrl;
41 42
    PFN_CERT_STORE_PROV_WRITE_CTL   provWriteCtl;
    PFN_CERT_STORE_PROV_DELETE_CTL  provDeleteCtl;
43
    PFN_CERT_STORE_PROV_CONTROL     provControl;
44
} WINE_PROVIDERSTORE;
45

46 47 48 49 50 51
static void ProvStore_addref(WINECRYPT_CERTSTORE *store)
{
    LONG ref = InterlockedIncrement(&store->ref);
    TRACE("ref = %d\n", ref);
}

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 58 59 60 61 62 63 64
    if(flags)
        FIXME("Unimplemented flags %x\n", flags);

    ref = InterlockedDecrement(&store->hdr.ref);
    TRACE("(%p) ref=%d\n", store, ref);

    if(ref)
        return ERROR_SUCCESS;
65 66

    if (store->provCloseStore)
67
        store->provCloseStore(store->hStoreProv, flags);
68
    if (!(store->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG))
69 70 71
        store->memStore->vtbl->release(store->memStore, flags);
    CRYPT_FreeStore(&store->hdr);
    return ERROR_SUCCESS;
72 73
}

74 75 76 77 78 79 80
static void ProvStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
{
    /* As long as we don't have contexts properly stored (and hack around hCertStore
       in add* and enum* functions), this function should never be called. */
    assert(0);
}

81 82
static BOOL ProvStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert,
 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
83
{
84
    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
85 86 87 88 89
    BOOL ret;

    TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);

    if (toReplace)
90
        ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, toReplace,
91
         ppStoreContext, TRUE);
92 93 94 95
    else
    {
        ret = TRUE;
        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 102 103
    }
    /* dirty trick: replace the returned context's hCertStore with
     * store.
     */
104
    if (ret && ppStoreContext)
105
        (*(cert_t**)ppStoreContext)->ctx.hCertStore = store;
106 107 108
    return ret;
}

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 115 116 117 118 119 120 121 122
    ret = (cert_t*)ps->memStore->vtbl->certs.enumContext(ps->memStore, prev);
    if (!ret)
        return NULL;

    /* same dirty trick: replace the returned context's hCertStore with
     * store.
     */
    ret->ctx.hCertStore = store;
    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 129
    BOOL ret = TRUE;

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 137 138
    return ret;
}

139 140
static BOOL ProvStore_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl,
 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
141
{
142
    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
143 144 145 146 147
    BOOL ret;

    TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);

    if (toReplace)
148
        ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, toReplace,
149
         ppStoreContext, TRUE);
150 151 152 153 154 155 156 157 158 159 160
    else
    {
        if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
        {
            SetLastError(ERROR_ACCESS_DENIED);
            ret = FALSE;
        }
        else
        {
            ret = TRUE;
            if (ps->provWriteCrl)
161
                ret = ps->provWriteCrl(ps->hStoreProv, context_ptr(crl),
162 163
                 CERT_STORE_PROV_WRITE_ADD_FLAG);
            if (ret)
164
                ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, NULL,
165
                 ppStoreContext, TRUE);
166 167 168 169 170
        }
    }
    /* dirty trick: replace the returned context's hCertStore with
     * store.
     */
171
    if (ret && ppStoreContext)
172
        (*(crl_t**)ppStoreContext)->ctx.hCertStore = store;
173 174 175
    return ret;
}

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 182 183 184 185 186 187 188 189
    ret = (crl_t*)ps->memStore->vtbl->crls.enumContext(ps->memStore, prev);
    if (!ret)
        return NULL;

    /* same dirty trick: replace the returned context's hCertStore with
     * store.
     */
    ret->ctx.hCertStore = store;
    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 196 197 198 199
    BOOL ret = TRUE;

    TRACE("(%p, %p)\n", store, crl);

    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 204 205
    return ret;
}

206 207
static BOOL ProvStore_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl,
 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
208
{
209
    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
210 211 212 213 214
    BOOL ret;

    TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);

    if (toReplace)
215
        ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, toReplace,
216
         ppStoreContext, TRUE);
217 218 219 220 221 222 223 224 225 226 227
    else
    {
        if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
        {
            SetLastError(ERROR_ACCESS_DENIED);
            ret = FALSE;
        }
        else
        {
            ret = TRUE;
            if (ps->provWriteCtl)
228
                ret = ps->provWriteCtl(ps->hStoreProv, context_ptr(ctl),
229 230
                 CERT_STORE_PROV_WRITE_ADD_FLAG);
            if (ret)
231
                ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, NULL,
232
                 ppStoreContext, TRUE);
233 234 235 236 237
        }
    }
    /* dirty trick: replace the returned context's hCertStore with
     * store.
     */
238
    if (ret && ppStoreContext)
239
        (*(ctl_t**)ppStoreContext)->ctx.hCertStore = store;
240 241 242
    return ret;
}

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 249 250 251 252 253 254 255 256
    ret = (ctl_t*)ps->memStore->vtbl->ctls.enumContext(ps->memStore, prev);
    if (!ret)
        return NULL;

    /* same dirty trick: replace the returned context's hCertStore with
     * store.
     */
    ret->ctx.hCertStore = store;
    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 263 264 265 266
    BOOL ret = TRUE;

    TRACE("(%p, %p)\n", store, ctl);

    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 271 272
    return ret;
}

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 277
    BOOL ret = TRUE;

278
    TRACE("(%p, %08x, %d, %p)\n", store, dwFlags, dwCtrlType,
279 280 281 282 283 284 285 286
     pvCtrlPara);

    if (store->provControl)
        ret = store->provControl(store->hStoreProv, dwFlags, dwCtrlType,
         pvCtrlPara);
    return ret;
}

287
static const store_vtbl_t ProvStoreVtbl = {
288
    ProvStore_addref,
289
    ProvStore_release,
290
    ProvStore_releaseContext,
291 292 293 294 295 296 297 298 299 300 301 302 303 304
    ProvStore_control,
    {
        ProvStore_addCert,
        ProvStore_enumCert,
        ProvStore_deleteCert
    }, {
        ProvStore_addCRL,
        ProvStore_enumCRL,
        ProvStore_deleteCRL
    }, {
        ProvStore_addCTL,
        ProvStore_enumCTL,
        ProvStore_deleteCTL
    }
305 306
};

307 308
WINECRYPT_CERTSTORE *CRYPT_ProvCreateStore(DWORD dwFlags,
 WINECRYPT_CERTSTORE *memStore, const CERT_STORE_PROV_INFO *pProvInfo)
309
{
310
    WINE_PROVIDERSTORE *ret = CryptMemAlloc(sizeof(WINE_PROVIDERSTORE));
311 312 313

    if (ret)
    {
314
        CRYPT_InitStore(&ret->hdr, dwFlags, StoreTypeProvider, &ProvStoreVtbl);
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
        ret->dwStoreProvFlags = pProvInfo->dwStoreProvFlags;
        if (ret->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG)
        {
            CertCloseStore(memStore, 0);
            ret->memStore = NULL;
        }
        else
            ret->memStore = memStore;
        ret->hStoreProv = pProvInfo->hStoreProv;
        if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
            ret->provCloseStore =
             pProvInfo->rgpvStoreProvFunc[CERT_STORE_PROV_CLOSE_FUNC];
        else
            ret->provCloseStore = NULL;
        if (pProvInfo->cStoreProvFunc >
         CERT_STORE_PROV_WRITE_CERT_FUNC)
            ret->provWriteCert = pProvInfo->rgpvStoreProvFunc[
             CERT_STORE_PROV_WRITE_CERT_FUNC];
        else
            ret->provWriteCert = NULL;
        if (pProvInfo->cStoreProvFunc >
         CERT_STORE_PROV_DELETE_CERT_FUNC)
            ret->provDeleteCert = pProvInfo->rgpvStoreProvFunc[
             CERT_STORE_PROV_DELETE_CERT_FUNC];
        else
            ret->provDeleteCert = NULL;
        if (pProvInfo->cStoreProvFunc >
         CERT_STORE_PROV_WRITE_CRL_FUNC)
            ret->provWriteCrl = pProvInfo->rgpvStoreProvFunc[
             CERT_STORE_PROV_WRITE_CRL_FUNC];
        else
Juan Lang's avatar
Juan Lang committed
346
            ret->provWriteCrl = NULL;
347 348 349 350 351
        if (pProvInfo->cStoreProvFunc >
         CERT_STORE_PROV_DELETE_CRL_FUNC)
            ret->provDeleteCrl = pProvInfo->rgpvStoreProvFunc[
             CERT_STORE_PROV_DELETE_CRL_FUNC];
        else
Juan Lang's avatar
Juan Lang committed
352
            ret->provDeleteCrl = NULL;
353 354 355 356 357 358 359 360 361 362 363 364
        if (pProvInfo->cStoreProvFunc >
         CERT_STORE_PROV_WRITE_CTL_FUNC)
            ret->provWriteCtl = pProvInfo->rgpvStoreProvFunc[
             CERT_STORE_PROV_WRITE_CTL_FUNC];
        else
            ret->provWriteCtl = NULL;
        if (pProvInfo->cStoreProvFunc >
         CERT_STORE_PROV_DELETE_CTL_FUNC)
            ret->provDeleteCtl = pProvInfo->rgpvStoreProvFunc[
             CERT_STORE_PROV_DELETE_CTL_FUNC];
        else
            ret->provDeleteCtl = NULL;
365 366 367 368 369 370 371
        if (pProvInfo->cStoreProvFunc >
         CERT_STORE_PROV_CONTROL_FUNC)
            ret->provControl = pProvInfo->rgpvStoreProvFunc[
             CERT_STORE_PROV_CONTROL_FUNC];
        else
            ret->provControl = NULL;
    }
372
    return (WINECRYPT_CERTSTORE*)ret;
373 374
}

375
WINECRYPT_CERTSTORE *CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
376 377 378 379 380
 DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara)
{
    static HCRYPTOIDFUNCSET set = NULL;
    PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc;
    HCRYPTOIDFUNCADDR hFunc;
381
    WINECRYPT_CERTSTORE *ret = NULL;
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404

    if (!set)
        set = CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0);
    CryptGetOIDFunctionAddress(set, dwEncodingType, lpszStoreProvider, 0,
     (void **)&provOpenFunc, &hFunc);
    if (provOpenFunc)
    {
        CERT_STORE_PROV_INFO provInfo = { 0 };

        provInfo.cbSize = sizeof(provInfo);
        if (dwFlags & CERT_STORE_DELETE_FLAG)
            provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
             dwFlags, pvPara, NULL, &provInfo);
        else
        {
            HCERTSTORE memStore;

            memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
             CERT_STORE_CREATE_NEW_FLAG, NULL);
            if (memStore)
            {
                if (provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
                 dwFlags, pvPara, memStore, &provInfo))
405
                    ret = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
406 407 408 409 410 411 412 413 414 415
                else
                    CertCloseStore(memStore, 0);
            }
        }
        CryptFreeOIDFunctionAddress(hFunc, 0);
    }
    else
        SetLastError(ERROR_FILE_NOT_FOUND);
    return ret;
}