4 * Copyright 2006 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
24 #define SECURITY_WIN32
30 #include "wine/test.h"
32 static HMODULE secdll, crypt32dll;
34 static ACQUIRE_CREDENTIALS_HANDLE_FN_A pAcquireCredentialsHandleA;
35 static ENUMERATE_SECURITY_PACKAGES_FN_A pEnumerateSecurityPackagesA;
36 static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
37 static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
38 static QUERY_CREDENTIALS_ATTRIBUTES_FN_A pQueryCredentialsAttributesA;
39 static INITIALIZE_SECURITY_CONTEXT_FN_A pInitializeSecurityContextA;
40 static QUERY_CONTEXT_ATTRIBUTES_FN_A pQueryContextAttributesA;
41 static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
42 static DECRYPT_MESSAGE_FN pDecryptMessage;
43 static ENCRYPT_MESSAGE_FN pEncryptMessage;
45 static PCCERT_CONTEXT (WINAPI *pCertCreateCertificateContext)(DWORD,const BYTE*,DWORD);
46 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT);
47 static BOOL (WINAPI *pCertSetCertificateContextProperty)(PCCERT_CONTEXT,DWORD,DWORD,const void*);
49 static BOOL (WINAPI *pCryptAcquireContextW)(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD);
50 static BOOL (WINAPI *pCryptDestroyKey)(HCRYPTKEY);
51 static BOOL (WINAPI *pCryptImportKey)(HCRYPTPROV,CONST BYTE*,DWORD,HCRYPTKEY,DWORD,HCRYPTKEY*);
52 static BOOL (WINAPI *pCryptReleaseContext)(HCRYPTPROV,ULONG_PTR);
54 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
55 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
56 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
57 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
58 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
59 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
60 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
61 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
62 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
63 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
64 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
66 static BYTE privKey[] = {
67 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
68 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
69 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
70 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
71 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
72 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
73 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
74 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
75 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
76 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
77 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
78 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
79 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
80 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
81 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
82 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
83 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
84 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
85 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
86 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
87 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
88 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
89 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
90 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
92 static const BYTE selfSignedCert[] = {
93 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
94 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
95 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
96 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
97 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
98 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
99 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
100 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
101 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
102 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
103 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
104 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
105 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
106 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
107 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
108 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
109 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
110 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
111 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
112 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
113 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
114 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
115 0xa8, 0x76, 0x57, 0x92, 0x36 };
117 static void InitFunctionPtrs(void)
121 crypt32dll = LoadLibraryA("crypt32.dll");
122 secdll = LoadLibraryA("secur32.dll");
124 secdll = LoadLibraryA("security.dll");
125 advapi32dll = GetModuleHandleA("advapi32.dll");
127 #define GET_PROC(h, func) p ## func = (void*)GetProcAddress(h, #func)
131 GET_PROC(secdll, AcquireCredentialsHandleA);
132 GET_PROC(secdll, EnumerateSecurityPackagesA);
133 GET_PROC(secdll, FreeContextBuffer);
134 GET_PROC(secdll, FreeCredentialsHandle);
135 GET_PROC(secdll, QueryCredentialsAttributesA);
136 GET_PROC(secdll, InitializeSecurityContextA);
137 GET_PROC(secdll, QueryContextAttributesA);
138 GET_PROC(secdll, DeleteSecurityContext);
139 GET_PROC(secdll, DecryptMessage);
140 GET_PROC(secdll, EncryptMessage);
143 GET_PROC(advapi32dll, CryptAcquireContextW);
144 GET_PROC(advapi32dll, CryptDestroyKey);
145 GET_PROC(advapi32dll, CryptImportKey);
146 GET_PROC(advapi32dll, CryptReleaseContext);
148 GET_PROC(crypt32dll, CertFreeCertificateContext);
149 GET_PROC(crypt32dll, CertSetCertificateContextProperty);
150 GET_PROC(crypt32dll, CertCreateCertificateContext);
155 static void test_strength(PCredHandle handle)
157 SecPkgCred_CipherStrengths strength = {-1,-1};
160 st = pQueryCredentialsAttributesA(handle, SECPKG_ATTR_CIPHER_STRENGTHS, &strength);
161 ok(st == SEC_E_OK, "QueryCredentialsAttributesA failed: %u\n", GetLastError());
162 ok(strength.dwMinimumCipherStrength, "dwMinimumCipherStrength not changed\n");
163 ok(strength.dwMaximumCipherStrength, "dwMaximumCipherStrength not changed\n");
164 trace("strength %d - %d\n", strength.dwMinimumCipherStrength, strength.dwMaximumCipherStrength);
167 static void testAcquireSecurityContext(void)
169 BOOL has_schannel = FALSE;
170 SecPkgInfoA *package_info;
175 SCHANNEL_CRED schanCred;
176 PCCERT_CONTEXT certs[2];
178 static CHAR unisp_name_a[] = UNISP_NAME_A;
179 WCHAR ms_def_prov_w[MAX_PATH];
182 CRYPT_KEY_PROV_INFO keyProvInfo;
184 if (!pAcquireCredentialsHandleA || !pCertCreateCertificateContext ||
185 !pEnumerateSecurityPackagesA || !pFreeContextBuffer ||
186 !pFreeCredentialsHandle || !pCryptAcquireContextW)
188 win_skip("Needed functions are not available\n");
192 if (SUCCEEDED(pEnumerateSecurityPackagesA(&i, &package_info)))
196 if (!strcmp(package_info[i].Name, unisp_name_a))
202 pFreeContextBuffer(package_info);
206 skip("Schannel not available\n");
210 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
212 keyProvInfo.pwszContainerName = cspNameW;
213 keyProvInfo.pwszProvName = ms_def_prov_w;
214 keyProvInfo.dwProvType = PROV_RSA_FULL;
215 keyProvInfo.dwFlags = 0;
216 keyProvInfo.cProvParam = 0;
217 keyProvInfo.rgProvParam = NULL;
218 keyProvInfo.dwKeySpec = AT_SIGNATURE;
220 certs[0] = pCertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
222 certs[1] = pCertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
223 sizeof(selfSignedCert));
225 SetLastError(0xdeadbeef);
226 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
228 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
230 /* WinMe would crash on some tests */
231 win_skip("CryptAcquireContextW is not implemented\n");
235 st = pAcquireCredentialsHandleA(NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL,
237 ok(st == SEC_E_SECPKG_NOT_FOUND,
238 "Expected SEC_E_SECPKG_NOT_FOUND, got %08x\n", st);
241 /* Crashes on Win2K */
242 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, 0, NULL, NULL, NULL,
244 ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
246 /* Crashes on WinNT */
247 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_BOTH, NULL,
248 NULL, NULL, NULL, NULL, NULL);
249 ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
251 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
252 NULL, NULL, NULL, NULL, NULL, NULL);
253 ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
256 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
257 NULL, NULL, NULL, NULL, NULL, NULL);
259 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
260 NULL, NULL, NULL, NULL, &cred, NULL);
261 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
263 pFreeCredentialsHandle(&cred);
264 memset(&cred, 0, sizeof(cred));
265 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
266 NULL, NULL, NULL, NULL, &cred, &exp);
267 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
268 /* expriy is indeterminate in win2k3 */
269 trace("expiry: %08x%08x\n", exp.HighPart, exp.LowPart);
270 pFreeCredentialsHandle(&cred);
272 /* Bad version in SCHANNEL_CRED */
273 memset(&schanCred, 0, sizeof(schanCred));
274 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
275 NULL, &schanCred, NULL, NULL, NULL, NULL);
276 ok(st == SEC_E_INTERNAL_ERROR ||
277 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */ ||
278 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
279 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
280 NULL, &schanCred, NULL, NULL, NULL, NULL);
281 ok(st == SEC_E_INTERNAL_ERROR ||
282 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */ ||
283 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
285 /* No cert in SCHANNEL_CRED succeeds for outbound.. */
286 schanCred.dwVersion = SCHANNEL_CRED_VERSION;
287 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
288 NULL, &schanCred, NULL, NULL, &cred, NULL);
289 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
290 pFreeCredentialsHandle(&cred);
291 /* but fails for inbound. */
292 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
293 NULL, &schanCred, NULL, NULL, &cred, NULL);
294 ok(st == SEC_E_NO_CREDENTIALS ||
295 st == SEC_E_OK /* Vista/win2k8 */,
296 "Expected SEC_E_NO_CREDENTIALS or SEC_E_OK, got %08x\n", st);
300 /* Crashes with bad paCred pointer */
301 schanCred.cCreds = 1;
302 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
303 NULL, &schanCred, NULL, NULL, NULL, NULL);
306 /* Bogus cert in SCHANNEL_CRED. Windows fails with
307 * SEC_E_UNKNOWN_CREDENTIALS, but I'll accept SEC_E_NO_CREDENTIALS too.
309 schanCred.cCreds = 1;
310 schanCred.paCred = &certs[0];
311 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
312 NULL, &schanCred, NULL, NULL, NULL, NULL);
313 ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
314 st == SEC_E_NO_CREDENTIALS ||
315 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
316 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
317 NULL, &schanCred, NULL, NULL, NULL, NULL);
318 ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
319 st == SEC_E_NO_CREDENTIALS ||
320 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
322 /* Good cert, but missing private key. Windows fails with
323 * SEC_E_NO_CREDENTIALS, but I'll accept SEC_E_UNKNOWN_CREDENTIALS too.
325 schanCred.cCreds = 1;
326 schanCred.paCred = &certs[1];
327 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
328 NULL, &schanCred, NULL, NULL, &cred, NULL);
329 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS ||
330 st == SEC_E_INTERNAL_ERROR, /* win2k */
331 "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
332 "or SEC_E_INTERNAL_ERROR, got %08x\n", st);
333 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
334 NULL, &schanCred, NULL, NULL, NULL, NULL);
335 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS ||
336 st == SEC_E_INTERNAL_ERROR, /* win2k */
337 "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
338 "or SEC_E_INTERNAL_ERROR, got %08x\n", st);
340 /* Good cert, with CRYPT_KEY_PROV_INFO set before it's had a key loaded. */
341 if (pCertSetCertificateContextProperty)
343 ret = pCertSetCertificateContextProperty(certs[1],
344 CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo);
345 schanCred.dwVersion = SCH_CRED_V3;
346 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
347 NULL, &schanCred, NULL, NULL, &cred, NULL);
348 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
349 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
350 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
351 NULL, &schanCred, NULL, NULL, &cred, NULL);
352 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
353 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
356 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
358 ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
362 ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
363 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
372 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
373 NULL, &schanCred, NULL, NULL, NULL, NULL);
375 /* Crashes on WinNT */
376 /* Good cert with private key, bogus version */
377 schanCred.dwVersion = SCH_CRED_V1;
378 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
379 NULL, &schanCred, NULL, NULL, &cred, NULL);
380 ok(st == SEC_E_INTERNAL_ERROR ||
381 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
382 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
383 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
384 NULL, &schanCred, NULL, NULL, &cred, NULL);
385 ok(st == SEC_E_INTERNAL_ERROR ||
386 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
387 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
388 schanCred.dwVersion = SCH_CRED_V2;
389 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
390 NULL, &schanCred, NULL, NULL, &cred, NULL);
391 ok(st == SEC_E_INTERNAL_ERROR ||
392 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
393 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
394 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
395 NULL, &schanCred, NULL, NULL, &cred, NULL);
396 ok(st == SEC_E_INTERNAL_ERROR ||
397 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
398 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
401 /* Succeeds on V3 or higher */
402 schanCred.dwVersion = SCH_CRED_V3;
403 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
404 NULL, &schanCred, NULL, NULL, &cred, NULL);
405 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
406 pFreeCredentialsHandle(&cred);
407 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
408 NULL, &schanCred, NULL, NULL, &cred, NULL);
410 st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
411 "AcquireCredentialsHandleA failed: %08x\n", st);
412 pFreeCredentialsHandle(&cred);
413 schanCred.dwVersion = SCHANNEL_CRED_VERSION;
414 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
415 NULL, &schanCred, NULL, NULL, &cred, NULL);
416 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
417 pFreeCredentialsHandle(&cred);
418 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
419 NULL, &schanCred, NULL, NULL, &cred, NULL);
421 st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
422 "AcquireCredentialsHandleA failed: %08x\n", st);
423 if (st == SEC_E_OK) test_strength(&cred);
424 pFreeCredentialsHandle(&cred);
426 /* How about more than one cert? */
427 schanCred.cCreds = 2;
428 schanCred.paCred = certs;
429 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
430 NULL, &schanCred, NULL, NULL, &cred, NULL);
431 ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
432 st == SEC_E_NO_CREDENTIALS /* Vista/win2k8 */ ||
433 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
434 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
435 NULL, &schanCred, NULL, NULL, &cred, NULL);
436 ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
437 st == SEC_E_NO_CREDENTIALS ||
438 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
442 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
443 NULL, &schanCred, NULL, NULL, &cred, NULL);
444 ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
445 st == SEC_E_NO_CREDENTIALS ||
446 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
447 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
448 NULL, &schanCred, NULL, NULL, &cred, NULL);
449 ok(st == SEC_E_UNKNOWN_CREDENTIALS,
450 "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
451 /* FIXME: what about two valid certs? */
453 if (pCryptDestroyKey)
454 pCryptDestroyKey(key);
457 if (pCryptReleaseContext)
458 pCryptReleaseContext(csp, 0);
459 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
462 if (pCertFreeCertificateContext)
464 pCertFreeCertificateContext(certs[0]);
465 pCertFreeCertificateContext(certs[1]);
469 static const char http_request[] = "HEAD /test.html HTTP/1.1\r\nHost: www.codeweavers.com\r\nConnection: close\r\n\r\n";
471 static void init_cred(SCHANNEL_CRED *cred)
473 cred->dwVersion = SCHANNEL_CRED_VERSION;
476 cred->hRootStore = NULL;
478 cred->aphMappers = NULL;
479 cred->cSupportedAlgs = 0;
480 cred->palgSupportedAlgs = NULL;
481 cred->grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
482 cred->dwMinimumCipherStrength = 0;
483 cred->dwMaximumCipherStrength = 0;
484 cred->dwSessionLifespan = 0;
488 static void init_buffers(SecBufferDesc *desc, unsigned count, unsigned size)
490 desc->ulVersion = SECBUFFER_VERSION;
491 desc->cBuffers = count;
492 desc->pBuffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count*sizeof(SecBuffer));
494 desc->pBuffers[0].cbBuffer = size;
495 desc->pBuffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, size);
498 static void reset_buffers(SecBufferDesc *desc)
502 for (i = 0; i < desc->cBuffers; ++i)
504 desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
507 desc->pBuffers[i].cbBuffer = 0;
508 desc->pBuffers[i].pvBuffer = NULL;
513 static void free_buffers(SecBufferDesc *desc)
515 HeapFree(GetProcessHeap(), 0, desc->pBuffers[0].pvBuffer);
516 HeapFree(GetProcessHeap(), 0, desc->pBuffers);
519 static int receive_data(SOCKET sock, SecBuffer *buf)
521 unsigned received = 0;
525 unsigned char *data = buf->pvBuffer;
526 unsigned expected = 0;
529 ret = recv(sock, (char *)data+received, buf->cbBuffer-received, 0);
532 skip("recv failed\n");
537 skip("connection closed\n");
542 while (expected < received)
544 unsigned frame_size = 5 + ((data[3]<<8) | data[4]);
545 expected += frame_size;
549 if (expected == received)
553 buf->cbBuffer = received;
558 static void test_communication(void)
564 struct hostent *host;
565 struct sockaddr_in addr;
567 SECURITY_STATUS status;
571 CredHandle cred_handle;
573 SecPkgContext_StreamSizes sizes;
575 SecBufferDesc buffers[2];
577 unsigned buf_size = 4000;
581 if (!pAcquireCredentialsHandleA || !pFreeCredentialsHandle ||
582 !pInitializeSecurityContextA || !pDeleteSecurityContext ||
583 !pQueryContextAttributesA || !pDecryptMessage || !pEncryptMessage)
585 skip("Required secur32 functions not available\n");
589 /* Create a socket and connect to www.codeweavers.com */
590 ret = WSAStartup(0x0202, &wsa_data);
593 skip("Can't init winsock 2.2\n");
597 host = gethostbyname("www.codeweavers.com");
600 skip("Can't resolve www.codeweavers.com\n");
604 addr.sin_family = host->h_addrtype;
605 addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
606 addr.sin_port = htons(443);
607 sock = socket(host->h_addrtype, SOCK_STREAM, 0);
608 if (sock == SOCKET_ERROR)
610 skip("Can't create socket\n");
614 ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
615 if (ret == SOCKET_ERROR)
617 skip("Can't connect to www.codeweavers.com\n");
621 /* Create client credentials */
623 cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
625 status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
626 &cred, NULL, NULL, &cred_handle, NULL);
627 ok(status == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", status);
628 if (status != SEC_E_OK) return;
630 /* Initialize the connection */
631 init_buffers(&buffers[0], 4, buf_size);
632 init_buffers(&buffers[1], 4, buf_size);
634 buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
635 status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
636 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
637 0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
638 ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
640 buffers[1].cBuffers = 1;
641 buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
642 data_size = buffers[0].pBuffers[0].cbBuffer;
643 status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
644 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
645 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
646 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
648 buffers[0].pBuffers[0].cbBuffer = buf_size;
649 buffers[1].cBuffers = 4;
650 buffers[1].pBuffers[0].cbBuffer = buf_size;
652 status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
653 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
654 0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
655 ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
657 while (status == SEC_I_CONTINUE_NEEDED)
659 buf = &buffers[0].pBuffers[0];
660 send(sock, buf->pvBuffer, buf->cbBuffer, 0);
661 buf->cbBuffer = buf_size;
663 buf = &buffers[1].pBuffers[0];
664 ret = receive_data(sock, buf);
668 buf->BufferType = SECBUFFER_TOKEN;
670 status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
671 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
672 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
673 buffers[1].pBuffers[0].cbBuffer = buf_size;
676 ok(status == SEC_E_OK || broken(status == SEC_E_INVALID_TOKEN) /* WinNT */,
677 "InitializeSecurityContext failed: %08x\n", status);
678 if(status != SEC_E_OK) {
679 win_skip("Handshake failed\n");
683 pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
685 reset_buffers(&buffers[0]);
687 /* Send a simple request so we get data for testing DecryptMessage */
688 buf = &buffers[0].pBuffers[0];
689 data = buf->pvBuffer;
690 buf->BufferType = SECBUFFER_STREAM_HEADER;
691 buf->cbBuffer = sizes.cbHeader;
693 buf->BufferType = SECBUFFER_DATA;
694 buf->pvBuffer = data + sizes.cbHeader;
695 buf->cbBuffer = sizeof(http_request) - 1;
696 memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
698 buf->BufferType = SECBUFFER_STREAM_TRAILER;
699 buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
700 buf->cbBuffer = sizes.cbTrailer;
702 status = pEncryptMessage(&context, 0, &buffers[0], 0);
703 ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
704 if (status != SEC_E_OK)
707 buf = &buffers[0].pBuffers[0];
708 send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
710 reset_buffers(&buffers[0]);
711 buf->cbBuffer = buf_size;
712 data_size = receive_data(sock, buf);
714 /* Too few buffers */
715 --buffers[0].cBuffers;
716 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
717 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
720 ++buffers[0].cBuffers;
721 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
722 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
724 /* Two data buffers */
725 buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
726 buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
727 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
728 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
730 /* Too few empty buffers */
731 buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
732 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
733 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
735 /* Incomplete data */
736 buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
737 buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
738 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
739 ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
740 ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
741 ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
743 buffers[0].pBuffers[0].cbBuffer = data_size;
744 buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
745 buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
746 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
747 ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
748 ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
749 ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
750 ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected third buffer to be SECBUFFER_STREAM_TRAILER\n");
752 data = buffers[0].pBuffers[1].pvBuffer;
753 data[buffers[0].pBuffers[1].cbBuffer] = 0;
755 pDeleteSecurityContext(&context);
756 pFreeCredentialsHandle(&cred_handle);
758 free_buffers(&buffers[0]);
759 free_buffers(&buffers[1]);
768 testAcquireSecurityContext();
769 test_communication();
774 FreeLibrary(crypt32dll);