wined3d: Add the bulk of the GLSL string generation functions.
[wine] / dlls / crypt32 / crl.c
1 /*
2  * Copyright 2006 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 #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 PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType,
31  const BYTE* pbCrlEncoded, DWORD cbCrlEncoded)
32 {
33     PCRL_CONTEXT crl = NULL;
34     BOOL ret;
35     PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
36     PCRL_INFO crlInfo = NULL;
37     DWORD size = 0;
38
39     TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCrlEncoded,
40      cbCrlEncoded);
41
42     if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
43     {
44         SetLastError(E_INVALIDARG);
45         return NULL;
46     }
47     /* First try to decode it as a signed crl. */
48     ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT, pbCrlEncoded,
49      cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&signedCrl, &size);
50     if (ret)
51     {
52         size = 0;
53         ret = CryptDecodeObjectEx(dwCertEncodingType,
54          X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
55          signedCrl->ToBeSigned.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
56          (BYTE *)&crlInfo, &size);
57         LocalFree(signedCrl);
58     }
59     /* Failing that, try it as an unsigned crl */
60     if (!ret)
61     {
62         size = 0;
63         ret = CryptDecodeObjectEx(dwCertEncodingType,
64          X509_CERT_CRL_TO_BE_SIGNED, pbCrlEncoded, cbCrlEncoded,
65          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL,
66          (BYTE *)&crlInfo, &size);
67     }
68     if (ret)
69     {
70         BYTE *data = NULL;
71
72         crl = (PCRL_CONTEXT)Context_CreateDataContext(sizeof(CRL_CONTEXT));
73         if (!crl)
74             goto end;
75         data = CryptMemAlloc(cbCrlEncoded);
76         if (!data)
77         {
78             CryptMemFree(crl);
79             crl = NULL;
80             goto end;
81         }
82         memcpy(data, pbCrlEncoded, cbCrlEncoded);
83         crl->dwCertEncodingType = dwCertEncodingType;
84         crl->pbCrlEncoded       = data;
85         crl->cbCrlEncoded       = cbCrlEncoded;
86         crl->pCrlInfo           = crlInfo;
87         crl->hCertStore         = 0;
88     }
89
90 end:
91     return (PCCRL_CONTEXT)crl;
92 }
93
94 BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore,
95  DWORD dwCertEncodingType, const BYTE *pbCrlEncoded, DWORD cbCrlEncoded,
96  DWORD dwAddDisposition, PCCRL_CONTEXT *ppCrlContext)
97 {
98     PCCRL_CONTEXT crl = CertCreateCRLContext(dwCertEncodingType,
99      pbCrlEncoded, cbCrlEncoded);
100     BOOL ret;
101
102     TRACE("(%p, %08lx, %p, %ld, %08lx, %p)\n", hCertStore, dwCertEncodingType,
103      pbCrlEncoded, cbCrlEncoded, dwAddDisposition, ppCrlContext);
104
105     if (crl)
106     {
107         ret = CertAddCRLContextToStore(hCertStore, crl, dwAddDisposition,
108          ppCrlContext);
109         CertFreeCRLContext(crl);
110     }
111     else
112         ret = FALSE;
113     return ret;
114 }
115
116 typedef BOOL (*CrlCompareFunc)(PCCRL_CONTEXT pCrlContext, DWORD dwType,
117  DWORD dwFlags, const void *pvPara);
118
119 static BOOL compare_crl_any(PCCRL_CONTEXT pCrlContext, DWORD dwType,
120  DWORD dwFlags, const void *pvPara)
121 {
122     return TRUE;
123 }
124
125 static BOOL compare_crl_issued_by(PCCRL_CONTEXT pCrlContext, DWORD dwType,
126  DWORD dwFlags, const void *pvPara)
127 {
128     BOOL ret;
129
130     if (pvPara)
131     {
132         PCCERT_CONTEXT issuer = (PCCERT_CONTEXT)pvPara;
133
134         ret = CertCompareCertificateName(issuer->dwCertEncodingType,
135          &issuer->pCertInfo->Issuer, &pCrlContext->pCrlInfo->Issuer);
136     }
137     else
138         ret = TRUE;
139     return ret;
140 }
141
142 static BOOL compare_crl_existing(PCCRL_CONTEXT pCrlContext, DWORD dwType,
143  DWORD dwFlags, const void *pvPara)
144 {
145     BOOL ret;
146
147     if (pvPara)
148     {
149         PCCRL_CONTEXT crl = (PCCRL_CONTEXT)pvPara;
150
151         ret = CertCompareCertificateName(pCrlContext->dwCertEncodingType,
152          &pCrlContext->pCrlInfo->Issuer, &crl->pCrlInfo->Issuer);
153     }
154     else
155         ret = TRUE;
156     return ret;
157 }
158
159 PCCRL_CONTEXT WINAPI CertFindCRLInStore(HCERTSTORE hCertStore,
160  DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType,
161  const void *pvFindPara, PCCRL_CONTEXT pPrevCrlContext)
162 {
163     PCCRL_CONTEXT ret;
164     CrlCompareFunc compare;
165
166     TRACE("(%p, %ld, %ld, %ld, %p, %p)\n", hCertStore, dwCertEncodingType,
167          dwFindFlags, dwFindType, pvFindPara, pPrevCrlContext);
168
169     switch (dwFindType)
170     {
171     case CRL_FIND_ANY:
172         compare = compare_crl_any;
173         break;
174     case CRL_FIND_ISSUED_BY:
175         compare = compare_crl_issued_by;
176         break;
177     case CRL_FIND_EXISTING:
178         compare = compare_crl_existing;
179         break;
180     default:
181         FIXME("find type %08lx unimplemented\n", dwFindType);
182         compare = NULL;
183     }
184
185     if (compare)
186     {
187         BOOL matches = FALSE;
188
189         ret = pPrevCrlContext;
190         do {
191             ret = CertEnumCRLsInStore(hCertStore, ret);
192             if (ret)
193                 matches = compare(ret, dwFindType, dwFindFlags, pvFindPara);
194         } while (ret != NULL && !matches);
195         if (!ret)
196             SetLastError(CRYPT_E_NOT_FOUND);
197     }
198     else
199     {
200         SetLastError(CRYPT_E_NOT_FOUND);
201         ret = NULL;
202     }
203     return ret;
204 }
205
206 PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT pCrlContext)
207 {
208     TRACE("(%p)\n", pCrlContext);
209     Context_AddRef((void *)pCrlContext, sizeof(CRL_CONTEXT));
210     return pCrlContext;
211 }
212
213 static void CrlDataContext_Free(void *context)
214 {
215     PCRL_CONTEXT crlContext = (PCRL_CONTEXT)context;
216
217     CryptMemFree(crlContext->pbCrlEncoded);
218     LocalFree(crlContext->pCrlInfo);
219 }
220
221 BOOL WINAPI CertFreeCRLContext( PCCRL_CONTEXT pCrlContext)
222 {
223     TRACE("(%p)\n", pCrlContext);
224
225     if (pCrlContext)
226         Context_Release((void *)pCrlContext, sizeof(CRL_CONTEXT),
227          CrlDataContext_Free);
228     return TRUE;
229 }
230
231 DWORD WINAPI CertEnumCRLContextProperties(PCCRL_CONTEXT pCRLContext,
232  DWORD dwPropId)
233 {
234     PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
235      (void *)pCRLContext, sizeof(CRL_CONTEXT));
236     DWORD ret;
237
238     TRACE("(%p, %ld)\n", pCRLContext, dwPropId);
239
240     if (properties)
241         ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
242     else
243         ret = 0;
244     return ret;
245 }
246
247 static BOOL WINAPI CRLContext_SetProperty(void *context, DWORD dwPropId,
248  DWORD dwFlags, const void *pvData);
249
250 static BOOL CRLContext_GetHashProp(void *context, DWORD dwPropId,
251  ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
252  DWORD *pcbData)
253 {
254     BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
255      pcbData);
256     if (ret)
257     {
258         CRYPT_DATA_BLOB blob = { *pcbData, pvData };
259
260         ret = CRLContext_SetProperty(context, dwPropId, 0, &blob);
261     }
262     return ret;
263 }
264
265 static BOOL WINAPI CRLContext_GetProperty(void *context, DWORD dwPropId,
266  void *pvData, DWORD *pcbData)
267 {
268     PCCRL_CONTEXT pCRLContext = (PCCRL_CONTEXT)context;
269     PCONTEXT_PROPERTY_LIST properties =
270      Context_GetProperties(context, sizeof(CRL_CONTEXT));
271     BOOL ret;
272     CRYPT_DATA_BLOB blob;
273
274     TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData);
275
276     if (properties)
277         ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
278     else
279         ret = FALSE;
280     if (ret)
281     {
282         if (!pvData)
283         {
284             *pcbData = blob.cbData;
285             ret = TRUE;
286         }
287         else if (*pcbData < blob.cbData)
288         {
289             SetLastError(ERROR_MORE_DATA);
290             *pcbData = blob.cbData;
291         }
292         else
293         {
294             memcpy(pvData, blob.pbData, blob.cbData);
295             *pcbData = blob.cbData;
296             ret = TRUE;
297         }
298     }
299     else
300     {
301         /* Implicit properties */
302         switch (dwPropId)
303         {
304         case CERT_SHA1_HASH_PROP_ID:
305             ret = CRLContext_GetHashProp(context, dwPropId, CALG_SHA1,
306              pCRLContext->pbCrlEncoded, pCRLContext->cbCrlEncoded, pvData,
307              pcbData);
308             break;
309         case CERT_MD5_HASH_PROP_ID:
310             ret = CRLContext_GetHashProp(context, dwPropId, CALG_MD5,
311              pCRLContext->pbCrlEncoded, pCRLContext->cbCrlEncoded, pvData,
312              pcbData);
313             break;
314         default:
315             SetLastError(CRYPT_E_NOT_FOUND);
316         }
317     }
318     TRACE("returning %d\n", ret);
319     return ret;
320 }
321
322 BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
323  DWORD dwPropId, void *pvData, DWORD *pcbData)
324 {
325     BOOL ret;
326
327     TRACE("(%p, %ld, %p, %p)\n", pCRLContext, dwPropId, pvData, pcbData);
328
329     switch (dwPropId)
330     {
331     case 0:
332     case CERT_CERT_PROP_ID:
333     case CERT_CRL_PROP_ID:
334     case CERT_CTL_PROP_ID:
335         SetLastError(E_INVALIDARG);
336         ret = FALSE;
337         break;
338     case CERT_ACCESS_STATE_PROP_ID:
339         if (!pvData)
340         {
341             *pcbData = sizeof(DWORD);
342             ret = TRUE;
343         }
344         else if (*pcbData < sizeof(DWORD))
345         {
346             SetLastError(ERROR_MORE_DATA);
347             *pcbData = sizeof(DWORD);
348             ret = FALSE;
349         }
350         else
351         {
352             *(DWORD *)pvData =
353              CertStore_GetAccessState(pCRLContext->hCertStore);
354             ret = TRUE;
355         }
356         break;
357     default:
358         ret = CRLContext_GetProperty((void *)pCRLContext, dwPropId, pvData,
359          pcbData);
360     }
361     return ret;
362 }
363
364 static BOOL WINAPI CRLContext_SetProperty(void *context, DWORD dwPropId,
365  DWORD dwFlags, const void *pvData)
366 {
367     PCONTEXT_PROPERTY_LIST properties =
368      Context_GetProperties(context, sizeof(CERT_CONTEXT));
369     BOOL ret;
370
371     TRACE("(%p, %ld, %08lx, %p)\n", context, dwPropId, dwFlags, pvData);
372
373     if (!properties)
374         ret = FALSE;
375     else if (!pvData)
376     {
377         ContextPropertyList_RemoveProperty(properties, dwPropId);
378         ret = TRUE;
379     }
380     else
381     {
382         switch (dwPropId)
383         {
384         case CERT_AUTO_ENROLL_PROP_ID:
385         case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
386         case CERT_DESCRIPTION_PROP_ID:
387         case CERT_FRIENDLY_NAME_PROP_ID:
388         case CERT_HASH_PROP_ID:
389         case CERT_KEY_IDENTIFIER_PROP_ID:
390         case CERT_MD5_HASH_PROP_ID:
391         case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
392         case CERT_PUBKEY_ALG_PARA_PROP_ID:
393         case CERT_PVK_FILE_PROP_ID:
394         case CERT_SIGNATURE_HASH_PROP_ID:
395         case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
396         case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
397         case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
398         case CERT_ENROLLMENT_PROP_ID:
399         case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
400         case CERT_RENEWAL_PROP_ID:
401         {
402             PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
403
404             ret = ContextPropertyList_SetProperty(properties, dwPropId,
405              blob->pbData, blob->cbData);
406             break;
407         }
408         case CERT_DATE_STAMP_PROP_ID:
409             ret = ContextPropertyList_SetProperty(properties, dwPropId,
410              (LPBYTE)pvData, sizeof(FILETIME));
411             break;
412         default:
413             FIXME("%ld: stub\n", dwPropId);
414             ret = FALSE;
415         }
416     }
417     TRACE("returning %d\n", ret);
418     return ret;
419 }
420
421 BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
422  DWORD dwPropId, DWORD dwFlags, const void *pvData)
423 {
424     BOOL ret;
425
426     TRACE("(%p, %ld, %08lx, %p)\n", pCRLContext, dwPropId, dwFlags, pvData);
427
428     /* Handle special cases for "read-only"/invalid prop IDs.  Windows just
429      * crashes on most of these, I'll be safer.
430      */
431     switch (dwPropId)
432     {
433     case 0:
434     case CERT_ACCESS_STATE_PROP_ID:
435     case CERT_CERT_PROP_ID:
436     case CERT_CRL_PROP_ID:
437     case CERT_CTL_PROP_ID:
438         SetLastError(E_INVALIDARG);
439         return FALSE;
440     }
441     ret = CRLContext_SetProperty((void *)pCRLContext, dwPropId, dwFlags,
442      pvData);
443     TRACE("returning %d\n", ret);
444     return ret;
445 }
446
447 LONG WINAPI CertVerifyCRLTimeValidity(LPFILETIME pTimeToVerify,
448  PCRL_INFO pCrlInfo)
449 {
450     FILETIME fileTime;
451     LONG ret;
452
453     if (!pTimeToVerify)
454     {
455         SYSTEMTIME sysTime;
456
457         GetSystemTime(&sysTime);
458         SystemTimeToFileTime(&sysTime, &fileTime);
459         pTimeToVerify = &fileTime;
460     }
461     if ((ret = CompareFileTime(pTimeToVerify, &pCrlInfo->ThisUpdate)) >= 0)
462     {
463         ret = CompareFileTime(pTimeToVerify, &pCrlInfo->NextUpdate);
464         if (ret < 0)
465             ret = 0;
466     }
467     return ret;
468 }