2 * Unit test suite for cryptnet.dll
4 * Copyright 2007 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define NONAMELESSUNION
27 #include "wine/test.h"
29 static const BYTE bigCert[] = {
30 0x30,0x78,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x14,0x31,0x12,0x30,0x10,
31 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
32 0x67,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
33 0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
34 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
35 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x30,
36 0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
37 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
39 static const BYTE certWithIssuingDistPoint[] = {
40 0x30,0x81,0x99,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,
41 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x14,0x31,0x12,
42 0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,
43 0x61,0x6e,0x67,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
44 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
45 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x14,0x31,0x12,0x30,0x10,
46 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
47 0x67,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x27,0x30,0x25,0x30,
48 0x23,0x06,0x03,0x55,0x1d,0x1c,0x01,0x01,0xff,0x04,0x19,0x30,0x17,0xa0,0x15,
49 0xa0,0x13,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,
50 0x68,0x71,0x2e,0x6f,0x72,0x67, };
51 static const BYTE certWithCRLDistPoint[] = {
52 0x30,0x81,0x9b,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,
53 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x14,0x31,0x12,
54 0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,
55 0x61,0x6e,0x67,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
56 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
57 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x14,0x31,0x12,0x30,0x10,
58 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
59 0x67,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x29,0x30,0x27,0x30,
60 0x25,0x06,0x03,0x55,0x1d,0x1f,0x01,0x01,0xff,0x04,0x1b,0x30,0x19,0x30,0x17,
61 0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,
62 0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67, };
64 static void compareUrlArray(const CRYPT_URL_ARRAY *expected,
65 const CRYPT_URL_ARRAY *got)
67 ok(expected->cUrl == got->cUrl, "Expected %d URLs, got %d\n",
68 expected->cUrl, got->cUrl);
69 if (expected->cUrl == got->cUrl)
73 for (i = 0; i < got->cUrl; i++)
74 ok(!lstrcmpiW(expected->rgwszUrl[i], got->rgwszUrl[i]),
75 "%d: unexpected URL\n", i);
80 { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
82 static void test_getObjectUrl(void)
85 DWORD urlArraySize = 0, infoSize = 0;
88 SetLastError(0xdeadbeef);
89 ret = CryptGetObjectUrl(NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
90 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
91 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
93 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, NULL, 0, NULL, NULL,
95 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, NULL, 0, NULL, NULL,
96 NULL, &infoSize, NULL);
97 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, NULL, 0, NULL,
98 &urlArraySize, NULL, &infoSize, NULL);
100 /* A cert with no CRL dist point extension fails.. */
101 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
103 SetLastError(0xdeadbeef);
104 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert, 0, NULL,
105 NULL, NULL, NULL, NULL);
106 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
107 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
108 CertFreeCertificateContext(cert);
110 cert = CertCreateCertificateContext(X509_ASN_ENCODING,
111 certWithIssuingDistPoint, sizeof(certWithIssuingDistPoint));
114 /* This cert has no AIA extension, so expect this to fail */
115 SetLastError(0xdeadbeef);
116 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert, 0,
117 NULL, NULL, NULL, NULL, NULL);
118 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
119 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
120 SetLastError(0xdeadbeef);
121 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert,
122 CRYPT_GET_URL_FROM_PROPERTY, NULL, NULL, NULL, NULL, NULL);
123 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
124 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
125 SetLastError(0xdeadbeef);
126 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert,
127 CRYPT_GET_URL_FROM_EXTENSION, NULL, NULL, NULL, NULL, NULL);
128 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
129 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
130 /* It does have an issuing dist point extension, but that's not what
131 * this is looking for (it wants a CRL dist points extension)
133 SetLastError(0xdeadbeef);
134 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
135 (void *)cert, 0, NULL, NULL, NULL, NULL, NULL);
136 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
137 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
138 SetLastError(0xdeadbeef);
139 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
140 (void *)cert, CRYPT_GET_URL_FROM_PROPERTY, NULL, NULL, NULL, NULL,
142 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
143 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
144 SetLastError(0xdeadbeef);
145 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
146 (void *)cert, CRYPT_GET_URL_FROM_EXTENSION, NULL, NULL, NULL, NULL,
148 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
149 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
150 CertFreeCertificateContext(cert);
152 cert = CertCreateCertificateContext(X509_ASN_ENCODING,
153 certWithCRLDistPoint, sizeof(certWithCRLDistPoint));
156 PCRYPT_URL_ARRAY urlArray;
158 /* This cert has no AIA extension, so expect this to fail */
159 SetLastError(0xdeadbeef);
160 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert, 0,
161 NULL, NULL, NULL, NULL, NULL);
162 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
163 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
164 SetLastError(0xdeadbeef);
165 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert,
166 CRYPT_GET_URL_FROM_PROPERTY, NULL, NULL, NULL, NULL, NULL);
167 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
168 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
169 SetLastError(0xdeadbeef);
170 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert,
171 CRYPT_GET_URL_FROM_EXTENSION, NULL, NULL, NULL, NULL, NULL);
172 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
173 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
174 /* It does have a CRL dist points extension */
175 SetLastError(0xdeadbeef);
176 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
177 (void *)cert, 0, NULL, NULL, NULL, NULL, NULL);
178 ok(!ret && GetLastError() == E_INVALIDARG,
179 "Expected E_INVALIDARG, got %08x\n", GetLastError());
180 SetLastError(0xdeadbeef);
181 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
182 (void *)cert, 0, NULL, NULL, NULL, &infoSize, NULL);
183 ok(!ret && GetLastError() == E_INVALIDARG,
184 "Expected E_INVALIDARG, got %08x\n", GetLastError());
185 /* Can get it without specifying the location: */
186 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
187 (void *)cert, 0, NULL, &urlArraySize, NULL, NULL, NULL);
188 ok(ret, "CryptGetObjectUrl failed: %08x\n", GetLastError());
189 urlArray = HeapAlloc(GetProcessHeap(), 0, urlArraySize);
192 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
193 (void *)cert, 0, urlArray, &urlArraySize, NULL, NULL, NULL);
194 ok(ret, "CryptGetObjectUrl failed: %08x\n", GetLastError());
198 CRYPT_URL_ARRAY expectedUrl = { 1, &pUrl };
200 compareUrlArray(&expectedUrl, urlArray);
202 HeapFree(GetProcessHeap(), 0, urlArray);
204 /* or by specifying it's an extension: */
205 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
206 (void *)cert, CRYPT_GET_URL_FROM_EXTENSION, NULL, &urlArraySize, NULL,
208 ok(ret, "CryptGetObjectUrl failed: %08x\n", GetLastError());
209 urlArray = HeapAlloc(GetProcessHeap(), 0, urlArraySize);
212 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
213 (void *)cert, CRYPT_GET_URL_FROM_EXTENSION, urlArray,
214 &urlArraySize, NULL, NULL, NULL);
215 ok(ret, "CryptGetObjectUrl failed: %08x\n", GetLastError());
219 CRYPT_URL_ARRAY expectedUrl = { 1, &pUrl };
221 compareUrlArray(&expectedUrl, urlArray);
223 HeapFree(GetProcessHeap(), 0, urlArray);
225 /* but it isn't contained in a property: */
226 SetLastError(0xdeadbeef);
227 ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
228 (void *)cert, CRYPT_GET_URL_FROM_PROPERTY, NULL, &urlArraySize, NULL,
230 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
231 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
232 CertFreeCertificateContext(cert);
236 static void make_tmp_file(LPSTR path)
238 static char curr[MAX_PATH] = { 0 };
240 DWORD dwNumberOfBytesWritten;
244 GetCurrentDirectoryA(MAX_PATH, curr);
245 GetTempFileNameA(curr, "net", 0, temp);
246 lstrcpyA(path, temp);
247 hf = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
248 FILE_ATTRIBUTE_NORMAL, NULL);
249 WriteFile(hf, certWithCRLDistPoint, sizeof(certWithCRLDistPoint),
250 &dwNumberOfBytesWritten, NULL);
254 static void test_retrieveObjectByUrl(void)
257 char tmpfile[MAX_PATH * 2], *ptr, url[MAX_PATH + 8];
258 CRYPT_BLOB_ARRAY *pBlobArray;
262 CRYPT_RETRIEVE_AUX_INFO aux = { 0 };
265 SetLastError(0xdeadbeef);
266 ret = CryptRetrieveObjectByUrlA(NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL);
267 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER ||
268 GetLastError() == E_INVALIDARG),
269 "got 0x%x/%u (expected ERROR_INVALID_PARAMETER or E_INVALIDARG)\n",
270 GetLastError(), GetLastError());
272 make_tmp_file(tmpfile);
273 ptr = strchr(tmpfile, ':');
275 ptr += 2; /* skip colon and first slash */
278 snprintf(url, sizeof(url), "file:///%s", ptr);
280 ptr = strchr(url, '\\');
285 pBlobArray = (CRYPT_BLOB_ARRAY *)0xdeadbeef;
286 ret = CryptRetrieveObjectByUrlA(url, NULL, 0, 0, (void **)&pBlobArray,
287 NULL, NULL, NULL, NULL);
288 ok(ret, "CryptRetrieveObjectByUrlA failed: %d\n", GetLastError());
289 ok(pBlobArray && pBlobArray != (CRYPT_BLOB_ARRAY *)0xdeadbeef,
290 "Expected a valid pointer\n");
291 if (pBlobArray && pBlobArray != (CRYPT_BLOB_ARRAY *)0xdeadbeef)
293 ok(pBlobArray->cBlob == 1, "Expected 1 blob, got %d\n",
295 ok(pBlobArray->rgBlob[0].cbData == sizeof(certWithCRLDistPoint),
296 "Unexpected size %d\n", pBlobArray->rgBlob[0].cbData);
297 CryptMemFree(pBlobArray);
299 cert = (PCCERT_CONTEXT)0xdeadbeef;
300 ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
301 (void **)&cert, NULL, NULL, NULL, NULL);
302 ok(cert && cert != (PCCERT_CONTEXT)0xdeadbeef, "Expected a cert\n");
303 if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
304 CertFreeCertificateContext(cert);
305 crl = (PCCRL_CONTEXT)0xdeadbeef;
306 SetLastError(0xdeadbeef);
307 ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CRL, 0, 0, (void **)&crl,
308 NULL, NULL, NULL, NULL);
309 /* vista: ERROR_NOT_SUPPORTED, w2k3,XP, newer w2k: CRYPT_E_NO_MATCH,
310 95: OSS_DATA_ERROR */
311 ok(!ret && (GetLastError() == ERROR_NOT_SUPPORTED ||
312 GetLastError() == CRYPT_E_NO_MATCH ||
313 GetLastError() == CRYPT_E_ASN1_BADTAG ||
314 GetLastError() == OSS_DATA_ERROR),
315 "got 0x%x/%u (expected CRYPT_E_NO_MATCH or CRYPT_E_ASN1_BADTAG or "
316 "OSS_DATA_ERROR)\n", GetLastError(), GetLastError());
318 /* only newer versions of cryptnet do the cleanup */
319 if(!ret && GetLastError() != CRYPT_E_ASN1_BADTAG &&
320 GetLastError() != OSS_DATA_ERROR) {
321 ok(crl == NULL, "Expected CRL to be NULL\n");
324 if (crl && crl != (PCCRL_CONTEXT)0xdeadbeef)
325 CertFreeCRLContext(crl);
326 store = (HCERTSTORE)0xdeadbeef;
327 ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CAPI2_ANY, 0, 0,
328 (void **)&store, NULL, NULL, NULL, NULL);
329 ok(ret, "CryptRetrieveObjectByUrlA failed: %d\n", GetLastError());
330 if (store && store != (HCERTSTORE)0xdeadbeef)
336 cert = CertEnumCertificatesInStore(store, cert);
340 ok(certs == 1, "Expected 1 cert, got %d\n", certs);
341 CertCloseStore(store, 0);
343 /* Are file URLs cached? */
344 cert = (PCCERT_CONTEXT)0xdeadbeef;
345 ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE,
346 CRYPT_CACHE_ONLY_RETRIEVAL, 0, (void **)&cert, NULL, NULL, NULL, NULL);
347 ok(ret, "CryptRetrieveObjectByUrlA failed: %08x\n", GetLastError());
348 if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
349 CertFreeCertificateContext(cert);
351 cert = (PCCERT_CONTEXT)0xdeadbeef;
352 ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
353 (void **)&cert, NULL, NULL, NULL, &aux);
354 /* w2k: success, 9x: fail with E_INVALIDARG */
355 ok(ret || (GetLastError() == E_INVALIDARG),
356 "got %u with 0x%x/%u (expected '!=0' or '0' with E_INVALIDARG)\n",
357 ret, GetLastError(), GetLastError());
358 if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
359 CertFreeCertificateContext(cert);
361 cert = (PCCERT_CONTEXT)0xdeadbeef;
362 aux.cbSize = sizeof(aux);
363 ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
364 (void **)&cert, NULL, NULL, NULL, &aux);
365 /* w2k: success, 9x: fail with E_INVALIDARG */
366 ok(ret || (GetLastError() == E_INVALIDARG),
367 "got %u with 0x%x/%u (expected '!=0' or '0' with E_INVALIDARG)\n",
368 ret, GetLastError(), GetLastError());
370 /* no more tests useful */
371 DeleteFileA(tmpfile);
372 skip("no usable CertificateContext\n");
376 aux.pLastSyncTime = &ft;
377 ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
378 (void **)&cert, NULL, NULL, NULL, &aux);
379 ok(ft.dwLowDateTime || ft.dwHighDateTime,
380 "Expected last sync time to be set\n");
381 DeleteFileA(tmpfile);
382 /* Okay, after being deleted, are file URLs still cached? */
383 SetLastError(0xdeadbeef);
384 ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE,
385 CRYPT_CACHE_ONLY_RETRIEVAL, 0, (void **)&cert, NULL, NULL, NULL, NULL);
386 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
387 GetLastError() == ERROR_PATH_NOT_FOUND),
388 "Expected ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND, got %d\n",
395 test_retrieveObjectByUrl();