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",
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",
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",
258 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
259 NULL, NULL, NULL, NULL, NULL, NULL);
261 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
262 NULL, NULL, NULL, NULL, &cred, NULL);
263 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
265 pFreeCredentialsHandle(&cred);
266 memset(&cred, 0, sizeof(cred));
267 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
268 NULL, NULL, NULL, NULL, &cred, &exp);
269 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
270 /* expriy is indeterminate in win2k3 */
271 trace("expiry: %08x%08x\n", exp.HighPart, exp.LowPart);
272 pFreeCredentialsHandle(&cred);
274 /* Bad version in SCHANNEL_CRED */
275 memset(&schanCred, 0, sizeof(schanCred));
276 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
277 NULL, &schanCred, NULL, NULL, NULL, NULL);
278 ok(st == SEC_E_INTERNAL_ERROR ||
279 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
280 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
281 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
282 NULL, &schanCred, NULL, NULL, NULL, NULL);
283 ok(st == SEC_E_INTERNAL_ERROR ||
284 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
285 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
287 /* No cert in SCHANNEL_CRED succeeds for outbound.. */
288 schanCred.dwVersion = SCHANNEL_CRED_VERSION;
289 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
290 NULL, &schanCred, NULL, NULL, &cred, NULL);
291 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
292 pFreeCredentialsHandle(&cred);
293 /* but fails for inbound. */
294 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
295 NULL, &schanCred, NULL, NULL, &cred, NULL);
296 ok(st == SEC_E_NO_CREDENTIALS ||
297 st == SEC_E_OK /* Vista/win2k8 */,
298 "Expected SEC_E_NO_CREDENTIALS or SEC_E_OK, got %08x\n", st);
302 /* Crashes with bad paCred pointer */
303 schanCred.cCreds = 1;
304 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
305 NULL, &schanCred, NULL, NULL, NULL, NULL);
308 /* Bogus cert in SCHANNEL_CRED. Windows fails with
309 * SEC_E_UNKNOWN_CREDENTIALS, but I'll accept SEC_E_NO_CREDENTIALS too.
311 schanCred.cCreds = 1;
312 schanCred.paCred = &certs[0];
313 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
314 NULL, &schanCred, NULL, NULL, NULL, NULL);
315 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS,
316 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
318 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
319 NULL, &schanCred, NULL, NULL, NULL, NULL);
320 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS,
321 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
324 /* Good cert, but missing private key. Windows fails with
325 * SEC_E_NO_CREDENTIALS, but I'll accept SEC_E_UNKNOWN_CREDENTIALS too.
327 schanCred.cCreds = 1;
328 schanCred.paCred = &certs[1];
329 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
330 NULL, &schanCred, NULL, NULL, &cred, NULL);
331 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS ||
332 st == SEC_E_INTERNAL_ERROR, /* win2k */
333 "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
334 "or SEC_E_INTERNAL_ERROR, got %08x\n", st);
335 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
336 NULL, &schanCred, NULL, NULL, NULL, NULL);
337 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS ||
338 st == SEC_E_INTERNAL_ERROR, /* win2k */
339 "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
340 "or SEC_E_INTERNAL_ERROR, got %08x\n", st);
342 /* Good cert, with CRYPT_KEY_PROV_INFO set before it's had a key loaded. */
343 if (pCertSetCertificateContextProperty)
345 ret = pCertSetCertificateContextProperty(certs[1],
346 CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo);
347 schanCred.dwVersion = SCH_CRED_V3;
348 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
349 NULL, &schanCred, NULL, NULL, &cred, NULL);
350 ok(st == SEC_E_UNKNOWN_CREDENTIALS,
351 "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
352 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
353 NULL, &schanCred, NULL, NULL, &cred, NULL);
354 ok(st == SEC_E_UNKNOWN_CREDENTIALS,
355 "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
358 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
360 ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
364 ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
365 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
374 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
375 NULL, &schanCred, NULL, NULL, NULL, NULL);
377 /* Good cert with private key, bogus version */
378 schanCred.dwVersion = SCH_CRED_V1;
379 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
380 NULL, &schanCred, NULL, NULL, &cred, NULL);
381 ok(st == SEC_E_INTERNAL_ERROR ||
382 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
383 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
384 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
385 NULL, &schanCred, NULL, NULL, &cred, NULL);
386 ok(st == SEC_E_INTERNAL_ERROR ||
387 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
388 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
389 schanCred.dwVersion = SCH_CRED_V2;
390 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
391 NULL, &schanCred, NULL, NULL, &cred, NULL);
392 ok(st == SEC_E_INTERNAL_ERROR ||
393 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
394 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
395 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
396 NULL, &schanCred, NULL, NULL, &cred, NULL);
397 ok(st == SEC_E_INTERNAL_ERROR ||
398 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
399 "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 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %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 "Expected SEC_E_UNKNOWN_CREDENTIALS, got %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 "Expected SEC_E_UNKNOWN_CREDENTIALS, got %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 mail.google.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 while (status == SEC_I_CONTINUE_NEEDED)
641 buf = &buffers[0].pBuffers[0];
642 send(sock, buf->pvBuffer, buf->cbBuffer, 0);
643 buf->cbBuffer = buf_size;
645 buf = &buffers[1].pBuffers[0];
646 ret = receive_data(sock, buf);
650 buf->BufferType = SECBUFFER_TOKEN;
652 status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
653 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
654 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
655 buffers[1].pBuffers[0].cbBuffer = buf_size;
658 ok(status == SEC_E_OK, "InitializeSecurityContext failed: %08x\n", status);
660 pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
662 reset_buffers(&buffers[0]);
664 /* Send a simple request so we get data for testing DecryptMessage */
665 buf = &buffers[0].pBuffers[0];
666 data = buf->pvBuffer;
667 buf->BufferType = SECBUFFER_STREAM_HEADER;
668 buf->cbBuffer = sizes.cbHeader;
670 buf->BufferType = SECBUFFER_DATA;
671 buf->pvBuffer = data + sizes.cbHeader;
672 buf->cbBuffer = sizeof(http_request) - 1;
673 memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
675 buf->BufferType = SECBUFFER_STREAM_TRAILER;
676 buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
677 buf->cbBuffer = sizes.cbTrailer;
679 status = pEncryptMessage(&context, 0, &buffers[0], 0);
680 ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
681 if (status != SEC_E_OK)
684 buf = &buffers[0].pBuffers[0];
685 send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
687 reset_buffers(&buffers[0]);
688 buf->cbBuffer = buf_size;
689 data_size = receive_data(sock, buf);
691 /* Too few buffers */
692 --buffers[0].cBuffers;
693 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
694 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
697 ++buffers[0].cBuffers;
698 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
699 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
701 /* Two data buffers */
702 buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
703 buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
704 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
705 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
707 /* Too few empty buffers */
708 buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
709 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
710 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
712 /* Incomplete data */
713 buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
714 buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
715 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
716 ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
717 ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
718 ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
720 buffers[0].pBuffers[0].cbBuffer = data_size;
721 buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
722 buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
723 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
724 ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
725 ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
726 ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
727 ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected first buffer to be SECBUFFER_STREAM_TRAILER\n");
729 data = buffers[0].pBuffers[1].pvBuffer;
730 data[buffers[0].pBuffers[1].cbBuffer] = 0;
732 pDeleteSecurityContext(&context);
733 pFreeCredentialsHandle(&cred_handle);
735 free_buffers(&buffers[0]);
736 free_buffers(&buffers[1]);
745 testAcquireSecurityContext();
746 test_communication();
751 FreeLibrary(crypt32dll);