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);
629 /* Initialize the connection */
630 init_buffers(&buffers[0], 4, buf_size);
631 init_buffers(&buffers[1], 4, buf_size);
633 buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
634 status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
635 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
636 0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
637 ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
639 buffers[1].cBuffers = 1;
640 buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
641 data_size = buffers[0].pBuffers[0].cbBuffer;
642 status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
643 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
644 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
645 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
647 buffers[0].pBuffers[0].cbBuffer = buf_size;
648 buffers[1].cBuffers = 4;
649 buffers[1].pBuffers[0].cbBuffer = buf_size;
651 status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
652 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
653 0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
654 ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
656 while (status == SEC_I_CONTINUE_NEEDED)
658 buf = &buffers[0].pBuffers[0];
659 send(sock, buf->pvBuffer, buf->cbBuffer, 0);
660 buf->cbBuffer = buf_size;
662 buf = &buffers[1].pBuffers[0];
663 ret = receive_data(sock, buf);
667 buf->BufferType = SECBUFFER_TOKEN;
669 status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
670 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
671 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
672 buffers[1].pBuffers[0].cbBuffer = buf_size;
675 ok(status == SEC_E_OK || broken(status == SEC_E_INVALID_TOKEN) /* WinNT */,
676 "InitializeSecurityContext failed: %08x\n", status);
677 if(status != SEC_E_OK) {
678 win_skip("Handshake failed\n");
682 pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
684 reset_buffers(&buffers[0]);
686 /* Send a simple request so we get data for testing DecryptMessage */
687 buf = &buffers[0].pBuffers[0];
688 data = buf->pvBuffer;
689 buf->BufferType = SECBUFFER_STREAM_HEADER;
690 buf->cbBuffer = sizes.cbHeader;
692 buf->BufferType = SECBUFFER_DATA;
693 buf->pvBuffer = data + sizes.cbHeader;
694 buf->cbBuffer = sizeof(http_request) - 1;
695 memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
697 buf->BufferType = SECBUFFER_STREAM_TRAILER;
698 buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
699 buf->cbBuffer = sizes.cbTrailer;
701 status = pEncryptMessage(&context, 0, &buffers[0], 0);
702 ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
703 if (status != SEC_E_OK)
706 buf = &buffers[0].pBuffers[0];
707 send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
709 reset_buffers(&buffers[0]);
710 buf->cbBuffer = buf_size;
711 data_size = receive_data(sock, buf);
713 /* Too few buffers */
714 --buffers[0].cBuffers;
715 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
716 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
719 ++buffers[0].cBuffers;
720 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
721 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
723 /* Two data buffers */
724 buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
725 buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
726 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
727 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
729 /* Too few empty buffers */
730 buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
731 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
732 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
734 /* Incomplete data */
735 buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
736 buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
737 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
738 ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
739 ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
740 ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
742 buffers[0].pBuffers[0].cbBuffer = data_size;
743 buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
744 buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
745 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
746 ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
747 ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
748 ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
749 ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected first buffer to be SECBUFFER_STREAM_TRAILER\n");
751 data = buffers[0].pBuffers[1].pvBuffer;
752 data[buffers[0].pBuffers[1].cbBuffer] = 0;
754 pDeleteSecurityContext(&context);
755 pFreeCredentialsHandle(&cred_handle);
757 free_buffers(&buffers[0]);
758 free_buffers(&buffers[1]);
767 testAcquireSecurityContext();
768 test_communication();
773 FreeLibrary(crypt32dll);