1c2c66affSColin Finck /*
2c2c66affSColin Finck * Copyright (C) 2006 Maarten Lankhorst
3c2c66affSColin Finck * Copyright 2007 Juan Lang
4c2c66affSColin Finck *
5c2c66affSColin Finck * This library is free software; you can redistribute it and/or
6c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
7c2c66affSColin Finck * License as published by the Free Software Foundation; either
8c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
9c2c66affSColin Finck *
10c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
11c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13c2c66affSColin Finck * Lesser General Public License for more details.
14c2c66affSColin Finck *
15c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
16c2c66affSColin Finck * License along with this library; if not, write to the Free Software
17c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18c2c66affSColin Finck *
19c2c66affSColin Finck */
20c2c66affSColin Finck
21c2c66affSColin Finck #define NONAMELESSUNION
22c2c66affSColin Finck #define CERT_REVOCATION_PARA_HAS_EXTRA_FIELDS
23c2c66affSColin Finck
24c2c66affSColin Finck #include <stdio.h>
25*18075aa0SAmine Khaldi #include <stdarg.h>
26c2c66affSColin Finck
27*18075aa0SAmine Khaldi #include "windef.h"
28*18075aa0SAmine Khaldi #include "winbase.h"
29*18075aa0SAmine Khaldi #include "winnt.h"
30*18075aa0SAmine Khaldi #include "winnls.h"
31*18075aa0SAmine Khaldi #include "wininet.h"
32*18075aa0SAmine Khaldi #include "objbase.h"
33*18075aa0SAmine Khaldi #include "wincrypt.h"
34c2c66affSColin Finck
35*18075aa0SAmine Khaldi #include "wine/debug.h"
36c2c66affSColin Finck
37c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(cryptnet);
38c2c66affSColin Finck
39c2c66affSColin Finck #define IS_INTOID(x) (((ULONG_PTR)(x) >> 16) == 0)
40c2c66affSColin Finck
41c2c66affSColin Finck static const WCHAR cryptNet[] = { 'c','r','y','p','t','n','e','t','.',
42c2c66affSColin Finck 'd','l','l',0 };
43c2c66affSColin Finck
44c2c66affSColin Finck /***********************************************************************
45c2c66affSColin Finck * DllRegisterServer (CRYPTNET.@)
46c2c66affSColin Finck */
DllRegisterServer(void)47c2c66affSColin Finck HRESULT WINAPI DllRegisterServer(void)
48c2c66affSColin Finck {
49c2c66affSColin Finck TRACE("\n");
50c2c66affSColin Finck CryptRegisterDefaultOIDFunction(X509_ASN_ENCODING,
51c2c66affSColin Finck CRYPT_OID_VERIFY_REVOCATION_FUNC, 0, cryptNet);
52c2c66affSColin Finck CryptRegisterOIDFunction(0, CRYPT_OID_OPEN_STORE_PROV_FUNC, "Ldap",
53c2c66affSColin Finck cryptNet, "LdapProvOpenStore");
54c2c66affSColin Finck CryptRegisterOIDFunction(0, CRYPT_OID_OPEN_STORE_PROV_FUNC,
55c2c66affSColin Finck CERT_STORE_PROV_LDAP_W, cryptNet, "LdapProvOpenStore");
56c2c66affSColin Finck return S_OK;
57c2c66affSColin Finck }
58c2c66affSColin Finck
59c2c66affSColin Finck /***********************************************************************
60c2c66affSColin Finck * DllUnregisterServer (CRYPTNET.@)
61c2c66affSColin Finck */
DllUnregisterServer(void)62c2c66affSColin Finck HRESULT WINAPI DllUnregisterServer(void)
63c2c66affSColin Finck {
64c2c66affSColin Finck TRACE("\n");
65c2c66affSColin Finck CryptUnregisterDefaultOIDFunction(X509_ASN_ENCODING,
66c2c66affSColin Finck CRYPT_OID_VERIFY_REVOCATION_FUNC, cryptNet);
67c2c66affSColin Finck CryptUnregisterOIDFunction(0, CRYPT_OID_OPEN_STORE_PROV_FUNC, "Ldap");
68c2c66affSColin Finck CryptUnregisterOIDFunction(0, CRYPT_OID_OPEN_STORE_PROV_FUNC,
69c2c66affSColin Finck CERT_STORE_PROV_LDAP_W);
70c2c66affSColin Finck return S_OK;
71c2c66affSColin Finck }
72c2c66affSColin Finck
url_oid_to_str(LPCSTR oid)73c2c66affSColin Finck static const char *url_oid_to_str(LPCSTR oid)
74c2c66affSColin Finck {
75c2c66affSColin Finck if (IS_INTOID(oid))
76c2c66affSColin Finck {
77c2c66affSColin Finck static char buf[10];
78c2c66affSColin Finck
79c2c66affSColin Finck switch (LOWORD(oid))
80c2c66affSColin Finck {
81c2c66affSColin Finck #define _x(oid) case LOWORD(oid): return #oid
82c2c66affSColin Finck _x(URL_OID_CERTIFICATE_ISSUER);
83c2c66affSColin Finck _x(URL_OID_CERTIFICATE_CRL_DIST_POINT);
84c2c66affSColin Finck _x(URL_OID_CTL_ISSUER);
85c2c66affSColin Finck _x(URL_OID_CTL_NEXT_UPDATE);
86c2c66affSColin Finck _x(URL_OID_CRL_ISSUER);
87c2c66affSColin Finck _x(URL_OID_CERTIFICATE_FRESHEST_CRL);
88c2c66affSColin Finck _x(URL_OID_CRL_FRESHEST_CRL);
89c2c66affSColin Finck _x(URL_OID_CROSS_CERT_DIST_POINT);
90c2c66affSColin Finck #undef _x
91c2c66affSColin Finck default:
92c2c66affSColin Finck snprintf(buf, sizeof(buf), "%d", LOWORD(oid));
93c2c66affSColin Finck return buf;
94c2c66affSColin Finck }
95c2c66affSColin Finck }
96c2c66affSColin Finck else
97c2c66affSColin Finck return oid;
98c2c66affSColin Finck }
99c2c66affSColin Finck
100c2c66affSColin Finck typedef BOOL (WINAPI *UrlDllGetObjectUrlFunc)(LPCSTR, LPVOID, DWORD,
101c2c66affSColin Finck PCRYPT_URL_ARRAY, DWORD *, PCRYPT_URL_INFO, DWORD *, LPVOID);
102c2c66affSColin Finck
CRYPT_GetUrlFromCertificateIssuer(LPCSTR pszUrlOid,LPVOID pvPara,DWORD dwFlags,PCRYPT_URL_ARRAY pUrlArray,DWORD * pcbUrlArray,PCRYPT_URL_INFO pUrlInfo,DWORD * pcbUrlInfo,LPVOID pvReserved)103c2c66affSColin Finck static BOOL WINAPI CRYPT_GetUrlFromCertificateIssuer(LPCSTR pszUrlOid,
104c2c66affSColin Finck LPVOID pvPara, DWORD dwFlags, PCRYPT_URL_ARRAY pUrlArray, DWORD *pcbUrlArray,
105c2c66affSColin Finck PCRYPT_URL_INFO pUrlInfo, DWORD *pcbUrlInfo, LPVOID pvReserved)
106c2c66affSColin Finck {
107c2c66affSColin Finck PCCERT_CONTEXT cert = pvPara;
108c2c66affSColin Finck PCERT_EXTENSION ext;
109c2c66affSColin Finck BOOL ret = FALSE;
110c2c66affSColin Finck
111c2c66affSColin Finck /* The only applicable flag is CRYPT_GET_URL_FROM_EXTENSION */
112c2c66affSColin Finck if (dwFlags && !(dwFlags & CRYPT_GET_URL_FROM_EXTENSION))
113c2c66affSColin Finck {
114c2c66affSColin Finck SetLastError(CRYPT_E_NOT_FOUND);
115c2c66affSColin Finck return FALSE;
116c2c66affSColin Finck }
117c2c66affSColin Finck if ((ext = CertFindExtension(szOID_AUTHORITY_INFO_ACCESS,
118c2c66affSColin Finck cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
119c2c66affSColin Finck {
120c2c66affSColin Finck CERT_AUTHORITY_INFO_ACCESS *aia;
121c2c66affSColin Finck DWORD size;
122c2c66affSColin Finck
123c2c66affSColin Finck ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_AUTHORITY_INFO_ACCESS,
124c2c66affSColin Finck ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
125c2c66affSColin Finck &aia, &size);
126c2c66affSColin Finck if (ret)
127c2c66affSColin Finck {
128c2c66affSColin Finck DWORD i, cUrl, bytesNeeded = sizeof(CRYPT_URL_ARRAY);
129c2c66affSColin Finck
130c2c66affSColin Finck for (i = 0, cUrl = 0; i < aia->cAccDescr; i++)
131c2c66affSColin Finck if (!strcmp(aia->rgAccDescr[i].pszAccessMethod,
132c2c66affSColin Finck szOID_PKIX_CA_ISSUERS))
133c2c66affSColin Finck {
134c2c66affSColin Finck if (aia->rgAccDescr[i].AccessLocation.dwAltNameChoice ==
135c2c66affSColin Finck CERT_ALT_NAME_URL)
136c2c66affSColin Finck {
137c2c66affSColin Finck if (aia->rgAccDescr[i].AccessLocation.u.pwszURL)
138c2c66affSColin Finck {
139c2c66affSColin Finck cUrl++;
140c2c66affSColin Finck bytesNeeded += sizeof(LPWSTR) +
141c2c66affSColin Finck (lstrlenW(aia->rgAccDescr[i].AccessLocation.u.
142c2c66affSColin Finck pwszURL) + 1) * sizeof(WCHAR);
143c2c66affSColin Finck }
144c2c66affSColin Finck }
145c2c66affSColin Finck else
146c2c66affSColin Finck FIXME("unsupported alt name type %d\n",
147c2c66affSColin Finck aia->rgAccDescr[i].AccessLocation.dwAltNameChoice);
148c2c66affSColin Finck }
149c2c66affSColin Finck if (!pcbUrlArray)
150c2c66affSColin Finck {
151c2c66affSColin Finck SetLastError(E_INVALIDARG);
152c2c66affSColin Finck ret = FALSE;
153c2c66affSColin Finck }
154c2c66affSColin Finck else if (!pUrlArray)
155c2c66affSColin Finck *pcbUrlArray = bytesNeeded;
156c2c66affSColin Finck else if (*pcbUrlArray < bytesNeeded)
157c2c66affSColin Finck {
158c2c66affSColin Finck SetLastError(ERROR_MORE_DATA);
159c2c66affSColin Finck *pcbUrlArray = bytesNeeded;
160c2c66affSColin Finck ret = FALSE;
161c2c66affSColin Finck }
162c2c66affSColin Finck else
163c2c66affSColin Finck {
164c2c66affSColin Finck LPWSTR nextUrl;
165c2c66affSColin Finck
166c2c66affSColin Finck *pcbUrlArray = bytesNeeded;
167c2c66affSColin Finck pUrlArray->cUrl = 0;
168c2c66affSColin Finck pUrlArray->rgwszUrl =
169c2c66affSColin Finck (LPWSTR *)((BYTE *)pUrlArray + sizeof(CRYPT_URL_ARRAY));
170c2c66affSColin Finck nextUrl = (LPWSTR)((BYTE *)pUrlArray + sizeof(CRYPT_URL_ARRAY)
171c2c66affSColin Finck + cUrl * sizeof(LPWSTR));
172c2c66affSColin Finck for (i = 0; i < aia->cAccDescr; i++)
173c2c66affSColin Finck if (!strcmp(aia->rgAccDescr[i].pszAccessMethod,
174c2c66affSColin Finck szOID_PKIX_CA_ISSUERS))
175c2c66affSColin Finck {
176c2c66affSColin Finck if (aia->rgAccDescr[i].AccessLocation.dwAltNameChoice
177c2c66affSColin Finck == CERT_ALT_NAME_URL)
178c2c66affSColin Finck {
179c2c66affSColin Finck if (aia->rgAccDescr[i].AccessLocation.u.pwszURL)
180c2c66affSColin Finck {
181c2c66affSColin Finck lstrcpyW(nextUrl,
182c2c66affSColin Finck aia->rgAccDescr[i].AccessLocation.u.pwszURL);
183c2c66affSColin Finck pUrlArray->rgwszUrl[pUrlArray->cUrl++] =
184c2c66affSColin Finck nextUrl;
185c2c66affSColin Finck nextUrl += (lstrlenW(nextUrl) + 1);
186c2c66affSColin Finck }
187c2c66affSColin Finck }
188c2c66affSColin Finck }
189c2c66affSColin Finck }
190c2c66affSColin Finck if (ret)
191c2c66affSColin Finck {
192c2c66affSColin Finck if (pcbUrlInfo)
193c2c66affSColin Finck {
194c2c66affSColin Finck FIXME("url info: stub\n");
195c2c66affSColin Finck if (!pUrlInfo)
196c2c66affSColin Finck *pcbUrlInfo = sizeof(CRYPT_URL_INFO);
197c2c66affSColin Finck else if (*pcbUrlInfo < sizeof(CRYPT_URL_INFO))
198c2c66affSColin Finck {
199c2c66affSColin Finck *pcbUrlInfo = sizeof(CRYPT_URL_INFO);
200c2c66affSColin Finck SetLastError(ERROR_MORE_DATA);
201c2c66affSColin Finck ret = FALSE;
202c2c66affSColin Finck }
203c2c66affSColin Finck else
204c2c66affSColin Finck {
205c2c66affSColin Finck *pcbUrlInfo = sizeof(CRYPT_URL_INFO);
206c2c66affSColin Finck memset(pUrlInfo, 0, sizeof(CRYPT_URL_INFO));
207c2c66affSColin Finck }
208c2c66affSColin Finck }
209c2c66affSColin Finck }
210c2c66affSColin Finck LocalFree(aia);
211c2c66affSColin Finck }
212c2c66affSColin Finck }
213c2c66affSColin Finck else
214c2c66affSColin Finck SetLastError(CRYPT_E_NOT_FOUND);
215c2c66affSColin Finck return ret;
216c2c66affSColin Finck }
217c2c66affSColin Finck
CRYPT_GetUrlFromCRLDistPointsExt(const CRYPT_DATA_BLOB * value,PCRYPT_URL_ARRAY pUrlArray,DWORD * pcbUrlArray,PCRYPT_URL_INFO pUrlInfo,DWORD * pcbUrlInfo)218c2c66affSColin Finck static BOOL CRYPT_GetUrlFromCRLDistPointsExt(const CRYPT_DATA_BLOB *value,
219c2c66affSColin Finck PCRYPT_URL_ARRAY pUrlArray, DWORD *pcbUrlArray, PCRYPT_URL_INFO pUrlInfo,
220c2c66affSColin Finck DWORD *pcbUrlInfo)
221c2c66affSColin Finck {
222c2c66affSColin Finck BOOL ret;
223c2c66affSColin Finck CRL_DIST_POINTS_INFO *info;
224c2c66affSColin Finck DWORD size;
225c2c66affSColin Finck
226c2c66affSColin Finck ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CRL_DIST_POINTS,
227c2c66affSColin Finck value->pbData, value->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
228c2c66affSColin Finck if (ret)
229c2c66affSColin Finck {
230c2c66affSColin Finck DWORD i, cUrl, bytesNeeded = sizeof(CRYPT_URL_ARRAY);
231c2c66affSColin Finck
232c2c66affSColin Finck for (i = 0, cUrl = 0; i < info->cDistPoint; i++)
233c2c66affSColin Finck if (info->rgDistPoint[i].DistPointName.dwDistPointNameChoice
234c2c66affSColin Finck == CRL_DIST_POINT_FULL_NAME)
235c2c66affSColin Finck {
236c2c66affSColin Finck DWORD j;
237c2c66affSColin Finck CERT_ALT_NAME_INFO *name =
238c2c66affSColin Finck &info->rgDistPoint[i].DistPointName.u.FullName;
239c2c66affSColin Finck
240c2c66affSColin Finck for (j = 0; j < name->cAltEntry; j++)
241c2c66affSColin Finck if (name->rgAltEntry[j].dwAltNameChoice ==
242c2c66affSColin Finck CERT_ALT_NAME_URL)
243c2c66affSColin Finck {
244c2c66affSColin Finck if (name->rgAltEntry[j].u.pwszURL)
245c2c66affSColin Finck {
246c2c66affSColin Finck cUrl++;
247c2c66affSColin Finck bytesNeeded += sizeof(LPWSTR) +
248c2c66affSColin Finck (lstrlenW(name->rgAltEntry[j].u.pwszURL) + 1)
249c2c66affSColin Finck * sizeof(WCHAR);
250c2c66affSColin Finck }
251c2c66affSColin Finck }
252c2c66affSColin Finck }
253c2c66affSColin Finck if (!pcbUrlArray)
254c2c66affSColin Finck {
255c2c66affSColin Finck SetLastError(E_INVALIDARG);
256c2c66affSColin Finck ret = FALSE;
257c2c66affSColin Finck }
258c2c66affSColin Finck else if (!pUrlArray)
259c2c66affSColin Finck *pcbUrlArray = bytesNeeded;
260c2c66affSColin Finck else if (*pcbUrlArray < bytesNeeded)
261c2c66affSColin Finck {
262c2c66affSColin Finck SetLastError(ERROR_MORE_DATA);
263c2c66affSColin Finck *pcbUrlArray = bytesNeeded;
264c2c66affSColin Finck ret = FALSE;
265c2c66affSColin Finck }
266c2c66affSColin Finck else
267c2c66affSColin Finck {
268c2c66affSColin Finck LPWSTR nextUrl;
269c2c66affSColin Finck
270c2c66affSColin Finck *pcbUrlArray = bytesNeeded;
271c2c66affSColin Finck pUrlArray->cUrl = 0;
272c2c66affSColin Finck pUrlArray->rgwszUrl =
273c2c66affSColin Finck (LPWSTR *)((BYTE *)pUrlArray + sizeof(CRYPT_URL_ARRAY));
274c2c66affSColin Finck nextUrl = (LPWSTR)((BYTE *)pUrlArray + sizeof(CRYPT_URL_ARRAY)
275c2c66affSColin Finck + cUrl * sizeof(LPWSTR));
276c2c66affSColin Finck for (i = 0; i < info->cDistPoint; i++)
277c2c66affSColin Finck if (info->rgDistPoint[i].DistPointName.dwDistPointNameChoice
278c2c66affSColin Finck == CRL_DIST_POINT_FULL_NAME)
279c2c66affSColin Finck {
280c2c66affSColin Finck DWORD j;
281c2c66affSColin Finck CERT_ALT_NAME_INFO *name =
282c2c66affSColin Finck &info->rgDistPoint[i].DistPointName.u.FullName;
283c2c66affSColin Finck
284c2c66affSColin Finck for (j = 0; j < name->cAltEntry; j++)
285c2c66affSColin Finck if (name->rgAltEntry[j].dwAltNameChoice ==
286c2c66affSColin Finck CERT_ALT_NAME_URL)
287c2c66affSColin Finck {
288c2c66affSColin Finck if (name->rgAltEntry[j].u.pwszURL)
289c2c66affSColin Finck {
290c2c66affSColin Finck lstrcpyW(nextUrl,
291c2c66affSColin Finck name->rgAltEntry[j].u.pwszURL);
292c2c66affSColin Finck pUrlArray->rgwszUrl[pUrlArray->cUrl++] =
293c2c66affSColin Finck nextUrl;
294c2c66affSColin Finck nextUrl +=
295c2c66affSColin Finck (lstrlenW(name->rgAltEntry[j].u.pwszURL) + 1);
296c2c66affSColin Finck }
297c2c66affSColin Finck }
298c2c66affSColin Finck }
299c2c66affSColin Finck }
300c2c66affSColin Finck if (ret)
301c2c66affSColin Finck {
302c2c66affSColin Finck if (pcbUrlInfo)
303c2c66affSColin Finck {
304c2c66affSColin Finck FIXME("url info: stub\n");
305c2c66affSColin Finck if (!pUrlInfo)
306c2c66affSColin Finck *pcbUrlInfo = sizeof(CRYPT_URL_INFO);
307c2c66affSColin Finck else if (*pcbUrlInfo < sizeof(CRYPT_URL_INFO))
308c2c66affSColin Finck {
309c2c66affSColin Finck *pcbUrlInfo = sizeof(CRYPT_URL_INFO);
310c2c66affSColin Finck SetLastError(ERROR_MORE_DATA);
311c2c66affSColin Finck ret = FALSE;
312c2c66affSColin Finck }
313c2c66affSColin Finck else
314c2c66affSColin Finck {
315c2c66affSColin Finck *pcbUrlInfo = sizeof(CRYPT_URL_INFO);
316c2c66affSColin Finck memset(pUrlInfo, 0, sizeof(CRYPT_URL_INFO));
317c2c66affSColin Finck }
318c2c66affSColin Finck }
319c2c66affSColin Finck }
320c2c66affSColin Finck LocalFree(info);
321c2c66affSColin Finck }
322c2c66affSColin Finck return ret;
323c2c66affSColin Finck }
324c2c66affSColin Finck
CRYPT_GetUrlFromCertificateCRLDistPoint(LPCSTR pszUrlOid,LPVOID pvPara,DWORD dwFlags,PCRYPT_URL_ARRAY pUrlArray,DWORD * pcbUrlArray,PCRYPT_URL_INFO pUrlInfo,DWORD * pcbUrlInfo,LPVOID pvReserved)325c2c66affSColin Finck static BOOL WINAPI CRYPT_GetUrlFromCertificateCRLDistPoint(LPCSTR pszUrlOid,
326c2c66affSColin Finck LPVOID pvPara, DWORD dwFlags, PCRYPT_URL_ARRAY pUrlArray, DWORD *pcbUrlArray,
327c2c66affSColin Finck PCRYPT_URL_INFO pUrlInfo, DWORD *pcbUrlInfo, LPVOID pvReserved)
328c2c66affSColin Finck {
329c2c66affSColin Finck PCCERT_CONTEXT cert = pvPara;
330c2c66affSColin Finck PCERT_EXTENSION ext;
331c2c66affSColin Finck BOOL ret = FALSE;
332c2c66affSColin Finck
333c2c66affSColin Finck /* The only applicable flag is CRYPT_GET_URL_FROM_EXTENSION */
334c2c66affSColin Finck if (dwFlags && !(dwFlags & CRYPT_GET_URL_FROM_EXTENSION))
335c2c66affSColin Finck {
336c2c66affSColin Finck SetLastError(CRYPT_E_NOT_FOUND);
337c2c66affSColin Finck return FALSE;
338c2c66affSColin Finck }
339c2c66affSColin Finck if ((ext = CertFindExtension(szOID_CRL_DIST_POINTS,
340c2c66affSColin Finck cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
341c2c66affSColin Finck ret = CRYPT_GetUrlFromCRLDistPointsExt(&ext->Value, pUrlArray,
342c2c66affSColin Finck pcbUrlArray, pUrlInfo, pcbUrlInfo);
343c2c66affSColin Finck else
344c2c66affSColin Finck SetLastError(CRYPT_E_NOT_FOUND);
345c2c66affSColin Finck return ret;
346c2c66affSColin Finck }
347c2c66affSColin Finck
348c2c66affSColin Finck /***********************************************************************
349c2c66affSColin Finck * CryptGetObjectUrl (CRYPTNET.@)
350c2c66affSColin Finck */
CryptGetObjectUrl(LPCSTR pszUrlOid,LPVOID pvPara,DWORD dwFlags,PCRYPT_URL_ARRAY pUrlArray,DWORD * pcbUrlArray,PCRYPT_URL_INFO pUrlInfo,DWORD * pcbUrlInfo,LPVOID pvReserved)351c2c66affSColin Finck BOOL WINAPI CryptGetObjectUrl(LPCSTR pszUrlOid, LPVOID pvPara, DWORD dwFlags,
352c2c66affSColin Finck PCRYPT_URL_ARRAY pUrlArray, DWORD *pcbUrlArray, PCRYPT_URL_INFO pUrlInfo,
353c2c66affSColin Finck DWORD *pcbUrlInfo, LPVOID pvReserved)
354c2c66affSColin Finck {
355c2c66affSColin Finck UrlDllGetObjectUrlFunc func = NULL;
356c2c66affSColin Finck HCRYPTOIDFUNCADDR hFunc = NULL;
357c2c66affSColin Finck BOOL ret = FALSE;
358c2c66affSColin Finck
359c2c66affSColin Finck TRACE("(%s, %p, %08x, %p, %p, %p, %p, %p)\n", debugstr_a(pszUrlOid),
360c2c66affSColin Finck pvPara, dwFlags, pUrlArray, pcbUrlArray, pUrlInfo, pcbUrlInfo, pvReserved);
361c2c66affSColin Finck
362c2c66affSColin Finck if (IS_INTOID(pszUrlOid))
363c2c66affSColin Finck {
364c2c66affSColin Finck switch (LOWORD(pszUrlOid))
365c2c66affSColin Finck {
366c2c66affSColin Finck case LOWORD(URL_OID_CERTIFICATE_ISSUER):
367c2c66affSColin Finck func = CRYPT_GetUrlFromCertificateIssuer;
368c2c66affSColin Finck break;
369c2c66affSColin Finck case LOWORD(URL_OID_CERTIFICATE_CRL_DIST_POINT):
370c2c66affSColin Finck func = CRYPT_GetUrlFromCertificateCRLDistPoint;
371c2c66affSColin Finck break;
372c2c66affSColin Finck default:
373c2c66affSColin Finck FIXME("unimplemented for %s\n", url_oid_to_str(pszUrlOid));
374c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
375c2c66affSColin Finck }
376c2c66affSColin Finck }
377c2c66affSColin Finck else
378c2c66affSColin Finck {
379c2c66affSColin Finck static HCRYPTOIDFUNCSET set = NULL;
380c2c66affSColin Finck
381c2c66affSColin Finck if (!set)
382c2c66affSColin Finck set = CryptInitOIDFunctionSet(URL_OID_GET_OBJECT_URL_FUNC, 0);
383c2c66affSColin Finck CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, pszUrlOid, 0,
384c2c66affSColin Finck (void **)&func, &hFunc);
385c2c66affSColin Finck }
386c2c66affSColin Finck if (func)
387c2c66affSColin Finck ret = func(pszUrlOid, pvPara, dwFlags, pUrlArray, pcbUrlArray,
388c2c66affSColin Finck pUrlInfo, pcbUrlInfo, pvReserved);
389c2c66affSColin Finck if (hFunc)
390c2c66affSColin Finck CryptFreeOIDFunctionAddress(hFunc, 0);
391c2c66affSColin Finck return ret;
392c2c66affSColin Finck }
393c2c66affSColin Finck
394c2c66affSColin Finck /***********************************************************************
395c2c66affSColin Finck * CryptRetrieveObjectByUrlA (CRYPTNET.@)
396c2c66affSColin Finck */
CryptRetrieveObjectByUrlA(LPCSTR pszURL,LPCSTR pszObjectOid,DWORD dwRetrievalFlags,DWORD dwTimeout,LPVOID * ppvObject,HCRYPTASYNC hAsyncRetrieve,PCRYPT_CREDENTIALS pCredentials,LPVOID pvVerify,PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)397c2c66affSColin Finck BOOL WINAPI CryptRetrieveObjectByUrlA(LPCSTR pszURL, LPCSTR pszObjectOid,
398c2c66affSColin Finck DWORD dwRetrievalFlags, DWORD dwTimeout, LPVOID *ppvObject,
399c2c66affSColin Finck HCRYPTASYNC hAsyncRetrieve, PCRYPT_CREDENTIALS pCredentials, LPVOID pvVerify,
400c2c66affSColin Finck PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
401c2c66affSColin Finck {
402c2c66affSColin Finck BOOL ret = FALSE;
403c2c66affSColin Finck int len;
404c2c66affSColin Finck
405c2c66affSColin Finck TRACE("(%s, %s, %08x, %d, %p, %p, %p, %p, %p)\n", debugstr_a(pszURL),
406c2c66affSColin Finck debugstr_a(pszObjectOid), dwRetrievalFlags, dwTimeout, ppvObject,
407c2c66affSColin Finck hAsyncRetrieve, pCredentials, pvVerify, pAuxInfo);
408c2c66affSColin Finck
409c2c66affSColin Finck if (!pszURL)
410c2c66affSColin Finck {
411c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
412c2c66affSColin Finck return FALSE;
413c2c66affSColin Finck }
414c2c66affSColin Finck len = MultiByteToWideChar(CP_ACP, 0, pszURL, -1, NULL, 0);
415c2c66affSColin Finck if (len)
416c2c66affSColin Finck {
417c2c66affSColin Finck LPWSTR url = CryptMemAlloc(len * sizeof(WCHAR));
418c2c66affSColin Finck
419c2c66affSColin Finck if (url)
420c2c66affSColin Finck {
421c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, pszURL, -1, url, len);
422c2c66affSColin Finck ret = CryptRetrieveObjectByUrlW(url, pszObjectOid,
423c2c66affSColin Finck dwRetrievalFlags, dwTimeout, ppvObject, hAsyncRetrieve,
424c2c66affSColin Finck pCredentials, pvVerify, pAuxInfo);
425c2c66affSColin Finck CryptMemFree(url);
426c2c66affSColin Finck }
427c2c66affSColin Finck else
428c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
429c2c66affSColin Finck }
430c2c66affSColin Finck return ret;
431c2c66affSColin Finck }
432c2c66affSColin Finck
CRYPT_FreeBlob(LPCSTR pszObjectOid,PCRYPT_BLOB_ARRAY pObject,void * pvFreeContext)433c2c66affSColin Finck static void WINAPI CRYPT_FreeBlob(LPCSTR pszObjectOid,
434c2c66affSColin Finck PCRYPT_BLOB_ARRAY pObject, void *pvFreeContext)
435c2c66affSColin Finck {
436c2c66affSColin Finck DWORD i;
437c2c66affSColin Finck
438c2c66affSColin Finck for (i = 0; i < pObject->cBlob; i++)
439c2c66affSColin Finck CryptMemFree(pObject->rgBlob[i].pbData);
440c2c66affSColin Finck CryptMemFree(pObject->rgBlob);
441c2c66affSColin Finck }
442c2c66affSColin Finck
CRYPT_GetObjectFromFile(HANDLE hFile,PCRYPT_BLOB_ARRAY pObject)443c2c66affSColin Finck static BOOL CRYPT_GetObjectFromFile(HANDLE hFile, PCRYPT_BLOB_ARRAY pObject)
444c2c66affSColin Finck {
445c2c66affSColin Finck BOOL ret;
446c2c66affSColin Finck LARGE_INTEGER size;
447c2c66affSColin Finck
448c2c66affSColin Finck if ((ret = GetFileSizeEx(hFile, &size)))
449c2c66affSColin Finck {
450c2c66affSColin Finck if (size.u.HighPart)
451c2c66affSColin Finck {
452c2c66affSColin Finck WARN("file too big\n");
453c2c66affSColin Finck SetLastError(ERROR_INVALID_DATA);
454c2c66affSColin Finck ret = FALSE;
455c2c66affSColin Finck }
456c2c66affSColin Finck else
457c2c66affSColin Finck {
458c2c66affSColin Finck CRYPT_DATA_BLOB blob;
459c2c66affSColin Finck
460c2c66affSColin Finck blob.pbData = CryptMemAlloc(size.u.LowPart);
461c2c66affSColin Finck if (blob.pbData)
462c2c66affSColin Finck {
463c2c66affSColin Finck ret = ReadFile(hFile, blob.pbData, size.u.LowPart, &blob.cbData,
464c2c66affSColin Finck NULL);
465c2c66affSColin Finck if (ret)
466c2c66affSColin Finck {
467c2c66affSColin Finck pObject->rgBlob = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
468c2c66affSColin Finck if (pObject->rgBlob)
469c2c66affSColin Finck {
470c2c66affSColin Finck pObject->cBlob = 1;
471c2c66affSColin Finck memcpy(pObject->rgBlob, &blob, sizeof(CRYPT_DATA_BLOB));
472c2c66affSColin Finck }
473c2c66affSColin Finck else
474c2c66affSColin Finck {
475c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
476c2c66affSColin Finck ret = FALSE;
477c2c66affSColin Finck }
478c2c66affSColin Finck }
479c2c66affSColin Finck if (!ret)
480c2c66affSColin Finck CryptMemFree(blob.pbData);
481c2c66affSColin Finck }
482c2c66affSColin Finck else
483c2c66affSColin Finck {
484c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
485c2c66affSColin Finck ret = FALSE;
486c2c66affSColin Finck }
487c2c66affSColin Finck }
488c2c66affSColin Finck }
489c2c66affSColin Finck return ret;
490c2c66affSColin Finck }
491c2c66affSColin Finck
CRYPT_GetObjectFromCache(LPCWSTR pszURL,PCRYPT_BLOB_ARRAY pObject,PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)492c2c66affSColin Finck static BOOL CRYPT_GetObjectFromCache(LPCWSTR pszURL, PCRYPT_BLOB_ARRAY pObject,
493c2c66affSColin Finck PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
494c2c66affSColin Finck {
495c2c66affSColin Finck BOOL ret = FALSE;
496c2c66affSColin Finck INTERNET_CACHE_ENTRY_INFOW *pCacheInfo = NULL;
497c2c66affSColin Finck DWORD size = 0;
498c2c66affSColin Finck
499c2c66affSColin Finck TRACE("(%s, %p, %p)\n", debugstr_w(pszURL), pObject, pAuxInfo);
500c2c66affSColin Finck
501c2c66affSColin Finck RetrieveUrlCacheEntryFileW(pszURL, NULL, &size, 0);
502c2c66affSColin Finck if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
503c2c66affSColin Finck return FALSE;
504c2c66affSColin Finck
505c2c66affSColin Finck pCacheInfo = CryptMemAlloc(size);
506c2c66affSColin Finck if (!pCacheInfo)
507c2c66affSColin Finck {
508c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
509c2c66affSColin Finck return FALSE;
510c2c66affSColin Finck }
511c2c66affSColin Finck
512c2c66affSColin Finck if ((ret = RetrieveUrlCacheEntryFileW(pszURL, pCacheInfo, &size, 0)))
513c2c66affSColin Finck {
514c2c66affSColin Finck FILETIME ft;
515c2c66affSColin Finck
516c2c66affSColin Finck GetSystemTimeAsFileTime(&ft);
517c2c66affSColin Finck if (CompareFileTime(&pCacheInfo->ExpireTime, &ft) >= 0)
518c2c66affSColin Finck {
519c2c66affSColin Finck HANDLE hFile = CreateFileW(pCacheInfo->lpszLocalFileName, GENERIC_READ,
520c2c66affSColin Finck FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
521c2c66affSColin Finck
522c2c66affSColin Finck if (hFile != INVALID_HANDLE_VALUE)
523c2c66affSColin Finck {
524c2c66affSColin Finck if ((ret = CRYPT_GetObjectFromFile(hFile, pObject)))
525c2c66affSColin Finck {
526c2c66affSColin Finck if (pAuxInfo && pAuxInfo->cbSize >=
527c2c66affSColin Finck offsetof(CRYPT_RETRIEVE_AUX_INFO,
528c2c66affSColin Finck pLastSyncTime) + sizeof(PFILETIME) &&
529c2c66affSColin Finck pAuxInfo->pLastSyncTime)
530c2c66affSColin Finck memcpy(pAuxInfo->pLastSyncTime,
531c2c66affSColin Finck &pCacheInfo->LastSyncTime,
532c2c66affSColin Finck sizeof(FILETIME));
533c2c66affSColin Finck }
534c2c66affSColin Finck CloseHandle(hFile);
535c2c66affSColin Finck }
536c2c66affSColin Finck else
537c2c66affSColin Finck {
538c2c66affSColin Finck DeleteUrlCacheEntryW(pszURL);
539c2c66affSColin Finck ret = FALSE;
540c2c66affSColin Finck }
541c2c66affSColin Finck }
542c2c66affSColin Finck else
543c2c66affSColin Finck {
544c2c66affSColin Finck DeleteUrlCacheEntryW(pszURL);
545c2c66affSColin Finck ret = FALSE;
546c2c66affSColin Finck }
547c2c66affSColin Finck UnlockUrlCacheEntryFileW(pszURL, 0);
548c2c66affSColin Finck }
549c2c66affSColin Finck CryptMemFree(pCacheInfo);
550c2c66affSColin Finck TRACE("returning %d\n", ret);
551c2c66affSColin Finck return ret;
552c2c66affSColin Finck }
553c2c66affSColin Finck
554c2c66affSColin Finck /* Parses the URL, and sets components' lpszHostName and lpszUrlPath members
555c2c66affSColin Finck * to NULL-terminated copies of those portions of the URL (to be freed with
556c2c66affSColin Finck * CryptMemFree.)
557c2c66affSColin Finck */
CRYPT_CrackUrl(LPCWSTR pszURL,URL_COMPONENTSW * components)558c2c66affSColin Finck static BOOL CRYPT_CrackUrl(LPCWSTR pszURL, URL_COMPONENTSW *components)
559c2c66affSColin Finck {
560c2c66affSColin Finck BOOL ret;
561c2c66affSColin Finck
562c2c66affSColin Finck TRACE("(%s, %p)\n", debugstr_w(pszURL), components);
563c2c66affSColin Finck
564c2c66affSColin Finck memset(components, 0, sizeof(*components));
565c2c66affSColin Finck components->dwStructSize = sizeof(*components);
566c2c66affSColin Finck components->lpszHostName = CryptMemAlloc(INTERNET_MAX_HOST_NAME_LENGTH * sizeof(WCHAR));
567c2c66affSColin Finck components->dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
568c2c66affSColin Finck if (!components->lpszHostName)
569c2c66affSColin Finck {
570c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
571c2c66affSColin Finck return FALSE;
572c2c66affSColin Finck }
573c2c66affSColin Finck components->lpszUrlPath = CryptMemAlloc(INTERNET_MAX_PATH_LENGTH * sizeof(WCHAR));
574c2c66affSColin Finck components->dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
575c2c66affSColin Finck if (!components->lpszUrlPath)
576c2c66affSColin Finck {
577c2c66affSColin Finck CryptMemFree(components->lpszHostName);
578c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
579c2c66affSColin Finck return FALSE;
580c2c66affSColin Finck }
581c2c66affSColin Finck
582c2c66affSColin Finck ret = InternetCrackUrlW(pszURL, 0, ICU_DECODE, components);
583c2c66affSColin Finck if (ret)
584c2c66affSColin Finck {
585c2c66affSColin Finck switch (components->nScheme)
586c2c66affSColin Finck {
587c2c66affSColin Finck case INTERNET_SCHEME_FTP:
588c2c66affSColin Finck if (!components->nPort)
589c2c66affSColin Finck components->nPort = INTERNET_DEFAULT_FTP_PORT;
590c2c66affSColin Finck break;
591c2c66affSColin Finck case INTERNET_SCHEME_HTTP:
592c2c66affSColin Finck if (!components->nPort)
593c2c66affSColin Finck components->nPort = INTERNET_DEFAULT_HTTP_PORT;
594c2c66affSColin Finck break;
595c2c66affSColin Finck default:
596c2c66affSColin Finck ; /* do nothing */
597c2c66affSColin Finck }
598c2c66affSColin Finck }
599c2c66affSColin Finck TRACE("returning %d\n", ret);
600c2c66affSColin Finck return ret;
601c2c66affSColin Finck }
602c2c66affSColin Finck
603c2c66affSColin Finck struct InetContext
604c2c66affSColin Finck {
605c2c66affSColin Finck HANDLE event;
606c2c66affSColin Finck DWORD timeout;
607c2c66affSColin Finck DWORD error;
608c2c66affSColin Finck };
609c2c66affSColin Finck
CRYPT_MakeInetContext(DWORD dwTimeout)610c2c66affSColin Finck static struct InetContext *CRYPT_MakeInetContext(DWORD dwTimeout)
611c2c66affSColin Finck {
612c2c66affSColin Finck struct InetContext *context = CryptMemAlloc(sizeof(struct InetContext));
613c2c66affSColin Finck
614c2c66affSColin Finck if (context)
615c2c66affSColin Finck {
616c2c66affSColin Finck context->event = CreateEventW(NULL, FALSE, FALSE, NULL);
617c2c66affSColin Finck if (!context->event)
618c2c66affSColin Finck {
619c2c66affSColin Finck CryptMemFree(context);
620c2c66affSColin Finck context = NULL;
621c2c66affSColin Finck }
622c2c66affSColin Finck else
623c2c66affSColin Finck {
624c2c66affSColin Finck context->timeout = dwTimeout;
625c2c66affSColin Finck context->error = ERROR_SUCCESS;
626c2c66affSColin Finck }
627c2c66affSColin Finck }
628c2c66affSColin Finck return context;
629c2c66affSColin Finck }
630c2c66affSColin Finck
CRYPT_DownloadObject(DWORD dwRetrievalFlags,HINTERNET hHttp,struct InetContext * context,PCRYPT_BLOB_ARRAY pObject,PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)631c2c66affSColin Finck static BOOL CRYPT_DownloadObject(DWORD dwRetrievalFlags, HINTERNET hHttp,
632c2c66affSColin Finck struct InetContext *context, PCRYPT_BLOB_ARRAY pObject,
633c2c66affSColin Finck PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
634c2c66affSColin Finck {
635c2c66affSColin Finck CRYPT_DATA_BLOB object = { 0, NULL };
636c2c66affSColin Finck DWORD bytesAvailable;
637c2c66affSColin Finck BOOL ret;
638c2c66affSColin Finck
639c2c66affSColin Finck do {
640c2c66affSColin Finck if ((ret = InternetQueryDataAvailable(hHttp, &bytesAvailable, 0, 0)))
641c2c66affSColin Finck {
642c2c66affSColin Finck if (bytesAvailable)
643c2c66affSColin Finck {
644c2c66affSColin Finck if (object.pbData)
645c2c66affSColin Finck object.pbData = CryptMemRealloc(object.pbData,
646c2c66affSColin Finck object.cbData + bytesAvailable);
647c2c66affSColin Finck else
648c2c66affSColin Finck object.pbData = CryptMemAlloc(bytesAvailable);
649c2c66affSColin Finck if (object.pbData)
650c2c66affSColin Finck {
651c2c66affSColin Finck INTERNET_BUFFERSA buffer = { sizeof(buffer), 0 };
652c2c66affSColin Finck
653c2c66affSColin Finck buffer.dwBufferLength = bytesAvailable;
654c2c66affSColin Finck buffer.lpvBuffer = object.pbData + object.cbData;
655c2c66affSColin Finck if (!(ret = InternetReadFileExA(hHttp, &buffer, IRF_NO_WAIT,
656c2c66affSColin Finck (DWORD_PTR)context)))
657c2c66affSColin Finck {
658c2c66affSColin Finck if (GetLastError() == ERROR_IO_PENDING)
659c2c66affSColin Finck {
660c2c66affSColin Finck if (WaitForSingleObject(context->event,
661c2c66affSColin Finck context->timeout) == WAIT_TIMEOUT)
662c2c66affSColin Finck SetLastError(ERROR_TIMEOUT);
663c2c66affSColin Finck else if (context->error)
664c2c66affSColin Finck SetLastError(context->error);
665c2c66affSColin Finck else
666c2c66affSColin Finck ret = TRUE;
667c2c66affSColin Finck }
668c2c66affSColin Finck }
669c2c66affSColin Finck if (ret)
670c2c66affSColin Finck object.cbData += buffer.dwBufferLength;
671c2c66affSColin Finck }
672c2c66affSColin Finck else
673c2c66affSColin Finck {
674c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
675c2c66affSColin Finck ret = FALSE;
676c2c66affSColin Finck }
677c2c66affSColin Finck }
678c2c66affSColin Finck }
679c2c66affSColin Finck else if (GetLastError() == ERROR_IO_PENDING)
680c2c66affSColin Finck {
681c2c66affSColin Finck if (WaitForSingleObject(context->event, context->timeout) ==
682c2c66affSColin Finck WAIT_TIMEOUT)
683c2c66affSColin Finck SetLastError(ERROR_TIMEOUT);
684c2c66affSColin Finck else
685c2c66affSColin Finck ret = TRUE;
686c2c66affSColin Finck }
687c2c66affSColin Finck } while (ret && bytesAvailable);
688c2c66affSColin Finck if (ret)
689c2c66affSColin Finck {
690c2c66affSColin Finck pObject->rgBlob = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
691c2c66affSColin Finck if (!pObject->rgBlob)
692c2c66affSColin Finck {
693c2c66affSColin Finck CryptMemFree(object.pbData);
694c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
695c2c66affSColin Finck ret = FALSE;
696c2c66affSColin Finck }
697c2c66affSColin Finck else
698c2c66affSColin Finck {
699c2c66affSColin Finck pObject->rgBlob[0].cbData = object.cbData;
700c2c66affSColin Finck pObject->rgBlob[0].pbData = object.pbData;
701c2c66affSColin Finck pObject->cBlob = 1;
702c2c66affSColin Finck }
703c2c66affSColin Finck }
704c2c66affSColin Finck TRACE("returning %d\n", ret);
705c2c66affSColin Finck return ret;
706c2c66affSColin Finck }
707c2c66affSColin Finck
708c2c66affSColin Finck /* Finds the object specified by pszURL in the cache. If it's not found,
709c2c66affSColin Finck * creates a new cache entry for the object and writes the object to it.
710c2c66affSColin Finck * Sets the expiration time of the cache entry to expires.
711c2c66affSColin Finck */
CRYPT_CacheURL(LPCWSTR pszURL,const CRYPT_BLOB_ARRAY * pObject,DWORD dwRetrievalFlags,FILETIME expires)712c2c66affSColin Finck static void CRYPT_CacheURL(LPCWSTR pszURL, const CRYPT_BLOB_ARRAY *pObject,
713c2c66affSColin Finck DWORD dwRetrievalFlags, FILETIME expires)
714c2c66affSColin Finck {
715c2c66affSColin Finck WCHAR cacheFileName[MAX_PATH];
716c2c66affSColin Finck HANDLE hCacheFile;
717c2c66affSColin Finck DWORD size = 0, entryType;
718c2c66affSColin Finck FILETIME ft;
719c2c66affSColin Finck
720c2c66affSColin Finck GetUrlCacheEntryInfoW(pszURL, NULL, &size);
721c2c66affSColin Finck if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
722c2c66affSColin Finck {
723c2c66affSColin Finck INTERNET_CACHE_ENTRY_INFOW *info = CryptMemAlloc(size);
724c2c66affSColin Finck
725c2c66affSColin Finck if (!info)
726c2c66affSColin Finck {
727c2c66affSColin Finck ERR("out of memory\n");
728c2c66affSColin Finck return;
729c2c66affSColin Finck }
730c2c66affSColin Finck
731c2c66affSColin Finck if (GetUrlCacheEntryInfoW(pszURL, info, &size))
732c2c66affSColin Finck {
733c2c66affSColin Finck lstrcpyW(cacheFileName, info->lpszLocalFileName);
734c2c66affSColin Finck /* Check if the existing cache entry is up to date. If it isn't,
735c2c66affSColin Finck * remove the existing cache entry, and create a new one with the
736c2c66affSColin Finck * new value.
737c2c66affSColin Finck */
738c2c66affSColin Finck GetSystemTimeAsFileTime(&ft);
739c2c66affSColin Finck if (CompareFileTime(&info->ExpireTime, &ft) < 0)
740c2c66affSColin Finck {
741c2c66affSColin Finck DeleteUrlCacheEntryW(pszURL);
742c2c66affSColin Finck }
743c2c66affSColin Finck else
744c2c66affSColin Finck {
745c2c66affSColin Finck info->ExpireTime = expires;
746c2c66affSColin Finck SetUrlCacheEntryInfoW(pszURL, info, CACHE_ENTRY_EXPTIME_FC);
747c2c66affSColin Finck CryptMemFree(info);
748c2c66affSColin Finck return;
749c2c66affSColin Finck }
750c2c66affSColin Finck }
751c2c66affSColin Finck CryptMemFree(info);
752c2c66affSColin Finck }
753c2c66affSColin Finck
754c2c66affSColin Finck if (!CreateUrlCacheEntryW(pszURL, pObject->rgBlob[0].cbData, NULL, cacheFileName, 0))
755c2c66affSColin Finck return;
756c2c66affSColin Finck
757c2c66affSColin Finck hCacheFile = CreateFileW(cacheFileName, GENERIC_WRITE, 0,
758c2c66affSColin Finck NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
759c2c66affSColin Finck if(hCacheFile == INVALID_HANDLE_VALUE)
760c2c66affSColin Finck return;
761c2c66affSColin Finck
762c2c66affSColin Finck WriteFile(hCacheFile, pObject->rgBlob[0].pbData,
763c2c66affSColin Finck pObject->rgBlob[0].cbData, &size, NULL);
764c2c66affSColin Finck CloseHandle(hCacheFile);
765c2c66affSColin Finck
766c2c66affSColin Finck if (!(dwRetrievalFlags & CRYPT_STICKY_CACHE_RETRIEVAL))
767c2c66affSColin Finck entryType = NORMAL_CACHE_ENTRY;
768c2c66affSColin Finck else
769c2c66affSColin Finck entryType = STICKY_CACHE_ENTRY;
770c2c66affSColin Finck memset(&ft, 0, sizeof(ft));
771c2c66affSColin Finck CommitUrlCacheEntryW(pszURL, cacheFileName, expires, ft, entryType,
772c2c66affSColin Finck NULL, 0, NULL, NULL);
773c2c66affSColin Finck }
774c2c66affSColin Finck
CRYPT_InetStatusCallback(HINTERNET hInt,DWORD_PTR dwContext,DWORD status,void * statusInfo,DWORD statusInfoLen)775c2c66affSColin Finck static void CALLBACK CRYPT_InetStatusCallback(HINTERNET hInt,
776c2c66affSColin Finck DWORD_PTR dwContext, DWORD status, void *statusInfo, DWORD statusInfoLen)
777c2c66affSColin Finck {
778c2c66affSColin Finck struct InetContext *context = (struct InetContext *)dwContext;
779c2c66affSColin Finck LPINTERNET_ASYNC_RESULT result;
780c2c66affSColin Finck
781c2c66affSColin Finck switch (status)
782c2c66affSColin Finck {
783c2c66affSColin Finck case INTERNET_STATUS_REQUEST_COMPLETE:
784c2c66affSColin Finck result = statusInfo;
785c2c66affSColin Finck context->error = result->dwError;
786c2c66affSColin Finck SetEvent(context->event);
787c2c66affSColin Finck }
788c2c66affSColin Finck }
789c2c66affSColin Finck
CRYPT_Connect(const URL_COMPONENTSW * components,struct InetContext * context,PCRYPT_CREDENTIALS pCredentials,HINTERNET * phInt,HINTERNET * phHost)790c2c66affSColin Finck static BOOL CRYPT_Connect(const URL_COMPONENTSW *components,
791c2c66affSColin Finck struct InetContext *context, PCRYPT_CREDENTIALS pCredentials,
792c2c66affSColin Finck HINTERNET *phInt, HINTERNET *phHost)
793c2c66affSColin Finck {
794c2c66affSColin Finck BOOL ret;
795c2c66affSColin Finck
796c2c66affSColin Finck TRACE("(%s:%d, %p, %p, %p, %p)\n", debugstr_w(components->lpszHostName),
797c2c66affSColin Finck components->nPort, context, pCredentials, phInt, phInt);
798c2c66affSColin Finck
799c2c66affSColin Finck *phHost = NULL;
800c2c66affSColin Finck *phInt = InternetOpenW(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL,
801c2c66affSColin Finck context ? INTERNET_FLAG_ASYNC : 0);
802c2c66affSColin Finck if (*phInt)
803c2c66affSColin Finck {
804c2c66affSColin Finck DWORD service;
805c2c66affSColin Finck
806c2c66affSColin Finck if (context)
807c2c66affSColin Finck InternetSetStatusCallbackW(*phInt, CRYPT_InetStatusCallback);
808c2c66affSColin Finck switch (components->nScheme)
809c2c66affSColin Finck {
810c2c66affSColin Finck case INTERNET_SCHEME_FTP:
811c2c66affSColin Finck service = INTERNET_SERVICE_FTP;
812c2c66affSColin Finck break;
813c2c66affSColin Finck case INTERNET_SCHEME_HTTP:
814c2c66affSColin Finck service = INTERNET_SERVICE_HTTP;
815c2c66affSColin Finck break;
816c2c66affSColin Finck default:
817c2c66affSColin Finck service = 0;
818c2c66affSColin Finck }
819c2c66affSColin Finck /* FIXME: use pCredentials for username/password */
820c2c66affSColin Finck *phHost = InternetConnectW(*phInt, components->lpszHostName,
821c2c66affSColin Finck components->nPort, NULL, NULL, service, 0, (DWORD_PTR)context);
822c2c66affSColin Finck if (!*phHost)
823c2c66affSColin Finck {
824c2c66affSColin Finck InternetCloseHandle(*phInt);
825c2c66affSColin Finck *phInt = NULL;
826c2c66affSColin Finck ret = FALSE;
827c2c66affSColin Finck }
828c2c66affSColin Finck else
829c2c66affSColin Finck ret = TRUE;
830c2c66affSColin Finck }
831c2c66affSColin Finck else
832c2c66affSColin Finck ret = FALSE;
833c2c66affSColin Finck TRACE("returning %d\n", ret);
834c2c66affSColin Finck return ret;
835c2c66affSColin Finck }
836c2c66affSColin Finck
FTP_RetrieveEncodedObjectW(LPCWSTR pszURL,LPCSTR pszObjectOid,DWORD dwRetrievalFlags,DWORD dwTimeout,PCRYPT_BLOB_ARRAY pObject,PFN_FREE_ENCODED_OBJECT_FUNC * ppfnFreeObject,void ** ppvFreeContext,HCRYPTASYNC hAsyncRetrieve,PCRYPT_CREDENTIALS pCredentials,PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)837c2c66affSColin Finck static BOOL WINAPI FTP_RetrieveEncodedObjectW(LPCWSTR pszURL,
838c2c66affSColin Finck LPCSTR pszObjectOid, DWORD dwRetrievalFlags, DWORD dwTimeout,
839c2c66affSColin Finck PCRYPT_BLOB_ARRAY pObject, PFN_FREE_ENCODED_OBJECT_FUNC *ppfnFreeObject,
840c2c66affSColin Finck void **ppvFreeContext, HCRYPTASYNC hAsyncRetrieve,
841c2c66affSColin Finck PCRYPT_CREDENTIALS pCredentials, PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
842c2c66affSColin Finck {
843c2c66affSColin Finck FIXME("(%s, %s, %08x, %d, %p, %p, %p, %p, %p, %p)\n", debugstr_w(pszURL),
844c2c66affSColin Finck debugstr_a(pszObjectOid), dwRetrievalFlags, dwTimeout, pObject,
845c2c66affSColin Finck ppfnFreeObject, ppvFreeContext, hAsyncRetrieve, pCredentials, pAuxInfo);
846c2c66affSColin Finck
847c2c66affSColin Finck pObject->cBlob = 0;
848c2c66affSColin Finck pObject->rgBlob = NULL;
849c2c66affSColin Finck *ppfnFreeObject = CRYPT_FreeBlob;
850c2c66affSColin Finck *ppvFreeContext = NULL;
851c2c66affSColin Finck return FALSE;
852c2c66affSColin Finck }
853c2c66affSColin Finck
854c2c66affSColin Finck static const WCHAR x509cacert[] = { 'a','p','p','l','i','c','a','t','i','o','n',
855c2c66affSColin Finck '/','x','-','x','5','0','9','-','c','a','-','c','e','r','t',0 };
856c2c66affSColin Finck static const WCHAR x509emailcert[] = { 'a','p','p','l','i','c','a','t','i','o',
857c2c66affSColin Finck 'n','/','x','-','x','5','0','9','-','e','m','a','i','l','-','c','e','r','t',
858c2c66affSColin Finck 0 };
859c2c66affSColin Finck static const WCHAR x509servercert[] = { 'a','p','p','l','i','c','a','t','i','o',
860c2c66affSColin Finck 'n','/','x','-','x','5','0','9','-','s','e','r','v','e','r','-','c','e','r',
861c2c66affSColin Finck 't',0 };
862c2c66affSColin Finck static const WCHAR x509usercert[] = { 'a','p','p','l','i','c','a','t','i','o',
863c2c66affSColin Finck 'n','/','x','-','x','5','0','9','-','u','s','e','r','-','c','e','r','t',0 };
864c2c66affSColin Finck static const WCHAR pkcs7cert[] = { 'a','p','p','l','i','c','a','t','i','o','n',
865c2c66affSColin Finck '/','x','-','p','k','c','s','7','-','c','e','r','t','i','f','c','a','t','e',
866c2c66affSColin Finck 's',0 };
867c2c66affSColin Finck static const WCHAR pkixCRL[] = { 'a','p','p','l','i','c','a','t','i','o','n',
868c2c66affSColin Finck '/','p','k','i','x','-','c','r','l',0 };
869c2c66affSColin Finck static const WCHAR pkcs7CRL[] = { 'a','p','p','l','i','c','a','t','i','o','n',
870c2c66affSColin Finck '/','x','-','p','k','c','s','7','-','c','r','l',0 };
871c2c66affSColin Finck static const WCHAR pkcs7sig[] = { 'a','p','p','l','i','c','a','t','i','o','n',
872c2c66affSColin Finck '/','x','-','p','k','c','s','7','-','s','i','g','n','a','t','u','r','e',0 };
873c2c66affSColin Finck static const WCHAR pkcs7mime[] = { 'a','p','p','l','i','c','a','t','i','o','n',
874c2c66affSColin Finck '/','x','-','p','k','c','s','7','-','m','i','m','e',0 };
875c2c66affSColin Finck
HTTP_RetrieveEncodedObjectW(LPCWSTR pszURL,LPCSTR pszObjectOid,DWORD dwRetrievalFlags,DWORD dwTimeout,PCRYPT_BLOB_ARRAY pObject,PFN_FREE_ENCODED_OBJECT_FUNC * ppfnFreeObject,void ** ppvFreeContext,HCRYPTASYNC hAsyncRetrieve,PCRYPT_CREDENTIALS pCredentials,PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)876c2c66affSColin Finck static BOOL WINAPI HTTP_RetrieveEncodedObjectW(LPCWSTR pszURL,
877c2c66affSColin Finck LPCSTR pszObjectOid, DWORD dwRetrievalFlags, DWORD dwTimeout,
878c2c66affSColin Finck PCRYPT_BLOB_ARRAY pObject, PFN_FREE_ENCODED_OBJECT_FUNC *ppfnFreeObject,
879c2c66affSColin Finck void **ppvFreeContext, HCRYPTASYNC hAsyncRetrieve,
880c2c66affSColin Finck PCRYPT_CREDENTIALS pCredentials, PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
881c2c66affSColin Finck {
882c2c66affSColin Finck BOOL ret = FALSE;
883c2c66affSColin Finck
884c2c66affSColin Finck TRACE("(%s, %s, %08x, %d, %p, %p, %p, %p, %p, %p)\n", debugstr_w(pszURL),
885c2c66affSColin Finck debugstr_a(pszObjectOid), dwRetrievalFlags, dwTimeout, pObject,
886c2c66affSColin Finck ppfnFreeObject, ppvFreeContext, hAsyncRetrieve, pCredentials, pAuxInfo);
887c2c66affSColin Finck
888c2c66affSColin Finck pObject->cBlob = 0;
889c2c66affSColin Finck pObject->rgBlob = NULL;
890c2c66affSColin Finck *ppfnFreeObject = CRYPT_FreeBlob;
891c2c66affSColin Finck *ppvFreeContext = NULL;
892c2c66affSColin Finck
893c2c66affSColin Finck if (!(dwRetrievalFlags & CRYPT_WIRE_ONLY_RETRIEVAL))
894c2c66affSColin Finck ret = CRYPT_GetObjectFromCache(pszURL, pObject, pAuxInfo);
895c2c66affSColin Finck if (!ret && (!(dwRetrievalFlags & CRYPT_CACHE_ONLY_RETRIEVAL) ||
896c2c66affSColin Finck (dwRetrievalFlags & CRYPT_WIRE_ONLY_RETRIEVAL)))
897c2c66affSColin Finck {
898c2c66affSColin Finck URL_COMPONENTSW components;
899c2c66affSColin Finck
900c2c66affSColin Finck if ((ret = CRYPT_CrackUrl(pszURL, &components)))
901c2c66affSColin Finck {
902c2c66affSColin Finck HINTERNET hInt, hHost;
903c2c66affSColin Finck struct InetContext *context = NULL;
904c2c66affSColin Finck
905c2c66affSColin Finck if (dwTimeout)
906c2c66affSColin Finck context = CRYPT_MakeInetContext(dwTimeout);
907c2c66affSColin Finck ret = CRYPT_Connect(&components, context, pCredentials, &hInt,
908c2c66affSColin Finck &hHost);
909c2c66affSColin Finck if (ret)
910c2c66affSColin Finck {
911c2c66affSColin Finck static LPCWSTR types[] = { x509cacert, x509emailcert,
912c2c66affSColin Finck x509servercert, x509usercert, pkcs7cert, pkixCRL, pkcs7CRL,
913c2c66affSColin Finck pkcs7sig, pkcs7mime, NULL };
914c2c66affSColin Finck HINTERNET hHttp = HttpOpenRequestW(hHost, NULL,
915c2c66affSColin Finck components.lpszUrlPath, NULL, NULL, types,
916c2c66affSColin Finck INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI,
917c2c66affSColin Finck (DWORD_PTR)context);
918c2c66affSColin Finck
919c2c66affSColin Finck if (hHttp)
920c2c66affSColin Finck {
921c2c66affSColin Finck if (dwTimeout)
922c2c66affSColin Finck {
923c2c66affSColin Finck InternetSetOptionW(hHttp,
924c2c66affSColin Finck INTERNET_OPTION_RECEIVE_TIMEOUT, &dwTimeout,
925c2c66affSColin Finck sizeof(dwTimeout));
926c2c66affSColin Finck InternetSetOptionW(hHttp, INTERNET_OPTION_SEND_TIMEOUT,
927c2c66affSColin Finck &dwTimeout, sizeof(dwTimeout));
928c2c66affSColin Finck }
929c2c66affSColin Finck ret = HttpSendRequestExW(hHttp, NULL, NULL, 0,
930c2c66affSColin Finck (DWORD_PTR)context);
931c2c66affSColin Finck if (!ret && GetLastError() == ERROR_IO_PENDING)
932c2c66affSColin Finck {
933c2c66affSColin Finck if (WaitForSingleObject(context->event,
934c2c66affSColin Finck context->timeout) == WAIT_TIMEOUT)
935c2c66affSColin Finck SetLastError(ERROR_TIMEOUT);
936c2c66affSColin Finck else
937c2c66affSColin Finck ret = TRUE;
938c2c66affSColin Finck }
939c2c66affSColin Finck if (ret &&
940c2c66affSColin Finck !(ret = HttpEndRequestW(hHttp, NULL, 0, (DWORD_PTR)context)) &&
941c2c66affSColin Finck GetLastError() == ERROR_IO_PENDING)
942c2c66affSColin Finck {
943c2c66affSColin Finck if (WaitForSingleObject(context->event,
944c2c66affSColin Finck context->timeout) == WAIT_TIMEOUT)
945c2c66affSColin Finck SetLastError(ERROR_TIMEOUT);
946c2c66affSColin Finck else
947c2c66affSColin Finck ret = TRUE;
948c2c66affSColin Finck }
949c2c66affSColin Finck if (ret)
950c2c66affSColin Finck ret = CRYPT_DownloadObject(dwRetrievalFlags, hHttp,
951c2c66affSColin Finck context, pObject, pAuxInfo);
952c2c66affSColin Finck if (ret && !(dwRetrievalFlags & CRYPT_DONT_CACHE_RESULT))
953c2c66affSColin Finck {
954c2c66affSColin Finck SYSTEMTIME st;
955c2c66affSColin Finck FILETIME ft;
956c2c66affSColin Finck DWORD len = sizeof(st);
957c2c66affSColin Finck
958c2c66affSColin Finck if (HttpQueryInfoW(hHttp, HTTP_QUERY_EXPIRES | HTTP_QUERY_FLAG_SYSTEMTIME,
959c2c66affSColin Finck &st, &len, NULL) && SystemTimeToFileTime(&st, &ft))
960c2c66affSColin Finck CRYPT_CacheURL(pszURL, pObject, dwRetrievalFlags, ft);
961c2c66affSColin Finck }
962c2c66affSColin Finck InternetCloseHandle(hHttp);
963c2c66affSColin Finck }
964c2c66affSColin Finck InternetCloseHandle(hHost);
965c2c66affSColin Finck InternetCloseHandle(hInt);
966c2c66affSColin Finck }
967c2c66affSColin Finck if (context)
968c2c66affSColin Finck {
969c2c66affSColin Finck CloseHandle(context->event);
970c2c66affSColin Finck CryptMemFree(context);
971c2c66affSColin Finck }
972c2c66affSColin Finck CryptMemFree(components.lpszUrlPath);
973c2c66affSColin Finck CryptMemFree(components.lpszHostName);
974c2c66affSColin Finck }
975c2c66affSColin Finck }
976c2c66affSColin Finck TRACE("returning %d\n", ret);
977c2c66affSColin Finck return ret;
978c2c66affSColin Finck }
979c2c66affSColin Finck
File_RetrieveEncodedObjectW(LPCWSTR pszURL,LPCSTR pszObjectOid,DWORD dwRetrievalFlags,DWORD dwTimeout,PCRYPT_BLOB_ARRAY pObject,PFN_FREE_ENCODED_OBJECT_FUNC * ppfnFreeObject,void ** ppvFreeContext,HCRYPTASYNC hAsyncRetrieve,PCRYPT_CREDENTIALS pCredentials,PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)980c2c66affSColin Finck static BOOL WINAPI File_RetrieveEncodedObjectW(LPCWSTR pszURL,
981c2c66affSColin Finck LPCSTR pszObjectOid, DWORD dwRetrievalFlags, DWORD dwTimeout,
982c2c66affSColin Finck PCRYPT_BLOB_ARRAY pObject, PFN_FREE_ENCODED_OBJECT_FUNC *ppfnFreeObject,
983c2c66affSColin Finck void **ppvFreeContext, HCRYPTASYNC hAsyncRetrieve,
984c2c66affSColin Finck PCRYPT_CREDENTIALS pCredentials, PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
985c2c66affSColin Finck {
986c2c66affSColin Finck URL_COMPONENTSW components = { sizeof(components), 0 };
987c2c66affSColin Finck BOOL ret;
988c2c66affSColin Finck
989c2c66affSColin Finck TRACE("(%s, %s, %08x, %d, %p, %p, %p, %p, %p, %p)\n", debugstr_w(pszURL),
990c2c66affSColin Finck debugstr_a(pszObjectOid), dwRetrievalFlags, dwTimeout, pObject,
991c2c66affSColin Finck ppfnFreeObject, ppvFreeContext, hAsyncRetrieve, pCredentials, pAuxInfo);
992c2c66affSColin Finck
993c2c66affSColin Finck pObject->cBlob = 0;
994c2c66affSColin Finck pObject->rgBlob = NULL;
995c2c66affSColin Finck *ppfnFreeObject = CRYPT_FreeBlob;
996c2c66affSColin Finck *ppvFreeContext = NULL;
997c2c66affSColin Finck
998c2c66affSColin Finck components.lpszUrlPath = CryptMemAlloc(INTERNET_MAX_PATH_LENGTH * sizeof(WCHAR));
999c2c66affSColin Finck components.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
1000c2c66affSColin Finck if (!components.lpszUrlPath)
1001c2c66affSColin Finck {
1002c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
1003c2c66affSColin Finck return FALSE;
1004c2c66affSColin Finck }
1005c2c66affSColin Finck
1006c2c66affSColin Finck ret = InternetCrackUrlW(pszURL, 0, ICU_DECODE, &components);
1007c2c66affSColin Finck if (ret)
1008c2c66affSColin Finck {
1009c2c66affSColin Finck LPWSTR path;
1010c2c66affSColin Finck
1011c2c66affSColin Finck /* 3 == lstrlenW(L"c:") + 1 */
1012c2c66affSColin Finck path = CryptMemAlloc((components.dwUrlPathLength + 3) * sizeof(WCHAR));
1013c2c66affSColin Finck if (path)
1014c2c66affSColin Finck {
1015c2c66affSColin Finck HANDLE hFile;
1016c2c66affSColin Finck
1017c2c66affSColin Finck /* Try to create the file directly - Wine handles / in pathnames */
1018c2c66affSColin Finck lstrcpynW(path, components.lpszUrlPath,
1019c2c66affSColin Finck components.dwUrlPathLength + 1);
1020c2c66affSColin Finck hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
1021c2c66affSColin Finck NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1022c2c66affSColin Finck #ifdef __REACTOS__
1023c2c66affSColin Finck if ((hFile == INVALID_HANDLE_VALUE) && (lstrlenW(components.lpszUrlPath) > 1) && (components.lpszUrlPath[1] != ':'))
1024c2c66affSColin Finck #else
1025c2c66affSColin Finck if (hFile == INVALID_HANDLE_VALUE)
1026c2c66affSColin Finck #endif
1027c2c66affSColin Finck {
1028c2c66affSColin Finck /* Try again on the current drive */
1029c2c66affSColin Finck GetCurrentDirectoryW(components.dwUrlPathLength, path);
1030c2c66affSColin Finck if (path[1] == ':')
1031c2c66affSColin Finck {
1032c2c66affSColin Finck lstrcpynW(path + 2, components.lpszUrlPath,
1033c2c66affSColin Finck components.dwUrlPathLength + 1);
1034c2c66affSColin Finck hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
1035c2c66affSColin Finck NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1036c2c66affSColin Finck }
1037c2c66affSColin Finck if (hFile == INVALID_HANDLE_VALUE)
1038c2c66affSColin Finck {
1039c2c66affSColin Finck /* Try again on the Windows drive */
1040c2c66affSColin Finck GetWindowsDirectoryW(path, components.dwUrlPathLength);
1041c2c66affSColin Finck if (path[1] == ':')
1042c2c66affSColin Finck {
1043c2c66affSColin Finck lstrcpynW(path + 2, components.lpszUrlPath,
1044c2c66affSColin Finck components.dwUrlPathLength + 1);
1045c2c66affSColin Finck hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
1046c2c66affSColin Finck NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1047c2c66affSColin Finck }
1048c2c66affSColin Finck }
1049c2c66affSColin Finck }
1050c2c66affSColin Finck if (hFile != INVALID_HANDLE_VALUE)
1051c2c66affSColin Finck {
1052c2c66affSColin Finck if ((ret = CRYPT_GetObjectFromFile(hFile, pObject)))
1053c2c66affSColin Finck {
1054c2c66affSColin Finck if (pAuxInfo && pAuxInfo->cbSize >=
1055c2c66affSColin Finck offsetof(CRYPT_RETRIEVE_AUX_INFO,
1056c2c66affSColin Finck pLastSyncTime) + sizeof(PFILETIME) &&
1057c2c66affSColin Finck pAuxInfo->pLastSyncTime)
1058c2c66affSColin Finck GetFileTime(hFile, NULL, NULL,
1059c2c66affSColin Finck pAuxInfo->pLastSyncTime);
1060c2c66affSColin Finck }
1061c2c66affSColin Finck CloseHandle(hFile);
1062c2c66affSColin Finck }
1063c2c66affSColin Finck else
1064c2c66affSColin Finck ret = FALSE;
1065c2c66affSColin Finck CryptMemFree(path);
1066c2c66affSColin Finck }
1067c2c66affSColin Finck else
1068c2c66affSColin Finck {
1069c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
1070c2c66affSColin Finck ret = FALSE;
1071c2c66affSColin Finck }
1072c2c66affSColin Finck }
1073c2c66affSColin Finck CryptMemFree(components.lpszUrlPath);
1074c2c66affSColin Finck return ret;
1075c2c66affSColin Finck }
1076c2c66affSColin Finck
1077c2c66affSColin Finck typedef BOOL (WINAPI *SchemeDllRetrieveEncodedObjectW)(LPCWSTR pwszUrl,
1078c2c66affSColin Finck LPCSTR pszObjectOid, DWORD dwRetrievalFlags, DWORD dwTimeout,
1079c2c66affSColin Finck PCRYPT_BLOB_ARRAY pObject, PFN_FREE_ENCODED_OBJECT_FUNC *ppfnFreeObject,
1080c2c66affSColin Finck void **ppvFreeContext, HCRYPTASYNC hAsyncRetrieve,
1081c2c66affSColin Finck PCRYPT_CREDENTIALS pCredentials, PCRYPT_RETRIEVE_AUX_INFO pAuxInfo);
1082c2c66affSColin Finck
CRYPT_GetRetrieveFunction(LPCWSTR pszURL,SchemeDllRetrieveEncodedObjectW * pFunc,HCRYPTOIDFUNCADDR * phFunc)1083c2c66affSColin Finck static BOOL CRYPT_GetRetrieveFunction(LPCWSTR pszURL,
1084c2c66affSColin Finck SchemeDllRetrieveEncodedObjectW *pFunc, HCRYPTOIDFUNCADDR *phFunc)
1085c2c66affSColin Finck {
1086c2c66affSColin Finck URL_COMPONENTSW components = { sizeof(components), 0 };
1087c2c66affSColin Finck BOOL ret;
1088c2c66affSColin Finck
1089c2c66affSColin Finck TRACE("(%s, %p, %p)\n", debugstr_w(pszURL), pFunc, phFunc);
1090c2c66affSColin Finck
1091c2c66affSColin Finck *pFunc = NULL;
1092c2c66affSColin Finck *phFunc = 0;
1093c2c66affSColin Finck components.dwSchemeLength = 1;
1094c2c66affSColin Finck ret = InternetCrackUrlW(pszURL, 0, 0, &components);
1095c2c66affSColin Finck if (ret)
1096c2c66affSColin Finck {
1097c2c66affSColin Finck /* Microsoft always uses CryptInitOIDFunctionSet/
1098c2c66affSColin Finck * CryptGetOIDFunctionAddress, but there doesn't seem to be a pressing
1099c2c66affSColin Finck * reason to do so for builtin schemes.
1100c2c66affSColin Finck */
1101c2c66affSColin Finck switch (components.nScheme)
1102c2c66affSColin Finck {
1103c2c66affSColin Finck case INTERNET_SCHEME_FTP:
1104c2c66affSColin Finck *pFunc = FTP_RetrieveEncodedObjectW;
1105c2c66affSColin Finck break;
1106c2c66affSColin Finck case INTERNET_SCHEME_HTTP:
1107c2c66affSColin Finck *pFunc = HTTP_RetrieveEncodedObjectW;
1108c2c66affSColin Finck break;
1109c2c66affSColin Finck case INTERNET_SCHEME_FILE:
1110c2c66affSColin Finck *pFunc = File_RetrieveEncodedObjectW;
1111c2c66affSColin Finck break;
1112c2c66affSColin Finck default:
1113c2c66affSColin Finck {
1114c2c66affSColin Finck int len = WideCharToMultiByte(CP_ACP, 0, components.lpszScheme,
1115c2c66affSColin Finck components.dwSchemeLength, NULL, 0, NULL, NULL);
1116c2c66affSColin Finck
1117c2c66affSColin Finck if (len)
1118c2c66affSColin Finck {
1119c2c66affSColin Finck LPSTR scheme = CryptMemAlloc(len);
1120c2c66affSColin Finck
1121c2c66affSColin Finck if (scheme)
1122c2c66affSColin Finck {
1123c2c66affSColin Finck static HCRYPTOIDFUNCSET set = NULL;
1124c2c66affSColin Finck
1125c2c66affSColin Finck if (!set)
1126c2c66affSColin Finck set = CryptInitOIDFunctionSet(
1127c2c66affSColin Finck SCHEME_OID_RETRIEVE_ENCODED_OBJECTW_FUNC, 0);
1128c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, components.lpszScheme,
1129c2c66affSColin Finck components.dwSchemeLength, scheme, len, NULL, NULL);
1130c2c66affSColin Finck ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING,
1131c2c66affSColin Finck scheme, 0, (void **)pFunc, phFunc);
1132c2c66affSColin Finck CryptMemFree(scheme);
1133c2c66affSColin Finck }
1134c2c66affSColin Finck else
1135c2c66affSColin Finck {
1136c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
1137c2c66affSColin Finck ret = FALSE;
1138c2c66affSColin Finck }
1139c2c66affSColin Finck }
1140c2c66affSColin Finck else
1141c2c66affSColin Finck ret = FALSE;
1142c2c66affSColin Finck }
1143c2c66affSColin Finck }
1144c2c66affSColin Finck }
1145c2c66affSColin Finck TRACE("returning %d\n", ret);
1146c2c66affSColin Finck return ret;
1147c2c66affSColin Finck }
1148c2c66affSColin Finck
CRYPT_CreateBlob(LPCSTR pszObjectOid,DWORD dwRetrievalFlags,const CRYPT_BLOB_ARRAY * pObject,void ** ppvContext)1149c2c66affSColin Finck static BOOL WINAPI CRYPT_CreateBlob(LPCSTR pszObjectOid,
1150c2c66affSColin Finck DWORD dwRetrievalFlags, const CRYPT_BLOB_ARRAY *pObject, void **ppvContext)
1151c2c66affSColin Finck {
1152c2c66affSColin Finck DWORD size, i;
1153c2c66affSColin Finck CRYPT_BLOB_ARRAY *context;
1154c2c66affSColin Finck BOOL ret = FALSE;
1155c2c66affSColin Finck
1156c2c66affSColin Finck size = sizeof(CRYPT_BLOB_ARRAY) + pObject->cBlob * sizeof(CRYPT_DATA_BLOB);
1157c2c66affSColin Finck for (i = 0; i < pObject->cBlob; i++)
1158c2c66affSColin Finck size += pObject->rgBlob[i].cbData;
1159c2c66affSColin Finck context = CryptMemAlloc(size);
1160c2c66affSColin Finck if (context)
1161c2c66affSColin Finck {
1162c2c66affSColin Finck LPBYTE nextData;
1163c2c66affSColin Finck
1164c2c66affSColin Finck context->cBlob = 0;
1165c2c66affSColin Finck context->rgBlob =
1166c2c66affSColin Finck (CRYPT_DATA_BLOB *)((LPBYTE)context + sizeof(CRYPT_BLOB_ARRAY));
1167c2c66affSColin Finck nextData =
1168c2c66affSColin Finck (LPBYTE)context->rgBlob + pObject->cBlob * sizeof(CRYPT_DATA_BLOB);
1169c2c66affSColin Finck for (i = 0; i < pObject->cBlob; i++)
1170c2c66affSColin Finck {
1171c2c66affSColin Finck memcpy(nextData, pObject->rgBlob[i].pbData,
1172c2c66affSColin Finck pObject->rgBlob[i].cbData);
1173c2c66affSColin Finck context->rgBlob[i].pbData = nextData;
1174c2c66affSColin Finck context->rgBlob[i].cbData = pObject->rgBlob[i].cbData;
1175c2c66affSColin Finck nextData += pObject->rgBlob[i].cbData;
1176c2c66affSColin Finck context->cBlob++;
1177c2c66affSColin Finck }
1178c2c66affSColin Finck *ppvContext = context;
1179c2c66affSColin Finck ret = TRUE;
1180c2c66affSColin Finck }
1181c2c66affSColin Finck return ret;
1182c2c66affSColin Finck }
1183c2c66affSColin Finck
1184c2c66affSColin Finck typedef BOOL (WINAPI *AddContextToStore)(HCERTSTORE hCertStore,
1185c2c66affSColin Finck const void *pContext, DWORD dwAddDisposition, const void **ppStoreContext);
1186c2c66affSColin Finck
decode_base64_blob(const CRYPT_DATA_BLOB * in,CRYPT_DATA_BLOB * out)1187c2c66affSColin Finck static BOOL decode_base64_blob( const CRYPT_DATA_BLOB *in, CRYPT_DATA_BLOB *out )
1188c2c66affSColin Finck {
1189c2c66affSColin Finck BOOL ret;
1190c2c66affSColin Finck DWORD len = in->cbData;
1191c2c66affSColin Finck
1192c2c66affSColin Finck while (len && !in->pbData[len - 1]) len--;
1193c2c66affSColin Finck if (!CryptStringToBinaryA( (char *)in->pbData, len, CRYPT_STRING_BASE64_ANY,
1194c2c66affSColin Finck NULL, &out->cbData, NULL, NULL )) return FALSE;
1195c2c66affSColin Finck
1196c2c66affSColin Finck if (!(out->pbData = CryptMemAlloc( out->cbData ))) return FALSE;
1197c2c66affSColin Finck ret = CryptStringToBinaryA( (char *)in->pbData, len, CRYPT_STRING_BASE64_ANY,
1198c2c66affSColin Finck out->pbData, &out->cbData, NULL, NULL );
1199c2c66affSColin Finck if (!ret) CryptMemFree( out->pbData );
1200c2c66affSColin Finck return ret;
1201c2c66affSColin Finck }
1202c2c66affSColin Finck
CRYPT_CreateContext(const CRYPT_BLOB_ARRAY * pObject,DWORD dwExpectedContentTypeFlags,AddContextToStore addFunc,void ** ppvContext)1203c2c66affSColin Finck static BOOL CRYPT_CreateContext(const CRYPT_BLOB_ARRAY *pObject,
1204c2c66affSColin Finck DWORD dwExpectedContentTypeFlags, AddContextToStore addFunc, void **ppvContext)
1205c2c66affSColin Finck {
1206c2c66affSColin Finck BOOL ret = TRUE;
1207c2c66affSColin Finck CRYPT_DATA_BLOB blob;
1208c2c66affSColin Finck
1209c2c66affSColin Finck if (!pObject->cBlob)
1210c2c66affSColin Finck {
1211c2c66affSColin Finck SetLastError(ERROR_INVALID_DATA);
1212c2c66affSColin Finck *ppvContext = NULL;
1213c2c66affSColin Finck ret = FALSE;
1214c2c66affSColin Finck }
1215c2c66affSColin Finck else if (pObject->cBlob == 1)
1216c2c66affSColin Finck {
1217c2c66affSColin Finck if (decode_base64_blob(&pObject->rgBlob[0], &blob))
1218c2c66affSColin Finck {
1219c2c66affSColin Finck ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
1220c2c66affSColin Finck dwExpectedContentTypeFlags, CERT_QUERY_FORMAT_FLAG_BINARY, 0,
1221c2c66affSColin Finck NULL, NULL, NULL, NULL, NULL, (const void **)ppvContext);
1222c2c66affSColin Finck CryptMemFree(blob.pbData);
1223c2c66affSColin Finck }
1224c2c66affSColin Finck else
1225c2c66affSColin Finck {
1226c2c66affSColin Finck ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &pObject->rgBlob[0],
1227c2c66affSColin Finck dwExpectedContentTypeFlags, CERT_QUERY_FORMAT_FLAG_BINARY, 0,
1228c2c66affSColin Finck NULL, NULL, NULL, NULL, NULL, (const void **)ppvContext);
1229c2c66affSColin Finck }
1230c2c66affSColin Finck if (!ret)
1231c2c66affSColin Finck {
1232c2c66affSColin Finck SetLastError(CRYPT_E_NO_MATCH);
1233c2c66affSColin Finck ret = FALSE;
1234c2c66affSColin Finck }
1235c2c66affSColin Finck }
1236c2c66affSColin Finck else
1237c2c66affSColin Finck {
1238c2c66affSColin Finck HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1239c2c66affSColin Finck CERT_STORE_CREATE_NEW_FLAG, NULL);
1240c2c66affSColin Finck
1241c2c66affSColin Finck if (store)
1242c2c66affSColin Finck {
1243c2c66affSColin Finck DWORD i;
1244c2c66affSColin Finck const void *context;
1245c2c66affSColin Finck
1246c2c66affSColin Finck for (i = 0; i < pObject->cBlob; i++)
1247c2c66affSColin Finck {
1248c2c66affSColin Finck if (decode_base64_blob(&pObject->rgBlob[i], &blob))
1249c2c66affSColin Finck {
1250c2c66affSColin Finck ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
1251c2c66affSColin Finck dwExpectedContentTypeFlags, CERT_QUERY_FORMAT_FLAG_BINARY,
1252c2c66affSColin Finck 0, NULL, NULL, NULL, NULL, NULL, &context);
1253c2c66affSColin Finck CryptMemFree(blob.pbData);
1254c2c66affSColin Finck }
1255c2c66affSColin Finck else
1256c2c66affSColin Finck {
1257c2c66affSColin Finck ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
1258c2c66affSColin Finck &pObject->rgBlob[i], dwExpectedContentTypeFlags,
1259c2c66affSColin Finck CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, NULL,
1260c2c66affSColin Finck NULL, &context);
1261c2c66affSColin Finck }
1262c2c66affSColin Finck if (ret)
1263c2c66affSColin Finck {
1264c2c66affSColin Finck if (!addFunc(store, context, CERT_STORE_ADD_ALWAYS, NULL))
1265c2c66affSColin Finck ret = FALSE;
1266c2c66affSColin Finck }
1267c2c66affSColin Finck else
1268c2c66affSColin Finck {
1269c2c66affSColin Finck SetLastError(CRYPT_E_NO_MATCH);
1270c2c66affSColin Finck ret = FALSE;
1271c2c66affSColin Finck }
1272c2c66affSColin Finck }
1273c2c66affSColin Finck }
1274c2c66affSColin Finck else
1275c2c66affSColin Finck ret = FALSE;
1276c2c66affSColin Finck *ppvContext = store;
1277c2c66affSColin Finck }
1278c2c66affSColin Finck return ret;
1279c2c66affSColin Finck }
1280c2c66affSColin Finck
CRYPT_CreateCert(LPCSTR pszObjectOid,DWORD dwRetrievalFlags,const CRYPT_BLOB_ARRAY * pObject,void ** ppvContext)1281c2c66affSColin Finck static BOOL WINAPI CRYPT_CreateCert(LPCSTR pszObjectOid,
1282c2c66affSColin Finck DWORD dwRetrievalFlags, const CRYPT_BLOB_ARRAY *pObject, void **ppvContext)
1283c2c66affSColin Finck {
1284c2c66affSColin Finck return CRYPT_CreateContext(pObject, CERT_QUERY_CONTENT_FLAG_CERT,
1285c2c66affSColin Finck (AddContextToStore)CertAddCertificateContextToStore, ppvContext);
1286c2c66affSColin Finck }
1287c2c66affSColin Finck
CRYPT_CreateCRL(LPCSTR pszObjectOid,DWORD dwRetrievalFlags,const CRYPT_BLOB_ARRAY * pObject,void ** ppvContext)1288c2c66affSColin Finck static BOOL WINAPI CRYPT_CreateCRL(LPCSTR pszObjectOid,
1289c2c66affSColin Finck DWORD dwRetrievalFlags, const CRYPT_BLOB_ARRAY *pObject, void **ppvContext)
1290c2c66affSColin Finck {
1291c2c66affSColin Finck return CRYPT_CreateContext(pObject, CERT_QUERY_CONTENT_FLAG_CRL,
1292c2c66affSColin Finck (AddContextToStore)CertAddCRLContextToStore, ppvContext);
1293c2c66affSColin Finck }
1294c2c66affSColin Finck
CRYPT_CreateCTL(LPCSTR pszObjectOid,DWORD dwRetrievalFlags,const CRYPT_BLOB_ARRAY * pObject,void ** ppvContext)1295c2c66affSColin Finck static BOOL WINAPI CRYPT_CreateCTL(LPCSTR pszObjectOid,
1296c2c66affSColin Finck DWORD dwRetrievalFlags, const CRYPT_BLOB_ARRAY *pObject, void **ppvContext)
1297c2c66affSColin Finck {
1298c2c66affSColin Finck return CRYPT_CreateContext(pObject, CERT_QUERY_CONTENT_FLAG_CTL,
1299c2c66affSColin Finck (AddContextToStore)CertAddCTLContextToStore, ppvContext);
1300c2c66affSColin Finck }
1301c2c66affSColin Finck
CRYPT_CreatePKCS7(LPCSTR pszObjectOid,DWORD dwRetrievalFlags,const CRYPT_BLOB_ARRAY * pObject,void ** ppvContext)1302c2c66affSColin Finck static BOOL WINAPI CRYPT_CreatePKCS7(LPCSTR pszObjectOid,
1303c2c66affSColin Finck DWORD dwRetrievalFlags, const CRYPT_BLOB_ARRAY *pObject, void **ppvContext)
1304c2c66affSColin Finck {
1305c2c66affSColin Finck BOOL ret;
1306c2c66affSColin Finck
1307c2c66affSColin Finck if (!pObject->cBlob)
1308c2c66affSColin Finck {
1309c2c66affSColin Finck SetLastError(ERROR_INVALID_DATA);
1310c2c66affSColin Finck *ppvContext = NULL;
1311c2c66affSColin Finck ret = FALSE;
1312c2c66affSColin Finck }
1313c2c66affSColin Finck else if (pObject->cBlob == 1)
1314c2c66affSColin Finck ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &pObject->rgBlob[0],
1315c2c66affSColin Finck CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
1316c2c66affSColin Finck CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED, CERT_QUERY_FORMAT_FLAG_BINARY,
1317c2c66affSColin Finck 0, NULL, NULL, NULL, ppvContext, NULL, NULL);
1318c2c66affSColin Finck else
1319c2c66affSColin Finck {
1320c2c66affSColin Finck FIXME("multiple messages unimplemented\n");
1321c2c66affSColin Finck ret = FALSE;
1322c2c66affSColin Finck }
1323c2c66affSColin Finck return ret;
1324c2c66affSColin Finck }
1325c2c66affSColin Finck
CRYPT_CreateAny(LPCSTR pszObjectOid,DWORD dwRetrievalFlags,const CRYPT_BLOB_ARRAY * pObject,void ** ppvContext)1326c2c66affSColin Finck static BOOL WINAPI CRYPT_CreateAny(LPCSTR pszObjectOid,
1327c2c66affSColin Finck DWORD dwRetrievalFlags, const CRYPT_BLOB_ARRAY *pObject, void **ppvContext)
1328c2c66affSColin Finck {
1329c2c66affSColin Finck BOOL ret;
1330c2c66affSColin Finck
1331c2c66affSColin Finck if (!pObject->cBlob)
1332c2c66affSColin Finck {
1333c2c66affSColin Finck SetLastError(ERROR_INVALID_DATA);
1334c2c66affSColin Finck *ppvContext = NULL;
1335c2c66affSColin Finck ret = FALSE;
1336c2c66affSColin Finck }
1337c2c66affSColin Finck else
1338c2c66affSColin Finck {
1339c2c66affSColin Finck HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
1340c2c66affSColin Finck CERT_STORE_CREATE_NEW_FLAG, NULL);
1341c2c66affSColin Finck
1342c2c66affSColin Finck if (store)
1343c2c66affSColin Finck {
1344c2c66affSColin Finck HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1345c2c66affSColin Finck CERT_STORE_CREATE_NEW_FLAG, NULL);
1346c2c66affSColin Finck
1347c2c66affSColin Finck if (memStore)
1348c2c66affSColin Finck {
1349c2c66affSColin Finck CertAddStoreToCollection(store, memStore,
1350c2c66affSColin Finck CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
1351c2c66affSColin Finck CertCloseStore(memStore, 0);
1352c2c66affSColin Finck }
1353c2c66affSColin Finck else
1354c2c66affSColin Finck {
1355c2c66affSColin Finck CertCloseStore(store, 0);
1356c2c66affSColin Finck store = NULL;
1357c2c66affSColin Finck }
1358c2c66affSColin Finck }
1359c2c66affSColin Finck if (store)
1360c2c66affSColin Finck {
1361c2c66affSColin Finck DWORD i;
1362c2c66affSColin Finck
1363c2c66affSColin Finck ret = TRUE;
1364c2c66affSColin Finck for (i = 0; i < pObject->cBlob; i++)
1365c2c66affSColin Finck {
1366c2c66affSColin Finck DWORD contentType, expectedContentTypes =
1367c2c66affSColin Finck CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
1368c2c66affSColin Finck CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED |
1369c2c66affSColin Finck CERT_QUERY_CONTENT_FLAG_CERT |
1370c2c66affSColin Finck CERT_QUERY_CONTENT_FLAG_CRL |
1371c2c66affSColin Finck CERT_QUERY_CONTENT_FLAG_CTL;
1372c2c66affSColin Finck HCERTSTORE contextStore;
1373c2c66affSColin Finck const void *context;
1374c2c66affSColin Finck
1375c2c66affSColin Finck if (CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
1376c2c66affSColin Finck &pObject->rgBlob[i], expectedContentTypes,
1377c2c66affSColin Finck CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, &contentType, NULL,
1378c2c66affSColin Finck &contextStore, NULL, &context))
1379c2c66affSColin Finck {
1380c2c66affSColin Finck switch (contentType)
1381c2c66affSColin Finck {
1382c2c66affSColin Finck case CERT_QUERY_CONTENT_CERT:
1383c2c66affSColin Finck if (!CertAddCertificateContextToStore(store,
1384c2c66affSColin Finck context, CERT_STORE_ADD_ALWAYS, NULL))
1385c2c66affSColin Finck ret = FALSE;
1386c2c66affSColin Finck CertFreeCertificateContext(context);
1387c2c66affSColin Finck break;
1388c2c66affSColin Finck case CERT_QUERY_CONTENT_CRL:
1389c2c66affSColin Finck if (!CertAddCRLContextToStore(store,
1390c2c66affSColin Finck context, CERT_STORE_ADD_ALWAYS, NULL))
1391c2c66affSColin Finck ret = FALSE;
1392c2c66affSColin Finck CertFreeCRLContext(context);
1393c2c66affSColin Finck break;
1394c2c66affSColin Finck case CERT_QUERY_CONTENT_CTL:
1395c2c66affSColin Finck if (!CertAddCTLContextToStore(store,
1396c2c66affSColin Finck context, CERT_STORE_ADD_ALWAYS, NULL))
1397c2c66affSColin Finck ret = FALSE;
1398c2c66affSColin Finck CertFreeCTLContext(context);
1399c2c66affSColin Finck break;
1400c2c66affSColin Finck default:
1401c2c66affSColin Finck CertAddStoreToCollection(store, contextStore, 0, 0);
1402c2c66affSColin Finck }
1403c2c66affSColin Finck CertCloseStore(contextStore, 0);
1404c2c66affSColin Finck }
1405c2c66affSColin Finck else
1406c2c66affSColin Finck ret = FALSE;
1407c2c66affSColin Finck }
1408c2c66affSColin Finck }
1409c2c66affSColin Finck else
1410c2c66affSColin Finck ret = FALSE;
1411c2c66affSColin Finck *ppvContext = store;
1412c2c66affSColin Finck }
1413c2c66affSColin Finck return ret;
1414c2c66affSColin Finck }
1415c2c66affSColin Finck
1416c2c66affSColin Finck typedef BOOL (WINAPI *ContextDllCreateObjectContext)(LPCSTR pszObjectOid,
1417c2c66affSColin Finck DWORD dwRetrievalFlags, const CRYPT_BLOB_ARRAY *pObject, void **ppvContext);
1418c2c66affSColin Finck
CRYPT_GetCreateFunction(LPCSTR pszObjectOid,ContextDllCreateObjectContext * pFunc,HCRYPTOIDFUNCADDR * phFunc)1419c2c66affSColin Finck static BOOL CRYPT_GetCreateFunction(LPCSTR pszObjectOid,
1420c2c66affSColin Finck ContextDllCreateObjectContext *pFunc, HCRYPTOIDFUNCADDR *phFunc)
1421c2c66affSColin Finck {
1422c2c66affSColin Finck BOOL ret = TRUE;
1423c2c66affSColin Finck
1424c2c66affSColin Finck TRACE("(%s, %p, %p)\n", debugstr_a(pszObjectOid), pFunc, phFunc);
1425c2c66affSColin Finck
1426c2c66affSColin Finck *pFunc = NULL;
1427c2c66affSColin Finck *phFunc = 0;
1428c2c66affSColin Finck if (IS_INTOID(pszObjectOid))
1429c2c66affSColin Finck {
1430c2c66affSColin Finck switch (LOWORD(pszObjectOid))
1431c2c66affSColin Finck {
1432c2c66affSColin Finck case 0:
1433c2c66affSColin Finck *pFunc = CRYPT_CreateBlob;
1434c2c66affSColin Finck break;
1435c2c66affSColin Finck case LOWORD(CONTEXT_OID_CERTIFICATE):
1436c2c66affSColin Finck *pFunc = CRYPT_CreateCert;
1437c2c66affSColin Finck break;
1438c2c66affSColin Finck case LOWORD(CONTEXT_OID_CRL):
1439c2c66affSColin Finck *pFunc = CRYPT_CreateCRL;
1440c2c66affSColin Finck break;
1441c2c66affSColin Finck case LOWORD(CONTEXT_OID_CTL):
1442c2c66affSColin Finck *pFunc = CRYPT_CreateCTL;
1443c2c66affSColin Finck break;
1444c2c66affSColin Finck case LOWORD(CONTEXT_OID_PKCS7):
1445c2c66affSColin Finck *pFunc = CRYPT_CreatePKCS7;
1446c2c66affSColin Finck break;
1447c2c66affSColin Finck case LOWORD(CONTEXT_OID_CAPI2_ANY):
1448c2c66affSColin Finck *pFunc = CRYPT_CreateAny;
1449c2c66affSColin Finck break;
1450c2c66affSColin Finck }
1451c2c66affSColin Finck }
1452c2c66affSColin Finck if (!*pFunc)
1453c2c66affSColin Finck {
1454c2c66affSColin Finck static HCRYPTOIDFUNCSET set = NULL;
1455c2c66affSColin Finck
1456c2c66affSColin Finck if (!set)
1457c2c66affSColin Finck set = CryptInitOIDFunctionSet(
1458c2c66affSColin Finck CONTEXT_OID_CREATE_OBJECT_CONTEXT_FUNC, 0);
1459c2c66affSColin Finck ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, pszObjectOid,
1460c2c66affSColin Finck 0, (void **)pFunc, phFunc);
1461c2c66affSColin Finck }
1462c2c66affSColin Finck TRACE("returning %d\n", ret);
1463c2c66affSColin Finck return ret;
1464c2c66affSColin Finck }
1465c2c66affSColin Finck
CRYPT_GetExpiration(const void * object,const char * pszObjectOid,FILETIME * expiration)1466c2c66affSColin Finck static BOOL CRYPT_GetExpiration(const void *object, const char *pszObjectOid, FILETIME *expiration)
1467c2c66affSColin Finck {
1468c2c66affSColin Finck if (!IS_INTOID(pszObjectOid))
1469c2c66affSColin Finck return FALSE;
1470c2c66affSColin Finck
1471c2c66affSColin Finck switch (LOWORD(pszObjectOid)) {
1472c2c66affSColin Finck case LOWORD(CONTEXT_OID_CERTIFICATE):
1473c2c66affSColin Finck *expiration = ((const CERT_CONTEXT*)object)->pCertInfo->NotAfter;
1474c2c66affSColin Finck return TRUE;
1475c2c66affSColin Finck case LOWORD(CONTEXT_OID_CRL):
1476c2c66affSColin Finck *expiration = ((const CRL_CONTEXT*)object)->pCrlInfo->NextUpdate;
1477c2c66affSColin Finck return TRUE;
1478c2c66affSColin Finck case LOWORD(CONTEXT_OID_CTL):
1479c2c66affSColin Finck *expiration = ((const CTL_CONTEXT*)object)->pCtlInfo->NextUpdate;
1480c2c66affSColin Finck return TRUE;
1481c2c66affSColin Finck }
1482c2c66affSColin Finck
1483c2c66affSColin Finck return FALSE;
1484c2c66affSColin Finck }
1485c2c66affSColin Finck
1486c2c66affSColin Finck /***********************************************************************
1487c2c66affSColin Finck * CryptRetrieveObjectByUrlW (CRYPTNET.@)
1488c2c66affSColin Finck */
CryptRetrieveObjectByUrlW(LPCWSTR pszURL,LPCSTR pszObjectOid,DWORD dwRetrievalFlags,DWORD dwTimeout,LPVOID * ppvObject,HCRYPTASYNC hAsyncRetrieve,PCRYPT_CREDENTIALS pCredentials,LPVOID pvVerify,PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)1489c2c66affSColin Finck BOOL WINAPI CryptRetrieveObjectByUrlW(LPCWSTR pszURL, LPCSTR pszObjectOid,
1490c2c66affSColin Finck DWORD dwRetrievalFlags, DWORD dwTimeout, LPVOID *ppvObject,
1491c2c66affSColin Finck HCRYPTASYNC hAsyncRetrieve, PCRYPT_CREDENTIALS pCredentials, LPVOID pvVerify,
1492c2c66affSColin Finck PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
1493c2c66affSColin Finck {
1494c2c66affSColin Finck BOOL ret;
1495c2c66affSColin Finck SchemeDllRetrieveEncodedObjectW retrieve;
1496c2c66affSColin Finck ContextDllCreateObjectContext create;
1497c2c66affSColin Finck HCRYPTOIDFUNCADDR hRetrieve = 0, hCreate = 0;
1498c2c66affSColin Finck
1499c2c66affSColin Finck TRACE("(%s, %s, %08x, %d, %p, %p, %p, %p, %p)\n", debugstr_w(pszURL),
1500c2c66affSColin Finck debugstr_a(pszObjectOid), dwRetrievalFlags, dwTimeout, ppvObject,
1501c2c66affSColin Finck hAsyncRetrieve, pCredentials, pvVerify, pAuxInfo);
1502c2c66affSColin Finck
1503c2c66affSColin Finck if (!pszURL)
1504c2c66affSColin Finck {
1505c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
1506c2c66affSColin Finck return FALSE;
1507c2c66affSColin Finck }
1508c2c66affSColin Finck ret = CRYPT_GetRetrieveFunction(pszURL, &retrieve, &hRetrieve);
1509c2c66affSColin Finck if (ret)
1510c2c66affSColin Finck ret = CRYPT_GetCreateFunction(pszObjectOid, &create, &hCreate);
1511c2c66affSColin Finck if (ret)
1512c2c66affSColin Finck {
1513c2c66affSColin Finck CRYPT_BLOB_ARRAY object = { 0, NULL };
1514c2c66affSColin Finck PFN_FREE_ENCODED_OBJECT_FUNC freeObject;
1515c2c66affSColin Finck void *freeContext;
1516c2c66affSColin Finck FILETIME expires;
1517c2c66affSColin Finck
1518c2c66affSColin Finck ret = retrieve(pszURL, pszObjectOid, dwRetrievalFlags, dwTimeout,
1519c2c66affSColin Finck &object, &freeObject, &freeContext, hAsyncRetrieve, pCredentials,
1520c2c66affSColin Finck pAuxInfo);
1521c2c66affSColin Finck if (ret)
1522c2c66affSColin Finck {
1523c2c66affSColin Finck ret = create(pszObjectOid, dwRetrievalFlags, &object, ppvObject);
1524c2c66affSColin Finck if (ret && !(dwRetrievalFlags & CRYPT_DONT_CACHE_RESULT) &&
1525c2c66affSColin Finck CRYPT_GetExpiration(*ppvObject, pszObjectOid, &expires))
1526c2c66affSColin Finck {
1527c2c66affSColin Finck CRYPT_CacheURL(pszURL, &object, dwRetrievalFlags, expires);
1528c2c66affSColin Finck }
1529c2c66affSColin Finck freeObject(pszObjectOid, &object, freeContext);
1530c2c66affSColin Finck }
1531c2c66affSColin Finck }
1532c2c66affSColin Finck if (hCreate)
1533c2c66affSColin Finck CryptFreeOIDFunctionAddress(hCreate, 0);
1534c2c66affSColin Finck if (hRetrieve)
1535c2c66affSColin Finck CryptFreeOIDFunctionAddress(hRetrieve, 0);
1536c2c66affSColin Finck TRACE("returning %d\n", ret);
1537c2c66affSColin Finck return ret;
1538c2c66affSColin Finck }
1539c2c66affSColin Finck
verify_cert_revocation_with_crl_online(PCCERT_CONTEXT cert,PCCRL_CONTEXT crl,DWORD index,FILETIME * pTime,PCERT_REVOCATION_STATUS pRevStatus)1540c2c66affSColin Finck static DWORD verify_cert_revocation_with_crl_online(PCCERT_CONTEXT cert,
1541c2c66affSColin Finck PCCRL_CONTEXT crl, DWORD index, FILETIME *pTime,
1542c2c66affSColin Finck PCERT_REVOCATION_STATUS pRevStatus)
1543c2c66affSColin Finck {
1544c2c66affSColin Finck DWORD error;
1545c2c66affSColin Finck PCRL_ENTRY entry = NULL;
1546c2c66affSColin Finck
1547c2c66affSColin Finck CertFindCertificateInCRL(cert, crl, 0, NULL, &entry);
1548c2c66affSColin Finck if (entry)
1549c2c66affSColin Finck {
1550c2c66affSColin Finck error = CRYPT_E_REVOKED;
1551c2c66affSColin Finck pRevStatus->dwIndex = index;
1552c2c66affSColin Finck }
1553c2c66affSColin Finck else
1554c2c66affSColin Finck {
1555c2c66affSColin Finck /* Since the CRL was retrieved for the cert being checked, then it's
1556c2c66affSColin Finck * guaranteed to be fresh, and the cert is not revoked.
1557c2c66affSColin Finck */
1558c2c66affSColin Finck error = ERROR_SUCCESS;
1559c2c66affSColin Finck }
1560c2c66affSColin Finck return error;
1561c2c66affSColin Finck }
1562c2c66affSColin Finck
verify_cert_revocation_from_dist_points_ext(const CRYPT_DATA_BLOB * value,PCCERT_CONTEXT cert,DWORD index,FILETIME * pTime,DWORD dwFlags,const CERT_REVOCATION_PARA * pRevPara,PCERT_REVOCATION_STATUS pRevStatus)1563c2c66affSColin Finck static DWORD verify_cert_revocation_from_dist_points_ext(
1564c2c66affSColin Finck const CRYPT_DATA_BLOB *value, PCCERT_CONTEXT cert, DWORD index,
1565c2c66affSColin Finck FILETIME *pTime, DWORD dwFlags, const CERT_REVOCATION_PARA *pRevPara,
1566c2c66affSColin Finck PCERT_REVOCATION_STATUS pRevStatus)
1567c2c66affSColin Finck {
1568c2c66affSColin Finck DWORD error = ERROR_SUCCESS, cbUrlArray;
1569c2c66affSColin Finck
1570c2c66affSColin Finck if (CRYPT_GetUrlFromCRLDistPointsExt(value, NULL, &cbUrlArray, NULL, NULL))
1571c2c66affSColin Finck {
1572c2c66affSColin Finck CRYPT_URL_ARRAY *urlArray = CryptMemAlloc(cbUrlArray);
1573c2c66affSColin Finck
1574c2c66affSColin Finck if (urlArray)
1575c2c66affSColin Finck {
1576c2c66affSColin Finck DWORD j, retrievalFlags = 0, startTime, endTime, timeout;
1577c2c66affSColin Finck BOOL ret;
1578c2c66affSColin Finck
1579c2c66affSColin Finck ret = CRYPT_GetUrlFromCRLDistPointsExt(value, urlArray,
1580c2c66affSColin Finck &cbUrlArray, NULL, NULL);
1581c2c66affSColin Finck if (dwFlags & CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION)
1582c2c66affSColin Finck retrievalFlags |= CRYPT_CACHE_ONLY_RETRIEVAL;
1583c2c66affSColin Finck if (dwFlags & CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG &&
1584c2c66affSColin Finck pRevPara && pRevPara->cbSize >= offsetof(CERT_REVOCATION_PARA,
1585c2c66affSColin Finck dwUrlRetrievalTimeout) + sizeof(DWORD))
1586c2c66affSColin Finck {
1587c2c66affSColin Finck startTime = GetTickCount();
1588c2c66affSColin Finck endTime = startTime + pRevPara->dwUrlRetrievalTimeout;
1589c2c66affSColin Finck timeout = pRevPara->dwUrlRetrievalTimeout;
1590c2c66affSColin Finck }
1591c2c66affSColin Finck else
1592c2c66affSColin Finck endTime = timeout = 0;
1593c2c66affSColin Finck if (!ret)
1594c2c66affSColin Finck error = GetLastError();
1595c2c66affSColin Finck /* continue looping if one was offline; break if revoked or timed out */
1596c2c66affSColin Finck for (j = 0; (!error || error == CRYPT_E_REVOCATION_OFFLINE) && j < urlArray->cUrl; j++)
1597c2c66affSColin Finck {
1598c2c66affSColin Finck PCCRL_CONTEXT crl;
1599c2c66affSColin Finck
1600c2c66affSColin Finck ret = CryptRetrieveObjectByUrlW(urlArray->rgwszUrl[j],
1601c2c66affSColin Finck CONTEXT_OID_CRL, retrievalFlags, timeout, (void **)&crl,
1602c2c66affSColin Finck NULL, NULL, NULL, NULL);
1603c2c66affSColin Finck if (ret)
1604c2c66affSColin Finck {
1605c2c66affSColin Finck error = verify_cert_revocation_with_crl_online(cert, crl,
1606c2c66affSColin Finck index, pTime, pRevStatus);
1607c2c66affSColin Finck if (!error && timeout)
1608c2c66affSColin Finck {
1609c2c66affSColin Finck DWORD time = GetTickCount();
1610c2c66affSColin Finck
1611c2c66affSColin Finck if ((int)(endTime - time) <= 0)
1612c2c66affSColin Finck {
1613c2c66affSColin Finck error = ERROR_TIMEOUT;
1614c2c66affSColin Finck pRevStatus->dwIndex = index;
1615c2c66affSColin Finck }
1616c2c66affSColin Finck else
1617c2c66affSColin Finck timeout = endTime - time;
1618c2c66affSColin Finck }
1619c2c66affSColin Finck CertFreeCRLContext(crl);
1620c2c66affSColin Finck }
1621c2c66affSColin Finck else
1622c2c66affSColin Finck error = CRYPT_E_REVOCATION_OFFLINE;
1623c2c66affSColin Finck }
1624c2c66affSColin Finck CryptMemFree(urlArray);
1625c2c66affSColin Finck }
1626c2c66affSColin Finck else
1627c2c66affSColin Finck {
1628c2c66affSColin Finck error = ERROR_OUTOFMEMORY;
1629c2c66affSColin Finck pRevStatus->dwIndex = index;
1630c2c66affSColin Finck }
1631c2c66affSColin Finck }
1632c2c66affSColin Finck else
1633c2c66affSColin Finck {
1634c2c66affSColin Finck error = GetLastError();
1635c2c66affSColin Finck pRevStatus->dwIndex = index;
1636c2c66affSColin Finck }
1637c2c66affSColin Finck return error;
1638c2c66affSColin Finck }
1639c2c66affSColin Finck
verify_cert_revocation_from_aia_ext(const CRYPT_DATA_BLOB * value,PCCERT_CONTEXT cert,DWORD index,FILETIME * pTime,DWORD dwFlags,PCERT_REVOCATION_PARA pRevPara,PCERT_REVOCATION_STATUS pRevStatus)1640c2c66affSColin Finck static DWORD verify_cert_revocation_from_aia_ext(
1641c2c66affSColin Finck const CRYPT_DATA_BLOB *value, PCCERT_CONTEXT cert, DWORD index,
1642c2c66affSColin Finck FILETIME *pTime, DWORD dwFlags, PCERT_REVOCATION_PARA pRevPara,
1643c2c66affSColin Finck PCERT_REVOCATION_STATUS pRevStatus)
1644c2c66affSColin Finck {
1645c2c66affSColin Finck BOOL ret;
1646c2c66affSColin Finck DWORD error, size;
1647c2c66affSColin Finck CERT_AUTHORITY_INFO_ACCESS *aia;
1648c2c66affSColin Finck
1649c2c66affSColin Finck ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_AUTHORITY_INFO_ACCESS,
1650c2c66affSColin Finck value->pbData, value->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &aia, &size);
1651c2c66affSColin Finck if (ret)
1652c2c66affSColin Finck {
1653c2c66affSColin Finck DWORD i;
1654c2c66affSColin Finck
1655c2c66affSColin Finck for (i = 0; i < aia->cAccDescr; i++)
1656c2c66affSColin Finck if (!strcmp(aia->rgAccDescr[i].pszAccessMethod,
1657c2c66affSColin Finck szOID_PKIX_OCSP))
1658c2c66affSColin Finck {
1659c2c66affSColin Finck if (aia->rgAccDescr[i].AccessLocation.dwAltNameChoice ==
1660c2c66affSColin Finck CERT_ALT_NAME_URL)
1661c2c66affSColin Finck FIXME("OCSP URL = %s\n",
1662c2c66affSColin Finck debugstr_w(aia->rgAccDescr[i].AccessLocation.u.pwszURL));
1663c2c66affSColin Finck else
1664c2c66affSColin Finck FIXME("unsupported AccessLocation type %d\n",
1665c2c66affSColin Finck aia->rgAccDescr[i].AccessLocation.dwAltNameChoice);
1666c2c66affSColin Finck }
1667c2c66affSColin Finck LocalFree(aia);
1668c2c66affSColin Finck /* FIXME: lie and pretend OCSP validated the cert */
1669c2c66affSColin Finck error = ERROR_SUCCESS;
1670c2c66affSColin Finck }
1671c2c66affSColin Finck else
1672c2c66affSColin Finck error = GetLastError();
1673c2c66affSColin Finck return error;
1674c2c66affSColin Finck }
1675c2c66affSColin Finck
verify_cert_revocation_with_crl_offline(PCCERT_CONTEXT cert,PCCRL_CONTEXT crl,DWORD index,FILETIME * pTime,PCERT_REVOCATION_STATUS pRevStatus)1676c2c66affSColin Finck static DWORD verify_cert_revocation_with_crl_offline(PCCERT_CONTEXT cert,
1677c2c66affSColin Finck PCCRL_CONTEXT crl, DWORD index, FILETIME *pTime,
1678c2c66affSColin Finck PCERT_REVOCATION_STATUS pRevStatus)
1679c2c66affSColin Finck {
1680c2c66affSColin Finck DWORD error;
1681c2c66affSColin Finck LONG valid;
1682c2c66affSColin Finck
1683c2c66affSColin Finck valid = CompareFileTime(pTime, &crl->pCrlInfo->ThisUpdate);
1684c2c66affSColin Finck if (valid <= 0)
1685c2c66affSColin Finck {
1686c2c66affSColin Finck /* If this CRL is not older than the time being verified, there's no
1687c2c66affSColin Finck * way to know whether the certificate was revoked.
1688c2c66affSColin Finck */
1689c2c66affSColin Finck TRACE("CRL not old enough\n");
1690c2c66affSColin Finck error = CRYPT_E_REVOCATION_OFFLINE;
1691c2c66affSColin Finck }
1692c2c66affSColin Finck else
1693c2c66affSColin Finck {
1694c2c66affSColin Finck PCRL_ENTRY entry = NULL;
1695c2c66affSColin Finck
1696c2c66affSColin Finck CertFindCertificateInCRL(cert, crl, 0, NULL, &entry);
1697c2c66affSColin Finck if (entry)
1698c2c66affSColin Finck {
1699c2c66affSColin Finck error = CRYPT_E_REVOKED;
1700c2c66affSColin Finck pRevStatus->dwIndex = index;
1701c2c66affSColin Finck }
1702c2c66affSColin Finck else
1703c2c66affSColin Finck {
1704c2c66affSColin Finck /* Since the CRL was not retrieved for the cert being checked,
1705c2c66affSColin Finck * there's no guarantee it's fresh, so the cert *might* be okay,
1706c2c66affSColin Finck * but it's safer not to guess.
1707c2c66affSColin Finck */
1708c2c66affSColin Finck TRACE("certificate not found\n");
1709c2c66affSColin Finck error = CRYPT_E_REVOCATION_OFFLINE;
1710c2c66affSColin Finck }
1711c2c66affSColin Finck }
1712c2c66affSColin Finck return error;
1713c2c66affSColin Finck }
1714c2c66affSColin Finck
verify_cert_revocation(PCCERT_CONTEXT cert,DWORD index,FILETIME * pTime,DWORD dwFlags,PCERT_REVOCATION_PARA pRevPara,PCERT_REVOCATION_STATUS pRevStatus)1715c2c66affSColin Finck static DWORD verify_cert_revocation(PCCERT_CONTEXT cert, DWORD index,
1716c2c66affSColin Finck FILETIME *pTime, DWORD dwFlags, PCERT_REVOCATION_PARA pRevPara,
1717c2c66affSColin Finck PCERT_REVOCATION_STATUS pRevStatus)
1718c2c66affSColin Finck {
1719c2c66affSColin Finck DWORD error = ERROR_SUCCESS;
1720c2c66affSColin Finck PCERT_EXTENSION ext;
1721c2c66affSColin Finck
1722c2c66affSColin Finck if ((ext = CertFindExtension(szOID_CRL_DIST_POINTS,
1723c2c66affSColin Finck cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
1724c2c66affSColin Finck error = verify_cert_revocation_from_dist_points_ext(&ext->Value, cert,
1725c2c66affSColin Finck index, pTime, dwFlags, pRevPara, pRevStatus);
1726c2c66affSColin Finck else if ((ext = CertFindExtension(szOID_AUTHORITY_INFO_ACCESS,
1727c2c66affSColin Finck cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
1728c2c66affSColin Finck error = verify_cert_revocation_from_aia_ext(&ext->Value, cert,
1729c2c66affSColin Finck index, pTime, dwFlags, pRevPara, pRevStatus);
1730c2c66affSColin Finck else
1731c2c66affSColin Finck {
1732c2c66affSColin Finck if (pRevPara && pRevPara->hCrlStore && pRevPara->pIssuerCert)
1733c2c66affSColin Finck {
1734c2c66affSColin Finck PCCRL_CONTEXT crl = NULL;
1735c2c66affSColin Finck BOOL canSignCRLs;
1736c2c66affSColin Finck
1737c2c66affSColin Finck /* If the caller told us about the issuer, make sure the issuer
1738c2c66affSColin Finck * can sign CRLs before looking for one.
1739c2c66affSColin Finck */
1740c2c66affSColin Finck if ((ext = CertFindExtension(szOID_KEY_USAGE,
1741c2c66affSColin Finck pRevPara->pIssuerCert->pCertInfo->cExtension,
1742c2c66affSColin Finck pRevPara->pIssuerCert->pCertInfo->rgExtension)))
1743c2c66affSColin Finck {
1744c2c66affSColin Finck CRYPT_BIT_BLOB usage;
1745c2c66affSColin Finck DWORD size = sizeof(usage);
1746c2c66affSColin Finck
1747c2c66affSColin Finck if (!CryptDecodeObjectEx(cert->dwCertEncodingType, X509_BITS,
1748c2c66affSColin Finck ext->Value.pbData, ext->Value.cbData,
1749c2c66affSColin Finck CRYPT_DECODE_NOCOPY_FLAG, NULL, &usage, &size))
1750c2c66affSColin Finck canSignCRLs = FALSE;
1751c2c66affSColin Finck else if (usage.cbData > 2)
1752c2c66affSColin Finck {
1753c2c66affSColin Finck /* The key usage extension only defines 9 bits => no more
1754c2c66affSColin Finck * than 2 bytes are needed to encode all known usages.
1755c2c66affSColin Finck */
1756c2c66affSColin Finck canSignCRLs = FALSE;
1757c2c66affSColin Finck }
1758c2c66affSColin Finck else
1759c2c66affSColin Finck {
1760c2c66affSColin Finck BYTE usageBits = usage.pbData[usage.cbData - 1];
1761c2c66affSColin Finck
1762c2c66affSColin Finck canSignCRLs = usageBits & CERT_CRL_SIGN_KEY_USAGE;
1763c2c66affSColin Finck }
1764c2c66affSColin Finck }
1765c2c66affSColin Finck else
1766c2c66affSColin Finck canSignCRLs = TRUE;
1767c2c66affSColin Finck if (canSignCRLs)
1768c2c66affSColin Finck {
1769c2c66affSColin Finck /* If the caller was helpful enough to tell us where to find a
1770c2c66affSColin Finck * CRL for the cert, look for one and check it.
1771c2c66affSColin Finck */
1772c2c66affSColin Finck crl = CertFindCRLInStore(pRevPara->hCrlStore,
1773c2c66affSColin Finck cert->dwCertEncodingType,
1774c2c66affSColin Finck CRL_FIND_ISSUED_BY_SIGNATURE_FLAG |
1775c2c66affSColin Finck CRL_FIND_ISSUED_BY_AKI_FLAG,
1776c2c66affSColin Finck CRL_FIND_ISSUED_BY, pRevPara->pIssuerCert, NULL);
1777c2c66affSColin Finck }
1778c2c66affSColin Finck if (crl)
1779c2c66affSColin Finck {
1780c2c66affSColin Finck error = verify_cert_revocation_with_crl_offline(cert, crl,
1781c2c66affSColin Finck index, pTime, pRevStatus);
1782c2c66affSColin Finck CertFreeCRLContext(crl);
1783c2c66affSColin Finck }
1784c2c66affSColin Finck else
1785c2c66affSColin Finck {
1786c2c66affSColin Finck TRACE("no CRL found\n");
1787c2c66affSColin Finck error = CRYPT_E_NO_REVOCATION_CHECK;
1788c2c66affSColin Finck pRevStatus->dwIndex = index;
1789c2c66affSColin Finck }
1790c2c66affSColin Finck }
1791c2c66affSColin Finck else
1792c2c66affSColin Finck {
1793c2c66affSColin Finck if (!pRevPara)
1794c2c66affSColin Finck WARN("no CERT_REVOCATION_PARA\n");
1795c2c66affSColin Finck else if (!pRevPara->hCrlStore)
1796c2c66affSColin Finck WARN("no dist points/aia extension and no CRL store\n");
1797c2c66affSColin Finck else if (!pRevPara->pIssuerCert)
1798c2c66affSColin Finck WARN("no dist points/aia extension and no issuer\n");
1799c2c66affSColin Finck error = CRYPT_E_NO_REVOCATION_CHECK;
1800c2c66affSColin Finck pRevStatus->dwIndex = index;
1801c2c66affSColin Finck }
1802c2c66affSColin Finck }
1803c2c66affSColin Finck return error;
1804c2c66affSColin Finck }
1805c2c66affSColin Finck
1806c2c66affSColin Finck typedef struct _CERT_REVOCATION_PARA_NO_EXTRA_FIELDS {
1807c2c66affSColin Finck DWORD cbSize;
1808c2c66affSColin Finck PCCERT_CONTEXT pIssuerCert;
1809c2c66affSColin Finck DWORD cCertStore;
1810c2c66affSColin Finck HCERTSTORE *rgCertStore;
1811c2c66affSColin Finck HCERTSTORE hCrlStore;
1812c2c66affSColin Finck LPFILETIME pftTimeToUse;
1813c2c66affSColin Finck } CERT_REVOCATION_PARA_NO_EXTRA_FIELDS;
1814c2c66affSColin Finck
1815c2c66affSColin Finck typedef struct _OLD_CERT_REVOCATION_STATUS {
1816c2c66affSColin Finck DWORD cbSize;
1817c2c66affSColin Finck DWORD dwIndex;
1818c2c66affSColin Finck DWORD dwError;
1819c2c66affSColin Finck DWORD dwReason;
1820c2c66affSColin Finck } OLD_CERT_REVOCATION_STATUS;
1821c2c66affSColin Finck
1822c2c66affSColin Finck /***********************************************************************
1823c2c66affSColin Finck * CertDllVerifyRevocation (CRYPTNET.@)
1824c2c66affSColin Finck */
CertDllVerifyRevocation(DWORD dwEncodingType,DWORD dwRevType,DWORD cContext,PVOID rgpvContext[],DWORD dwFlags,PCERT_REVOCATION_PARA pRevPara,PCERT_REVOCATION_STATUS pRevStatus)1825c2c66affSColin Finck BOOL WINAPI CertDllVerifyRevocation(DWORD dwEncodingType, DWORD dwRevType,
1826c2c66affSColin Finck DWORD cContext, PVOID rgpvContext[], DWORD dwFlags,
1827c2c66affSColin Finck PCERT_REVOCATION_PARA pRevPara, PCERT_REVOCATION_STATUS pRevStatus)
1828c2c66affSColin Finck {
1829c2c66affSColin Finck DWORD error = 0, i;
1830c2c66affSColin Finck FILETIME now;
1831c2c66affSColin Finck LPFILETIME pTime = NULL;
1832c2c66affSColin Finck
1833c2c66affSColin Finck TRACE("(%08x, %d, %d, %p, %08x, %p, %p)\n", dwEncodingType, dwRevType,
1834c2c66affSColin Finck cContext, rgpvContext, dwFlags, pRevPara, pRevStatus);
1835c2c66affSColin Finck
1836c2c66affSColin Finck if (pRevStatus->cbSize != sizeof(OLD_CERT_REVOCATION_STATUS) &&
1837c2c66affSColin Finck pRevStatus->cbSize != sizeof(CERT_REVOCATION_STATUS))
1838c2c66affSColin Finck {
1839c2c66affSColin Finck SetLastError(E_INVALIDARG);
1840c2c66affSColin Finck return FALSE;
1841c2c66affSColin Finck }
1842c2c66affSColin Finck if (!cContext)
1843c2c66affSColin Finck {
1844c2c66affSColin Finck SetLastError(E_INVALIDARG);
1845c2c66affSColin Finck return FALSE;
1846c2c66affSColin Finck }
1847c2c66affSColin Finck if (pRevPara && pRevPara->cbSize >=
1848c2c66affSColin Finck sizeof(CERT_REVOCATION_PARA_NO_EXTRA_FIELDS))
1849c2c66affSColin Finck pTime = pRevPara->pftTimeToUse;
1850c2c66affSColin Finck if (!pTime)
1851c2c66affSColin Finck {
1852c2c66affSColin Finck GetSystemTimeAsFileTime(&now);
1853c2c66affSColin Finck pTime = &now;
1854c2c66affSColin Finck }
1855c2c66affSColin Finck memset(&pRevStatus->dwIndex, 0, pRevStatus->cbSize - sizeof(DWORD));
1856c2c66affSColin Finck if (dwRevType != CERT_CONTEXT_REVOCATION_TYPE)
1857c2c66affSColin Finck error = CRYPT_E_NO_REVOCATION_CHECK;
1858c2c66affSColin Finck else
1859c2c66affSColin Finck {
1860c2c66affSColin Finck for (i = 0; !error && i < cContext; i++)
1861c2c66affSColin Finck error = verify_cert_revocation(rgpvContext[i], i, pTime, dwFlags,
1862c2c66affSColin Finck pRevPara, pRevStatus);
1863c2c66affSColin Finck }
1864c2c66affSColin Finck if (error)
1865c2c66affSColin Finck {
1866c2c66affSColin Finck SetLastError(error);
1867c2c66affSColin Finck pRevStatus->dwError = error;
1868c2c66affSColin Finck }
1869c2c66affSColin Finck TRACE("returning %d (%08x)\n", !error, error);
1870c2c66affSColin Finck return !error;
1871c2c66affSColin Finck }
1872