quartz: Free two assert calls from having side effects.
[wine/testsucceed.git] / dlls / secur32 / tests / schannel.c
bloba729394b53551a61654f2e0505c2a61a1edbea00
1 /*
2 * Schannel tests
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
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #define SECURITY_WIN32
25 #include <security.h>
26 #include <schannel.h>
27 #include <winsock2.h>
28 #include <ws2tcpip.h>
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',
65 'm','p',0 };
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)
119 HMODULE advapi32dll;
121 crypt32dll = LoadLibraryA("crypt32.dll");
122 secdll = LoadLibraryA("secur32.dll");
123 if(!secdll)
124 secdll = LoadLibraryA("security.dll");
125 advapi32dll = GetModuleHandleA("advapi32.dll");
127 #define GET_PROC(h, func) p ## func = (void*)GetProcAddress(h, #func)
129 if(secdll)
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);
152 #undef GET_PROC
155 static void test_strength(PCredHandle handle)
157 SecPkgCred_CipherStrengths strength = {-1,-1};
158 SECURITY_STATUS st;
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;
171 ULONG i;
172 SECURITY_STATUS st;
173 CredHandle cred;
174 TimeStamp exp;
175 SCHANNEL_CRED schanCred;
176 PCCERT_CONTEXT certs[2];
177 HCRYPTPROV csp;
178 static CHAR unisp_name_a[] = UNISP_NAME_A;
179 WCHAR ms_def_prov_w[MAX_PATH];
180 BOOL ret;
181 HCRYPTKEY key;
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");
189 return;
192 if (SUCCEEDED(pEnumerateSecurityPackagesA(&i, &package_info)))
194 while(i--)
196 if (!strcmp(package_info[i].Name, unisp_name_a))
198 has_schannel = TRUE;
199 break;
202 pFreeContextBuffer(package_info);
204 if (!has_schannel)
206 skip("Schannel not available\n");
207 return;
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,
221 sizeof(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,
227 CRYPT_DELETEKEYSET);
228 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
230 /* WinMe would crash on some tests */
231 win_skip("CryptAcquireContextW is not implemented\n");
232 return;
235 st = pAcquireCredentialsHandleA(NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL,
236 NULL);
237 ok(st == SEC_E_SECPKG_NOT_FOUND,
238 "Expected SEC_E_SECPKG_NOT_FOUND, got %08x\n", st);
239 if (0)
241 /* Crashes on Win2K */
242 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, 0, NULL, NULL, NULL,
243 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);
255 /* Crashes */
256 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);
262 if(st == SEC_E_OK)
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);
298 if (0)
300 /* Crashes with bad paCred pointer */
301 schanCred.cCreds = 1;
302 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 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
347 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
348 NULL, &schanCred, NULL, NULL, &cred, NULL);
349 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
350 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
351 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
352 NULL, &schanCred, NULL, NULL, &cred, NULL);
353 ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
354 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
357 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
358 CRYPT_NEWKEYSET);
359 ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
360 ret = 0;
361 if (pCryptImportKey)
363 ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
364 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
366 if (ret)
368 PCCERT_CONTEXT tmp;
370 if (0)
372 /* Crashes */
373 pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
374 NULL, &schanCred, NULL, NULL, NULL, NULL);
376 /* Crashes on WinNT */
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);
402 /* Succeeds on V3 or higher */
403 schanCred.dwVersion = SCH_CRED_V3;
404 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
405 NULL, &schanCred, NULL, NULL, &cred, NULL);
406 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
407 pFreeCredentialsHandle(&cred);
408 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
409 NULL, &schanCred, NULL, NULL, &cred, NULL);
410 ok(st == SEC_E_OK ||
411 st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
412 "AcquireCredentialsHandleA failed: %08x\n", st);
413 pFreeCredentialsHandle(&cred);
414 schanCred.dwVersion = SCHANNEL_CRED_VERSION;
415 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
416 NULL, &schanCred, NULL, NULL, &cred, NULL);
417 ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
418 pFreeCredentialsHandle(&cred);
419 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
420 NULL, &schanCred, NULL, NULL, &cred, NULL);
421 ok(st == SEC_E_OK ||
422 st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
423 "AcquireCredentialsHandleA failed: %08x\n", st);
424 if (st == SEC_E_OK) test_strength(&cred);
425 pFreeCredentialsHandle(&cred);
427 /* How about more than one cert? */
428 schanCred.cCreds = 2;
429 schanCred.paCred = certs;
430 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
431 NULL, &schanCred, NULL, NULL, &cred, NULL);
432 ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
433 st == SEC_E_NO_CREDENTIALS /* Vista/win2k8 */ ||
434 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
435 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
436 NULL, &schanCred, NULL, NULL, &cred, NULL);
437 ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
438 st == SEC_E_NO_CREDENTIALS ||
439 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
440 tmp = certs[0];
441 certs[0] = certs[1];
442 certs[1] = tmp;
443 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
444 NULL, &schanCred, NULL, NULL, &cred, NULL);
445 ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
446 st == SEC_E_NO_CREDENTIALS ||
447 st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
448 st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
449 NULL, &schanCred, NULL, NULL, &cred, NULL);
450 ok(st == SEC_E_UNKNOWN_CREDENTIALS,
451 "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
452 /* FIXME: what about two valid certs? */
454 if (pCryptDestroyKey)
455 pCryptDestroyKey(key);
458 if (pCryptReleaseContext)
459 pCryptReleaseContext(csp, 0);
460 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
461 CRYPT_DELETEKEYSET);
463 if (pCertFreeCertificateContext)
465 pCertFreeCertificateContext(certs[0]);
466 pCertFreeCertificateContext(certs[1]);
470 static const char http_request[] = "HEAD /test.html HTTP/1.1\r\nHost: www.codeweavers.com\r\nConnection: close\r\n\r\n";
472 static void init_cred(SCHANNEL_CRED *cred)
474 cred->dwVersion = SCHANNEL_CRED_VERSION;
475 cred->cCreds = 0;
476 cred->paCred = 0;
477 cred->hRootStore = NULL;
478 cred->cMappers = 0;
479 cred->aphMappers = NULL;
480 cred->cSupportedAlgs = 0;
481 cred->palgSupportedAlgs = NULL;
482 cred->grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
483 cred->dwMinimumCipherStrength = 0;
484 cred->dwMaximumCipherStrength = 0;
485 cred->dwSessionLifespan = 0;
486 cred->dwFlags = 0;
489 static void init_buffers(SecBufferDesc *desc, unsigned count, unsigned size)
491 desc->ulVersion = SECBUFFER_VERSION;
492 desc->cBuffers = count;
493 desc->pBuffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count*sizeof(SecBuffer));
495 desc->pBuffers[0].cbBuffer = size;
496 desc->pBuffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, size);
499 static void reset_buffers(SecBufferDesc *desc)
501 unsigned i;
503 for (i = 0; i < desc->cBuffers; ++i)
505 desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
506 if (i > 0)
508 desc->pBuffers[i].cbBuffer = 0;
509 desc->pBuffers[i].pvBuffer = NULL;
514 static void free_buffers(SecBufferDesc *desc)
516 HeapFree(GetProcessHeap(), 0, desc->pBuffers[0].pvBuffer);
517 HeapFree(GetProcessHeap(), 0, desc->pBuffers);
520 static int receive_data(SOCKET sock, SecBuffer *buf)
522 unsigned received = 0;
524 while (1)
526 unsigned char *data = buf->pvBuffer;
527 unsigned expected = 0;
528 int ret;
530 ret = recv(sock, (char *)data+received, buf->cbBuffer-received, 0);
531 if (ret == -1)
533 skip("recv failed\n");
534 return -1;
536 else if(ret == 0)
538 skip("connection closed\n");
539 return -1;
541 received += ret;
543 while (expected < received)
545 unsigned frame_size = 5 + ((data[3]<<8) | data[4]);
546 expected += frame_size;
547 data += frame_size;
550 if (expected == received)
551 break;
554 buf->cbBuffer = received;
556 return received;
559 static void test_communication(void)
561 int ret;
563 WSADATA wsa_data;
564 SOCKET sock;
565 struct hostent *host;
566 struct sockaddr_in addr;
568 SECURITY_STATUS status;
569 ULONG attrs;
571 SCHANNEL_CRED cred;
572 CredHandle cred_handle;
573 CtxtHandle context;
574 SecPkgContext_StreamSizes sizes;
576 SecBufferDesc buffers[2];
577 SecBuffer *buf;
578 unsigned buf_size = 4000;
579 unsigned char *data;
580 unsigned data_size;
582 if (!pAcquireCredentialsHandleA || !pFreeCredentialsHandle ||
583 !pInitializeSecurityContextA || !pDeleteSecurityContext ||
584 !pQueryContextAttributesA || !pDecryptMessage || !pEncryptMessage)
586 skip("Required secur32 functions not available\n");
587 return;
590 /* Create a socket and connect to www.codeweavers.com */
591 ret = WSAStartup(0x0202, &wsa_data);
592 if (ret)
594 skip("Can't init winsock 2.2\n");
595 return;
598 host = gethostbyname("www.codeweavers.com");
599 if (!host)
601 skip("Can't resolve www.codeweavers.com\n");
602 return;
605 addr.sin_family = host->h_addrtype;
606 addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
607 addr.sin_port = htons(443);
608 sock = socket(host->h_addrtype, SOCK_STREAM, 0);
609 if (sock == SOCKET_ERROR)
611 skip("Can't create socket\n");
612 return;
615 ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
616 if (ret == SOCKET_ERROR)
618 skip("Can't connect to www.codeweavers.com\n");
619 return;
622 /* Create client credentials */
623 init_cred(&cred);
624 cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
626 status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
627 &cred, NULL, NULL, &cred_handle, NULL);
628 ok(status == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", status);
629 if (status != SEC_E_OK) return;
631 /* Initialize the connection */
632 init_buffers(&buffers[0], 4, buf_size);
633 init_buffers(&buffers[1], 4, buf_size);
635 buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
636 status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
637 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
638 0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
639 ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
641 buffers[1].cBuffers = 1;
642 buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
643 data_size = buffers[0].pBuffers[0].cbBuffer;
644 status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
645 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
646 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
647 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
649 buffers[0].pBuffers[0].cbBuffer = buf_size;
650 buffers[1].cBuffers = 4;
651 buffers[1].pBuffers[0].cbBuffer = buf_size;
653 status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
654 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
655 0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
656 ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
658 while (status == SEC_I_CONTINUE_NEEDED)
660 buf = &buffers[0].pBuffers[0];
661 send(sock, buf->pvBuffer, buf->cbBuffer, 0);
662 buf->cbBuffer = buf_size;
664 buf = &buffers[1].pBuffers[0];
665 ret = receive_data(sock, buf);
666 if (ret == -1)
667 return;
669 buf->BufferType = SECBUFFER_TOKEN;
671 status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
672 ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
673 0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
674 buffers[1].pBuffers[0].cbBuffer = buf_size;
677 ok(status == SEC_E_OK || broken(status == SEC_E_INVALID_TOKEN) /* WinNT */,
678 "InitializeSecurityContext failed: %08x\n", status);
679 if(status != SEC_E_OK) {
680 win_skip("Handshake failed\n");
681 return;
684 pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
686 reset_buffers(&buffers[0]);
688 /* Send a simple request so we get data for testing DecryptMessage */
689 buf = &buffers[0].pBuffers[0];
690 data = buf->pvBuffer;
691 buf->BufferType = SECBUFFER_STREAM_HEADER;
692 buf->cbBuffer = sizes.cbHeader;
693 ++buf;
694 buf->BufferType = SECBUFFER_DATA;
695 buf->pvBuffer = data + sizes.cbHeader;
696 buf->cbBuffer = sizeof(http_request) - 1;
697 memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
698 ++buf;
699 buf->BufferType = SECBUFFER_STREAM_TRAILER;
700 buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
701 buf->cbBuffer = sizes.cbTrailer;
703 status = pEncryptMessage(&context, 0, &buffers[0], 0);
704 ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
705 if (status != SEC_E_OK)
706 return;
708 buf = &buffers[0].pBuffers[0];
709 send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
711 reset_buffers(&buffers[0]);
712 buf->cbBuffer = buf_size;
713 data_size = receive_data(sock, buf);
715 /* Too few buffers */
716 --buffers[0].cBuffers;
717 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
718 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
720 /* No data buffer */
721 ++buffers[0].cBuffers;
722 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
723 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
725 /* Two data buffers */
726 buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
727 buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
728 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
729 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
731 /* Too few empty buffers */
732 buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
733 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
734 ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
736 /* Incomplete data */
737 buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
738 buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
739 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
740 ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
741 ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
742 ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
744 buffers[0].pBuffers[0].cbBuffer = data_size;
745 buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
746 buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
747 status = pDecryptMessage(&context, &buffers[0], 0, NULL);
748 ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
749 if (status == SEC_E_OK)
751 ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
752 ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
753 ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected third buffer to be SECBUFFER_STREAM_TRAILER\n");
755 data = buffers[0].pBuffers[1].pvBuffer;
756 data[buffers[0].pBuffers[1].cbBuffer] = 0;
759 pDeleteSecurityContext(&context);
760 pFreeCredentialsHandle(&cred_handle);
762 free_buffers(&buffers[0]);
763 free_buffers(&buffers[1]);
765 closesocket(sock);
768 START_TEST(schannel)
770 InitFunctionPtrs();
772 testAcquireSecurityContext();
773 test_communication();
775 if(secdll)
776 FreeLibrary(secdll);
777 if(crypt32dll)
778 FreeLibrary(crypt32dll);