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
);
290 /* File URL support was apparently removed in Vista/Windows 2008 */
291 win_skip("File URLs not supported\n");
294 ok(ret
, "CryptRetrieveObjectByUrlA failed: %d\n", GetLastError());
295 ok(pBlobArray
&& pBlobArray
!= (CRYPT_BLOB_ARRAY
*)0xdeadbeef,
296 "Expected a valid pointer\n");
297 if (pBlobArray
&& pBlobArray
!= (CRYPT_BLOB_ARRAY
*)0xdeadbeef)
299 ok(pBlobArray
->cBlob
== 1, "Expected 1 blob, got %d\n",
301 ok(pBlobArray
->rgBlob
[0].cbData
== sizeof(certWithCRLDistPoint
),
302 "Unexpected size %d\n", pBlobArray
->rgBlob
[0].cbData
);
303 CryptMemFree(pBlobArray
);
305 cert
= (PCCERT_CONTEXT
)0xdeadbeef;
306 ret
= CryptRetrieveObjectByUrlA(url
, CONTEXT_OID_CERTIFICATE
, 0, 0,
307 (void **)&cert
, NULL
, NULL
, NULL
, NULL
);
308 ok(cert
&& cert
!= (PCCERT_CONTEXT
)0xdeadbeef, "Expected a cert\n");
309 if (cert
&& cert
!= (PCCERT_CONTEXT
)0xdeadbeef)
310 CertFreeCertificateContext(cert
);
311 crl
= (PCCRL_CONTEXT
)0xdeadbeef;
312 SetLastError(0xdeadbeef);
313 ret
= CryptRetrieveObjectByUrlA(url
, CONTEXT_OID_CRL
, 0, 0, (void **)&crl
,
314 NULL
, NULL
, NULL
, NULL
);
315 /* w2k3,XP, newer w2k: CRYPT_E_NO_MATCH, 95: OSS_DATA_ERROR */
316 ok(!ret
&& (GetLastError() == CRYPT_E_NO_MATCH
||
317 GetLastError() == CRYPT_E_ASN1_BADTAG
||
318 GetLastError() == OSS_DATA_ERROR
),
319 "got 0x%x/%u (expected CRYPT_E_NO_MATCH or CRYPT_E_ASN1_BADTAG or "
320 "OSS_DATA_ERROR)\n", GetLastError(), GetLastError());
322 /* only newer versions of cryptnet do the cleanup */
323 if(!ret
&& GetLastError() != CRYPT_E_ASN1_BADTAG
&&
324 GetLastError() != OSS_DATA_ERROR
) {
325 ok(crl
== NULL
, "Expected CRL to be NULL\n");
328 if (crl
&& crl
!= (PCCRL_CONTEXT
)0xdeadbeef)
329 CertFreeCRLContext(crl
);
330 store
= (HCERTSTORE
)0xdeadbeef;
331 ret
= CryptRetrieveObjectByUrlA(url
, CONTEXT_OID_CAPI2_ANY
, 0, 0,
332 &store
, NULL
, NULL
, NULL
, NULL
);
333 ok(ret
, "CryptRetrieveObjectByUrlA failed: %d\n", GetLastError());
334 if (store
&& store
!= (HCERTSTORE
)0xdeadbeef)
340 cert
= CertEnumCertificatesInStore(store
, cert
);
344 ok(certs
== 1, "Expected 1 cert, got %d\n", certs
);
345 CertCloseStore(store
, 0);
347 /* Are file URLs cached? */
348 cert
= (PCCERT_CONTEXT
)0xdeadbeef;
349 ret
= CryptRetrieveObjectByUrlA(url
, CONTEXT_OID_CERTIFICATE
,
350 CRYPT_CACHE_ONLY_RETRIEVAL
, 0, (void **)&cert
, NULL
, NULL
, NULL
, NULL
);
351 ok(ret
, "CryptRetrieveObjectByUrlA failed: %08x\n", GetLastError());
352 if (cert
&& cert
!= (PCCERT_CONTEXT
)0xdeadbeef)
353 CertFreeCertificateContext(cert
);
355 cert
= (PCCERT_CONTEXT
)0xdeadbeef;
356 ret
= CryptRetrieveObjectByUrlA(url
, CONTEXT_OID_CERTIFICATE
, 0, 0,
357 (void **)&cert
, NULL
, NULL
, NULL
, &aux
);
358 /* w2k: success, 9x: fail with E_INVALIDARG */
359 ok(ret
|| (GetLastError() == E_INVALIDARG
),
360 "got %u with 0x%x/%u (expected '!=0' or '0' with E_INVALIDARG)\n",
361 ret
, GetLastError(), GetLastError());
362 if (cert
&& cert
!= (PCCERT_CONTEXT
)0xdeadbeef)
363 CertFreeCertificateContext(cert
);
365 cert
= (PCCERT_CONTEXT
)0xdeadbeef;
366 aux
.cbSize
= sizeof(aux
);
367 ret
= CryptRetrieveObjectByUrlA(url
, CONTEXT_OID_CERTIFICATE
, 0, 0,
368 (void **)&cert
, NULL
, NULL
, NULL
, &aux
);
369 /* w2k: success, 9x: fail with E_INVALIDARG */
370 ok(ret
|| (GetLastError() == E_INVALIDARG
),
371 "got %u with 0x%x/%u (expected '!=0' or '0' with E_INVALIDARG)\n",
372 ret
, GetLastError(), GetLastError());
374 /* no more tests useful */
375 DeleteFileA(tmpfile
);
376 skip("no usable CertificateContext\n");
380 aux
.pLastSyncTime
= &ft
;
381 ret
= CryptRetrieveObjectByUrlA(url
, CONTEXT_OID_CERTIFICATE
, 0, 0,
382 (void **)&cert
, NULL
, NULL
, NULL
, &aux
);
383 ok(ft
.dwLowDateTime
|| ft
.dwHighDateTime
,
384 "Expected last sync time to be set\n");
385 DeleteFileA(tmpfile
);
386 /* Okay, after being deleted, are file URLs still cached? */
387 SetLastError(0xdeadbeef);
388 ret
= CryptRetrieveObjectByUrlA(url
, CONTEXT_OID_CERTIFICATE
,
389 CRYPT_CACHE_ONLY_RETRIEVAL
, 0, (void **)&cert
, NULL
, NULL
, NULL
, NULL
);
390 ok(!ret
&& (GetLastError() == ERROR_FILE_NOT_FOUND
||
391 GetLastError() == ERROR_PATH_NOT_FOUND
),
392 "Expected ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND, got %d\n",
399 test_retrieveObjectByUrl();