crypt32: Set output chain to NULL.
[wine] / dlls / crypt32 / chain.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 #include <stdarg.h>
20 #include "windef.h"
21 #include "winbase.h"
22 #include "wincrypt.h"
23 #include "wine/debug.h"
24 #include "crypt32_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
27
28 /* This represents a subset of a certificate chain engine:  it doesn't include
29  * the "hOther" store described by MSDN, because I'm not sure how that's used.
30  * It also doesn't include the "hTrust" store, because I don't yet implement
31  * CTLs or complex certificate chains.
32  */
33 typedef struct _CertificateChainEngine
34 {
35     LONG       ref;
36     HCERTSTORE hRoot;
37     HCERTSTORE hWorld;
38     DWORD      dwFlags;
39     DWORD      dwUrlRetrievalTimeout;
40     DWORD      MaximumCachedCertificates;
41     DWORD      CycleDetectionModulus;
42 } CertificateChainEngine, *PCertificateChainEngine;
43
44 static inline void CRYPT_AddStoresToCollection(HCERTSTORE collection,
45  DWORD cStores, HCERTSTORE *stores)
46 {
47     DWORD i;
48
49     for (i = 0; i < cStores; i++)
50         CertAddStoreToCollection(collection, stores[i], 0, 0);
51 }
52
53 static inline void CRYPT_CloseStores(DWORD cStores, HCERTSTORE *stores)
54 {
55     DWORD i;
56
57     for (i = 0; i < cStores; i++)
58         CertCloseStore(stores[i], 0);
59 }
60
61 static const WCHAR rootW[] = { 'R','o','o','t',0 };
62
63 static BOOL CRYPT_CheckRestrictedRoot(HCERTSTORE store)
64 {
65     BOOL ret = TRUE;
66
67     if (store)
68     {
69         HCERTSTORE rootStore = CertOpenSystemStoreW(0, rootW);
70         PCCERT_CONTEXT cert = NULL, check;
71         BYTE hash[20];
72         DWORD size;
73
74         do {
75             cert = CertEnumCertificatesInStore(store, cert);
76             if (cert)
77             {
78                 size = sizeof(hash);
79
80                 ret = CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID,
81                  hash, &size);
82                 if (ret)
83                 {
84                     CRYPT_HASH_BLOB blob = { sizeof(hash), hash };
85
86                     check = CertFindCertificateInStore(rootStore,
87                      cert->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
88                      NULL);
89                     if (!check)
90                         ret = FALSE;
91                     else
92                         CertFreeCertificateContext(check);
93                 }
94             }
95         } while (ret && cert);
96         if (cert)
97             CertFreeCertificateContext(cert);
98         CertCloseStore(rootStore, 0);
99     }
100     return ret;
101 }
102
103 BOOL WINAPI CertCreateCertificateChainEngine(PCERT_CHAIN_ENGINE_CONFIG pConfig,
104  HCERTCHAINENGINE *phChainEngine)
105 {
106     static const WCHAR caW[] = { 'C','A',0 };
107     static const WCHAR myW[] = { 'M','y',0 };
108     static const WCHAR trustW[] = { 'T','r','u','s','t',0 };
109     BOOL ret;
110
111     TRACE("(%p, %p)\n", pConfig, phChainEngine);
112
113     if (pConfig->cbSize != sizeof(*pConfig))
114     {
115         SetLastError(E_INVALIDARG);
116         return FALSE;
117     }
118     *phChainEngine = NULL;
119     ret = CRYPT_CheckRestrictedRoot(pConfig->hRestrictedRoot);
120     if (ret)
121     {
122         PCertificateChainEngine engine =
123          CryptMemAlloc(sizeof(CertificateChainEngine));
124
125         if (engine)
126         {
127             HCERTSTORE worldStores[4];
128
129             engine->ref = 1;
130             if (pConfig->hRestrictedRoot)
131                 engine->hRoot = CertDuplicateStore(pConfig->hRestrictedRoot);
132             else
133                 engine->hRoot = CertOpenSystemStoreW(0, rootW);
134             engine->hWorld = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
135              CERT_STORE_CREATE_NEW_FLAG, NULL);
136             worldStores[0] = CertDuplicateStore(engine->hRoot);
137             worldStores[1] = CertOpenSystemStoreW(0, caW);
138             worldStores[2] = CertOpenSystemStoreW(0, myW);
139             worldStores[3] = CertOpenSystemStoreW(0, trustW);
140             CRYPT_AddStoresToCollection(engine->hWorld,
141              sizeof(worldStores) / sizeof(worldStores[0]), worldStores);
142             CRYPT_AddStoresToCollection(engine->hWorld,
143              pConfig->cAdditionalStore, pConfig->rghAdditionalStore);
144             CRYPT_CloseStores(sizeof(worldStores) / sizeof(worldStores[0]),
145              worldStores);
146             engine->dwFlags = pConfig->dwFlags;
147             engine->dwUrlRetrievalTimeout = pConfig->dwUrlRetrievalTimeout;
148             engine->MaximumCachedCertificates =
149              pConfig->MaximumCachedCertificates;
150             engine->CycleDetectionModulus = pConfig->CycleDetectionModulus;
151             *phChainEngine = (HCERTCHAINENGINE)engine;
152             ret = TRUE;
153         }
154         else
155             ret = FALSE;
156     }
157     return ret;
158 }
159
160 void WINAPI CertFreeCertificateChainEngine(HCERTCHAINENGINE hChainEngine)
161 {
162     PCertificateChainEngine engine = (PCertificateChainEngine)hChainEngine;
163
164     TRACE("(%p)\n", hChainEngine);
165
166     if (engine && InterlockedDecrement(&engine->ref) == 0)
167     {
168         CertCloseStore(engine->hWorld, 0);
169         CertCloseStore(engine->hRoot, 0);
170         CryptMemFree(engine);
171     }
172 }
173
174 BOOL WINAPI CertGetCertificateChain(HCERTCHAINENGINE hChainEngine,
175  PCCERT_CONTEXT pCertContext, LPFILETIME pTime, HCERTSTORE hAdditionalStore,
176  PCERT_CHAIN_PARA pChainPara, DWORD dwFlags, LPVOID pvReserved,
177  PCCERT_CHAIN_CONTEXT* ppChainContext)
178 {
179     FIXME("(%p, %p, %p, %p, %p, 0x%08X, %p, %p): stub\n", hChainEngine,
180      pCertContext, pTime, hAdditionalStore, pChainPara, dwFlags, pvReserved,
181      ppChainContext);
182
183     if (ppChainContext)
184         *ppChainContext = NULL;
185     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
186     return FALSE;
187 }
188
189 void WINAPI CertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
190 {
191     FIXME("(%p): stub\n", pChainContext);
192 }