1 /*
2 * Copyright 2008 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
20 #include <assert.h>
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wincrypt.h"
26 #include "wine/debug.h"
27 #include "crypt32_private.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
30
CTL_free(context_t * context)31 static void CTL_free(context_t *context)
32 {
33 ctl_t *ctl = (ctl_t*)context;
34
35 CryptMsgClose(ctl->ctx.hCryptMsg);
36 CryptMemFree(ctl->ctx.pbCtlEncoded);
37 CryptMemFree(ctl->ctx.pbCtlContext);
38 LocalFree(ctl->ctx.pCtlInfo);
39 }
40
CTL_clone(context_t * context,WINECRYPT_CERTSTORE * store,BOOL use_link)41 static context_t *CTL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
42 {
43 ctl_t *ctl;
44
45 if(!use_link) {
46 FIXME("Only links supported\n");
47 return NULL;
48 }
49
50 ctl = (ctl_t*)Context_CreateLinkContext(sizeof(CTL_CONTEXT), context, store);
51 if(!ctl)
52 return NULL;
53
54 ctl->ctx.hCertStore = store;
55 return &ctl->base;
56 }
57
58 static const context_vtbl_t ctl_vtbl = {
59 CTL_free,
60 CTL_clone
61 };
62
CertAddCTLContextToStore(HCERTSTORE hCertStore,PCCTL_CONTEXT pCtlContext,DWORD dwAddDisposition,PCCTL_CONTEXT * ppStoreContext)63 BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
64 PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
65 PCCTL_CONTEXT* ppStoreContext)
66 {
67 WINECRYPT_CERTSTORE *store = hCertStore;
68 BOOL ret = TRUE;
69 PCCTL_CONTEXT toAdd = NULL, existing = NULL;
70
71 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCtlContext, dwAddDisposition,
72 ppStoreContext);
73
74 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
75 {
76 existing = CertFindCTLInStore(hCertStore, 0, 0, CTL_FIND_EXISTING,
77 pCtlContext, NULL);
78 }
79
80 switch (dwAddDisposition)
81 {
82 case CERT_STORE_ADD_ALWAYS:
83 toAdd = CertDuplicateCTLContext(pCtlContext);
84 break;
85 case CERT_STORE_ADD_NEW:
86 if (existing)
87 {
88 TRACE("found matching CTL, not adding\n");
89 SetLastError(CRYPT_E_EXISTS);
90 ret = FALSE;
91 }
92 else
93 toAdd = CertDuplicateCTLContext(pCtlContext);
94 break;
95 case CERT_STORE_ADD_NEWER:
96 if (existing)
97 {
98 LONG newer = CompareFileTime(&existing->pCtlInfo->ThisUpdate,
99 &pCtlContext->pCtlInfo->ThisUpdate);
100
101 if (newer < 0)
102 toAdd = CertDuplicateCTLContext(pCtlContext);
103 else
104 {
105 TRACE("existing CTL is newer, not adding\n");
106 SetLastError(CRYPT_E_EXISTS);
107 ret = FALSE;
108 }
109 }
110 else
111 toAdd = CertDuplicateCTLContext(pCtlContext);
112 break;
113 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
114 if (existing)
115 {
116 LONG newer = CompareFileTime(&existing->pCtlInfo->ThisUpdate,
117 &pCtlContext->pCtlInfo->ThisUpdate);
118
119 if (newer < 0)
120 {
121 toAdd = CertDuplicateCTLContext(pCtlContext);
122 Context_CopyProperties(existing, pCtlContext);
123 }
124 else
125 {
126 TRACE("existing CTL is newer, not adding\n");
127 SetLastError(CRYPT_E_EXISTS);
128 ret = FALSE;
129 }
130 }
131 else
132 toAdd = CertDuplicateCTLContext(pCtlContext);
133 break;
134 case CERT_STORE_ADD_REPLACE_EXISTING:
135 toAdd = CertDuplicateCTLContext(pCtlContext);
136 break;
137 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
138 toAdd = CertDuplicateCTLContext(pCtlContext);
139 if (existing)
140 Context_CopyProperties(toAdd, existing);
141 break;
142 case CERT_STORE_ADD_USE_EXISTING:
143 if (existing)
144 {
145 Context_CopyProperties(existing, pCtlContext);
146 if (ppStoreContext)
147 *ppStoreContext = CertDuplicateCTLContext(existing);
148 }
149 else
150 toAdd = CertDuplicateCTLContext(pCtlContext);
151 break;
152 default:
153 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
154 ret = FALSE;
155 }
156
157 if (toAdd)
158 {
159 if (store) {
160 context_t *ret_ctx;
161
162 ret = store->vtbl->ctls.addContext(store, context_from_ptr(toAdd),
163 existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_ctx : NULL, TRUE);
164 if(ret && ppStoreContext)
165 *ppStoreContext = context_ptr(ret_ctx);
166 }else if (ppStoreContext) {
167 *ppStoreContext = CertDuplicateCTLContext(toAdd);
168 }
169 CertFreeCTLContext(toAdd);
170 }
171 CertFreeCTLContext(existing);
172
173 TRACE("returning %d\n", ret);
174 return ret;
175 }
176
CertAddEncodedCTLToStore(HCERTSTORE hCertStore,DWORD dwMsgAndCertEncodingType,const BYTE * pbCtlEncoded,DWORD cbCtlEncoded,DWORD dwAddDisposition,PCCTL_CONTEXT * ppCtlContext)177 BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
178 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
179 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
180 {
181 PCCTL_CONTEXT ctl = CertCreateCTLContext(dwMsgAndCertEncodingType,
182 pbCtlEncoded, cbCtlEncoded);
183 BOOL ret;
184
185 TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore,
186 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
187 ppCtlContext);
188
189 if (ctl)
190 {
191 ret = CertAddCTLContextToStore(hCertStore, ctl, dwAddDisposition,
192 ppCtlContext);
193 CertFreeCTLContext(ctl);
194 }
195 else
196 ret = FALSE;
197 return ret;
198 }
199
CertEnumCTLsInStore(HCERTSTORE hCertStore,PCCTL_CONTEXT pPrev)200 PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore, PCCTL_CONTEXT pPrev)
201 {
202 ctl_t *prev = pPrev ? ctl_from_ptr(pPrev) : NULL, *ret;
203 WINECRYPT_CERTSTORE *hcs = hCertStore;
204
205 TRACE("(%p, %p)\n", hCertStore, pPrev);
206 if (!hCertStore)
207 ret = NULL;
208 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
209 ret = NULL;
210 else
211 ret = (ctl_t*)hcs->vtbl->ctls.enumContext(hcs, prev ? &prev->base : NULL);
212 return ret ? &ret->ctx : NULL;
213 }
214
215 typedef BOOL (*CtlCompareFunc)(PCCTL_CONTEXT pCtlContext, DWORD dwType,
216 DWORD dwFlags, const void *pvPara);
217
compare_ctl_any(PCCTL_CONTEXT pCtlContext,DWORD dwType,DWORD dwFlags,const void * pvPara)218 static BOOL compare_ctl_any(PCCTL_CONTEXT pCtlContext, DWORD dwType,
219 DWORD dwFlags, const void *pvPara)
220 {
221 return TRUE;
222 }
223
compare_ctl_by_md5_hash(PCCTL_CONTEXT pCtlContext,DWORD dwType,DWORD dwFlags,const void * pvPara)224 static BOOL compare_ctl_by_md5_hash(PCCTL_CONTEXT pCtlContext, DWORD dwType,
225 DWORD dwFlags, const void *pvPara)
226 {
227 BOOL ret;
228 BYTE hash[16];
229 DWORD size = sizeof(hash);
230
231 ret = CertGetCTLContextProperty(pCtlContext, CERT_MD5_HASH_PROP_ID, hash,
232 &size);
233 if (ret)
234 {
235 const CRYPT_HASH_BLOB *pHash = pvPara;
236
237 if (size == pHash->cbData)
238 ret = !memcmp(pHash->pbData, hash, size);
239 else
240 ret = FALSE;
241 }
242 return ret;
243 }
244
compare_ctl_by_sha1_hash(PCCTL_CONTEXT pCtlContext,DWORD dwType,DWORD dwFlags,const void * pvPara)245 static BOOL compare_ctl_by_sha1_hash(PCCTL_CONTEXT pCtlContext, DWORD dwType,
246 DWORD dwFlags, const void *pvPara)
247 {
248 BOOL ret;
249 BYTE hash[20];
250 DWORD size = sizeof(hash);
251
252 ret = CertGetCTLContextProperty(pCtlContext, CERT_SHA1_HASH_PROP_ID, hash,
253 &size);
254 if (ret)
255 {
256 const CRYPT_HASH_BLOB *pHash = pvPara;
257
258 if (size == pHash->cbData)
259 ret = !memcmp(pHash->pbData, hash, size);
260 else
261 ret = FALSE;
262 }
263 return ret;
264 }
265
compare_ctl_existing(PCCTL_CONTEXT pCtlContext,DWORD dwType,DWORD dwFlags,const void * pvPara)266 static BOOL compare_ctl_existing(PCCTL_CONTEXT pCtlContext, DWORD dwType,
267 DWORD dwFlags, const void *pvPara)
268 {
269 BOOL ret;
270
271 if (pvPara)
272 {
273 PCCTL_CONTEXT ctl = pvPara;
274
275 if (pCtlContext->cbCtlContext == ctl->cbCtlContext)
276 {
277 if (ctl->cbCtlContext)
278 ret = !memcmp(pCtlContext->pbCtlContext, ctl->pbCtlContext,
279 ctl->cbCtlContext);
280 else
281 ret = TRUE;
282 }
283 else
284 ret = FALSE;
285 }
286 else
287 ret = FALSE;
288 return ret;
289 }
290
CertFindCTLInStore(HCERTSTORE hCertStore,DWORD dwCertEncodingType,DWORD dwFindFlags,DWORD dwFindType,const void * pvFindPara,PCCTL_CONTEXT pPrevCtlContext)291 PCCTL_CONTEXT WINAPI CertFindCTLInStore(HCERTSTORE hCertStore,
292 DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType,
293 const void *pvFindPara, PCCTL_CONTEXT pPrevCtlContext)
294 {
295 PCCTL_CONTEXT ret;
296 CtlCompareFunc compare;
297
298 TRACE("(%p, %d, %d, %d, %p, %p)\n", hCertStore, dwCertEncodingType,
299 dwFindFlags, dwFindType, pvFindPara, pPrevCtlContext);
300
301 switch (dwFindType)
302 {
303 case CTL_FIND_ANY:
304 compare = compare_ctl_any;
305 break;
306 case CTL_FIND_SHA1_HASH:
307 compare = compare_ctl_by_sha1_hash;
308 break;
309 case CTL_FIND_MD5_HASH:
310 compare = compare_ctl_by_md5_hash;
311 break;
312 case CTL_FIND_EXISTING:
313 compare = compare_ctl_existing;
314 break;
315 default:
316 FIXME("find type %08x unimplemented\n", dwFindType);
317 compare = NULL;
318 }
319
320 if (compare)
321 {
322 BOOL matches = FALSE;
323
324 ret = pPrevCtlContext;
325 do {
326 ret = CertEnumCTLsInStore(hCertStore, ret);
327 if (ret)
328 matches = compare(ret, dwFindType, dwFindFlags, pvFindPara);
329 } while (ret != NULL && !matches);
330 if (!ret)
331 SetLastError(CRYPT_E_NOT_FOUND);
332 }
333 else
334 {
335 SetLastError(CRYPT_E_NOT_FOUND);
336 ret = NULL;
337 }
338 return ret;
339 }
340
CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)341 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
342 {
343 WINECRYPT_CERTSTORE *hcs;
344 ctl_t *ctl = ctl_from_ptr(pCtlContext);
345 BOOL ret;
346
347 TRACE("(%p)\n", pCtlContext);
348
349 if (!pCtlContext)
350 return TRUE;
351
352 hcs = pCtlContext->hCertStore;
353
354 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
355 return FALSE;
356
357 ret = hcs->vtbl->ctls.delete(hcs, &ctl->base);
358 if (ret)
359 ret = CertFreeCTLContext(pCtlContext);
360 return ret;
361 }
362
CertCreateCTLContext(DWORD dwMsgAndCertEncodingType,const BYTE * pbCtlEncoded,DWORD cbCtlEncoded)363 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType,
364 const BYTE *pbCtlEncoded, DWORD cbCtlEncoded)
365 {
366 ctl_t *ctl = NULL;
367 HCRYPTMSG msg;
368 BOOL ret;
369 BYTE *content = NULL;
370 DWORD contentSize = 0, size;
371 PCTL_INFO ctlInfo = NULL;
372
373 TRACE("(%08x, %p, %d)\n", dwMsgAndCertEncodingType, pbCtlEncoded,
374 cbCtlEncoded);
375
376 if (GET_CERT_ENCODING_TYPE(dwMsgAndCertEncodingType) != X509_ASN_ENCODING)
377 {
378 SetLastError(E_INVALIDARG);
379 return NULL;
380 }
381 if (!pbCtlEncoded || !cbCtlEncoded)
382 {
383 SetLastError(ERROR_INVALID_DATA);
384 return NULL;
385 }
386 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0,
387 0, NULL, NULL);
388 if (!msg)
389 return NULL;
390 ret = CryptMsgUpdate(msg, pbCtlEncoded, cbCtlEncoded, TRUE);
391 if (!ret)
392 {
393 SetLastError(ERROR_INVALID_DATA);
394 goto end;
395 }
396 /* Check that it's really a CTL */
397 ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL, &size);
398 if (ret)
399 {
400 char *innerContent = CryptMemAlloc(size);
401
402 if (innerContent)
403 {
404 ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0,
405 innerContent, &size);
406 if (ret)
407 {
408 if (strcmp(innerContent, szOID_CTL))
409 {
410 SetLastError(ERROR_INVALID_DATA);
411 ret = FALSE;
412 }
413 }
414 CryptMemFree(innerContent);
415 }
416 else
417 {
418 SetLastError(ERROR_OUTOFMEMORY);
419 ret = FALSE;
420 }
421 }
422 if (!ret)
423 goto end;
424 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &contentSize);
425 if (!ret)
426 goto end;
427 content = CryptMemAlloc(contentSize);
428 if (content)
429 {
430 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, content,
431 &contentSize);
432 if (ret)
433 {
434 ret = CryptDecodeObjectEx(dwMsgAndCertEncodingType, PKCS_CTL,
435 content, contentSize, CRYPT_DECODE_ALLOC_FLAG, NULL,
436 &ctlInfo, &size);
437 if (ret)
438 {
439 ctl = (ctl_t*)Context_CreateDataContext(sizeof(CTL_CONTEXT), &ctl_vtbl, &empty_store);
440 if (ctl)
441 {
442 BYTE *data = CryptMemAlloc(cbCtlEncoded);
443
444 if (data)
445 {
446 memcpy(data, pbCtlEncoded, cbCtlEncoded);
447 ctl->ctx.dwMsgAndCertEncodingType =
448 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
449 ctl->ctx.pbCtlEncoded = data;
450 ctl->ctx.cbCtlEncoded = cbCtlEncoded;
451 ctl->ctx.pCtlInfo = ctlInfo;
452 ctl->ctx.hCertStore = &empty_store;
453 ctl->ctx.hCryptMsg = msg;
454 ctl->ctx.pbCtlContext = content;
455 ctl->ctx.cbCtlContext = contentSize;
456 }
457 else
458 {
459 SetLastError(ERROR_OUTOFMEMORY);
460 ret = FALSE;
461 }
462 }
463 else
464 {
465 SetLastError(ERROR_OUTOFMEMORY);
466 ret = FALSE;
467 }
468 }
469 }
470 }
471 else
472 {
473 SetLastError(ERROR_OUTOFMEMORY);
474 ret = FALSE;
475 }
476
477 end:
478 if (!ret)
479 {
480 if(ctl)
481 Context_Release(&ctl->base);
482 ctl = NULL;
483 LocalFree(ctlInfo);
484 CryptMemFree(content);
485 CryptMsgClose(msg);
486 return NULL;
487 }
488 return &ctl->ctx;
489 }
490
CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)491 PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
492 {
493 TRACE("(%p)\n", pCtlContext);
494 if (pCtlContext)
495 Context_AddRef(&ctl_from_ptr(pCtlContext)->base);
496 return pCtlContext;
497 }
498
CertFreeCTLContext(PCCTL_CONTEXT pCTLContext)499 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCTLContext)
500 {
501 TRACE("(%p)\n", pCTLContext);
502
503 if (pCTLContext)
504 Context_Release(&ctl_from_ptr(pCTLContext)->base);
505 return TRUE;
506 }
507
CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,DWORD dwPropId)508 DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,
509 DWORD dwPropId)
510 {
511 ctl_t *ctl = ctl_from_ptr(pCTLContext);
512 DWORD ret;
513
514 TRACE("(%p, %d)\n", pCTLContext, dwPropId);
515
516 if (ctl->base.properties)
517 ret = ContextPropertyList_EnumPropIDs(ctl->base.properties, dwPropId);
518 else
519 ret = 0;
520 return ret;
521 }
522
523 static BOOL CTLContext_SetProperty(ctl_t *ctl, DWORD dwPropId,
524 DWORD dwFlags, const void *pvData);
525
CTLContext_GetHashProp(ctl_t * ctl,DWORD dwPropId,ALG_ID algID,const BYTE * toHash,DWORD toHashLen,void * pvData,DWORD * pcbData)526 static BOOL CTLContext_GetHashProp(ctl_t *ctl, DWORD dwPropId,
527 ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
528 DWORD *pcbData)
529 {
530 BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
531 pcbData);
532 if (ret && pvData)
533 {
534 CRYPT_DATA_BLOB blob = { *pcbData, pvData };
535
536 ret = CTLContext_SetProperty(ctl, dwPropId, 0, &blob);
537 }
538 return ret;
539 }
540
CTLContext_GetProperty(ctl_t * ctl,DWORD dwPropId,void * pvData,DWORD * pcbData)541 static BOOL CTLContext_GetProperty(ctl_t *ctl, DWORD dwPropId,
542 void *pvData, DWORD *pcbData)
543 {
544 BOOL ret;
545 CRYPT_DATA_BLOB blob;
546
547 TRACE("(%p, %d, %p, %p)\n", ctl, dwPropId, pvData, pcbData);
548
549 if (ctl->base.properties)
550 ret = ContextPropertyList_FindProperty(ctl->base.properties, dwPropId, &blob);
551 else
552 ret = FALSE;
553 if (ret)
554 {
555 if (!pvData)
556 *pcbData = blob.cbData;
557 else if (*pcbData < blob.cbData)
558 {
559 SetLastError(ERROR_MORE_DATA);
560 *pcbData = blob.cbData;
561 ret = FALSE;
562 }
563 else
564 {
565 memcpy(pvData, blob.pbData, blob.cbData);
566 *pcbData = blob.cbData;
567 }
568 }
569 else
570 {
571 /* Implicit properties */
572 switch (dwPropId)
573 {
574 case CERT_SHA1_HASH_PROP_ID:
575 ret = CTLContext_GetHashProp(ctl, dwPropId, CALG_SHA1,
576 ctl->ctx.pbCtlEncoded, ctl->ctx.cbCtlEncoded, pvData, pcbData);
577 break;
578 case CERT_MD5_HASH_PROP_ID:
579 ret = CTLContext_GetHashProp(ctl, dwPropId, CALG_MD5,
580 ctl->ctx.pbCtlEncoded, ctl->ctx.cbCtlEncoded, pvData, pcbData);
581 break;
582 default:
583 SetLastError(CRYPT_E_NOT_FOUND);
584 }
585 }
586 TRACE("returning %d\n", ret);
587 return ret;
588 }
589
CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,DWORD dwPropId,void * pvData,DWORD * pcbData)590 BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
591 DWORD dwPropId, void *pvData, DWORD *pcbData)
592 {
593 BOOL ret;
594
595 TRACE("(%p, %d, %p, %p)\n", pCTLContext, dwPropId, pvData, pcbData);
596
597 switch (dwPropId)
598 {
599 case 0:
600 case CERT_CERT_PROP_ID:
601 case CERT_CRL_PROP_ID:
602 case CERT_CTL_PROP_ID:
603 SetLastError(E_INVALIDARG);
604 ret = FALSE;
605 break;
606 case CERT_ACCESS_STATE_PROP_ID:
607 if (!pvData)
608 {
609 *pcbData = sizeof(DWORD);
610 ret = TRUE;
611 }
612 else if (*pcbData < sizeof(DWORD))
613 {
614 SetLastError(ERROR_MORE_DATA);
615 *pcbData = sizeof(DWORD);
616 ret = FALSE;
617 }
618 else
619 {
620 ret = CertGetStoreProperty(pCTLContext->hCertStore, dwPropId, pvData, pcbData);
621 }
622 break;
623 default:
624 ret = CTLContext_GetProperty(ctl_from_ptr(pCTLContext), dwPropId, pvData,
625 pcbData);
626 }
627 return ret;
628 }
629
CTLContext_SetProperty(ctl_t * ctl,DWORD dwPropId,DWORD dwFlags,const void * pvData)630 static BOOL CTLContext_SetProperty(ctl_t *ctl, DWORD dwPropId,
631 DWORD dwFlags, const void *pvData)
632 {
633 BOOL ret;
634
635 TRACE("(%p, %d, %08x, %p)\n", ctl, dwPropId, dwFlags, pvData);
636
637 if (!ctl->base.properties)
638 ret = FALSE;
639 else if (!pvData)
640 {
641 ContextPropertyList_RemoveProperty(ctl->base.properties, dwPropId);
642 ret = TRUE;
643 }
644 else
645 {
646 switch (dwPropId)
647 {
648 case CERT_AUTO_ENROLL_PROP_ID:
649 case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
650 case CERT_DESCRIPTION_PROP_ID:
651 case CERT_FRIENDLY_NAME_PROP_ID:
652 case CERT_HASH_PROP_ID:
653 case CERT_KEY_IDENTIFIER_PROP_ID:
654 case CERT_MD5_HASH_PROP_ID:
655 case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
656 case CERT_PUBKEY_ALG_PARA_PROP_ID:
657 case CERT_PVK_FILE_PROP_ID:
658 case CERT_SIGNATURE_HASH_PROP_ID:
659 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
660 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
661 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
662 case CERT_ENROLLMENT_PROP_ID:
663 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
664 case CERT_RENEWAL_PROP_ID:
665 {
666 PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
667
668 ret = ContextPropertyList_SetProperty(ctl->base.properties, dwPropId,
669 blob->pbData, blob->cbData);
670 break;
671 }
672 case CERT_DATE_STAMP_PROP_ID:
673 ret = ContextPropertyList_SetProperty(ctl->base.properties, dwPropId,
674 pvData, sizeof(FILETIME));
675 break;
676 default:
677 FIXME("%d: stub\n", dwPropId);
678 ret = FALSE;
679 }
680 }
681 TRACE("returning %d\n", ret);
682 return ret;
683 }
684
CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,DWORD dwPropId,DWORD dwFlags,const void * pvData)685 BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
686 DWORD dwPropId, DWORD dwFlags, const void *pvData)
687 {
688 BOOL ret;
689
690 TRACE("(%p, %d, %08x, %p)\n", pCTLContext, dwPropId, dwFlags, pvData);
691
692 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
693 * crashes on most of these, I'll be safer.
694 */
695 switch (dwPropId)
696 {
697 case 0:
698 case CERT_ACCESS_STATE_PROP_ID:
699 case CERT_CERT_PROP_ID:
700 case CERT_CRL_PROP_ID:
701 case CERT_CTL_PROP_ID:
702 SetLastError(E_INVALIDARG);
703 return FALSE;
704 }
705 ret = CTLContext_SetProperty(ctl_from_ptr(pCTLContext), dwPropId, dwFlags, pvData);
706 TRACE("returning %d\n", ret);
707 return ret;
708 }
709