03267db076e4183b55fbfc9c3ab695f54d5d5f97
[reactos.git] / reactos / dll / win32 / 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 }