Release 1.5.29.
[wine] / dlls / secur32 / tests / schannel.c
1 /*
2  * Schannel tests
3  *
4  * Copyright 2006 Juan Lang
5  *
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.
10  *
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.
15  *
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
19  */
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>
29
30 #include "wine/test.h"
31
32 static HMODULE secdll, crypt32dll;
33
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;
44
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*);
48 static PCCERT_CONTEXT (WINAPI *pCertEnumCertificatesInStore)(HCERTSTORE,PCCERT_CONTEXT);
49
50 static BOOL (WINAPI *pCryptAcquireContextW)(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD);
51 static BOOL (WINAPI *pCryptDestroyKey)(HCRYPTKEY);
52 static BOOL (WINAPI *pCryptImportKey)(HCRYPTPROV,CONST BYTE*,DWORD,HCRYPTKEY,DWORD,HCRYPTKEY*);
53 static BOOL (WINAPI *pCryptReleaseContext)(HCRYPTPROV,ULONG_PTR);
54
55 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
56  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
57  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
58  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
59  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
60  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
61  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
62  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
63  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
64  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
65 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
66  'm','p',0 };
67 static BYTE privKey[] = {
68  0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
69  0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
70  0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
71  0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
72  0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
73  0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
74  0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
75  0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
76  0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
77  0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
78  0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
79  0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
80  0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
81  0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
82  0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
83  0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
84  0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
85  0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
86  0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
87  0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
88  0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
89  0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
90  0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
91  0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
92
93 static const BYTE selfSignedCert[] = {
94  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
95  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
96  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
97  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
98  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
99  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
100  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
101  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
102  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
103  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
104  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
105  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
106  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
107  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
108  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
109  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
110  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
111  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
112  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
113  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
114  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
115  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
116  0xa8, 0x76, 0x57, 0x92, 0x36 };
117
118 static void InitFunctionPtrs(void)
119 {
120     HMODULE advapi32dll;
121
122     crypt32dll = LoadLibraryA("crypt32.dll");
123     secdll = LoadLibraryA("secur32.dll");
124     if(!secdll)
125         secdll = LoadLibraryA("security.dll");
126     advapi32dll = GetModuleHandleA("advapi32.dll");
127
128 #define GET_PROC(h, func)  p ## func = (void*)GetProcAddress(h, #func)
129
130     if(secdll)
131     {
132         GET_PROC(secdll, AcquireCredentialsHandleA);
133         GET_PROC(secdll, EnumerateSecurityPackagesA);
134         GET_PROC(secdll, FreeContextBuffer);
135         GET_PROC(secdll, FreeCredentialsHandle);
136         GET_PROC(secdll, QueryCredentialsAttributesA);
137         GET_PROC(secdll, InitializeSecurityContextA);
138         GET_PROC(secdll, QueryContextAttributesA);
139         GET_PROC(secdll, DeleteSecurityContext);
140         GET_PROC(secdll, DecryptMessage);
141         GET_PROC(secdll, EncryptMessage);
142     }
143
144     GET_PROC(advapi32dll, CryptAcquireContextW);
145     GET_PROC(advapi32dll, CryptDestroyKey);
146     GET_PROC(advapi32dll, CryptImportKey);
147     GET_PROC(advapi32dll, CryptReleaseContext);
148
149     GET_PROC(crypt32dll, CertFreeCertificateContext);
150     GET_PROC(crypt32dll, CertSetCertificateContextProperty);
151     GET_PROC(crypt32dll, CertCreateCertificateContext);
152     GET_PROC(crypt32dll, CertEnumCertificatesInStore);
153
154 #undef GET_PROC
155 }
156
157 static void test_strength(PCredHandle handle)
158 {
159     SecPkgCred_CipherStrengths strength = {-1,-1};
160     SECURITY_STATUS st;
161
162     st = pQueryCredentialsAttributesA(handle, SECPKG_ATTR_CIPHER_STRENGTHS, &strength);
163     ok(st == SEC_E_OK, "QueryCredentialsAttributesA failed: %u\n", GetLastError());
164     ok(strength.dwMinimumCipherStrength, "dwMinimumCipherStrength not changed\n");
165     ok(strength.dwMaximumCipherStrength, "dwMaximumCipherStrength not changed\n");
166     trace("strength %d - %d\n", strength.dwMinimumCipherStrength, strength.dwMaximumCipherStrength);
167 }
168
169 static void test_supported_protocols(CredHandle *handle, unsigned exprots)
170 {
171     SecPkgCred_SupportedProtocols protocols;
172     SECURITY_STATUS status;
173
174     status = pQueryCredentialsAttributesA(handle, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &protocols);
175     ok(status == SEC_E_OK, "QueryCredentialsAttributes failed: %08x\n", status);
176
177     if(exprots)
178         ok(protocols.grbitProtocol == exprots, "protocols.grbitProtocol = %x, expected %x\n", protocols.grbitProtocol, exprots);
179
180     trace("Supported protocols:\n");
181
182 #define X(flag, name) do { if(protocols.grbitProtocol & flag) { trace(name "\n"); protocols.grbitProtocol &= ~flag; } }while(0)
183     X(SP_PROT_SSL2_CLIENT, "SSL 2 client");
184     X(SP_PROT_SSL3_CLIENT, "SSL 3 client");
185     X(SP_PROT_TLS1_0_CLIENT, "TLS 1.0 client");
186     X(SP_PROT_TLS1_1_CLIENT, "TLS 1.1 client");
187     X(SP_PROT_TLS1_2_CLIENT, "TLS 1.2 client");
188 #undef X
189
190     if(protocols.grbitProtocol)
191         trace("Unknown flags: %x\n", protocols.grbitProtocol);
192 }
193
194 static void testAcquireSecurityContext(void)
195 {
196     BOOL has_schannel = FALSE;
197     SecPkgInfoA *package_info;
198     ULONG i;
199     SECURITY_STATUS st;
200     CredHandle cred;
201     TimeStamp exp;
202     SCHANNEL_CRED schanCred;
203     PCCERT_CONTEXT certs[2];
204     HCRYPTPROV csp;
205     static CHAR unisp_name_a[] = UNISP_NAME_A;
206     WCHAR ms_def_prov_w[MAX_PATH];
207     BOOL ret;
208     HCRYPTKEY key;
209     CRYPT_KEY_PROV_INFO keyProvInfo;
210
211     if (!pAcquireCredentialsHandleA || !pCertCreateCertificateContext ||
212         !pEnumerateSecurityPackagesA || !pFreeContextBuffer ||
213         !pFreeCredentialsHandle || !pCryptAcquireContextW)
214     {
215         win_skip("Needed functions are not available\n");
216         return;
217     }
218
219     if (SUCCEEDED(pEnumerateSecurityPackagesA(&i, &package_info)))
220     {
221         while(i--)
222         {
223             if (!strcmp(package_info[i].Name, unisp_name_a))
224             {
225                 has_schannel = TRUE;
226                 break;
227             }
228         }
229         pFreeContextBuffer(package_info);
230     }
231     if (!has_schannel)
232     {
233         skip("Schannel not available\n");
234         return;
235     }
236
237     lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
238
239     keyProvInfo.pwszContainerName = cspNameW;
240     keyProvInfo.pwszProvName = ms_def_prov_w;
241     keyProvInfo.dwProvType = PROV_RSA_FULL;
242     keyProvInfo.dwFlags = 0;
243     keyProvInfo.cProvParam = 0;
244     keyProvInfo.rgProvParam = NULL;
245     keyProvInfo.dwKeySpec = AT_SIGNATURE;
246
247     certs[0] = pCertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
248      sizeof(bigCert));
249     certs[1] = pCertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
250      sizeof(selfSignedCert));
251
252     SetLastError(0xdeadbeef);
253     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
254      CRYPT_DELETEKEYSET);
255     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
256     {
257         /* WinMe would crash on some tests */
258         win_skip("CryptAcquireContextW is not implemented\n");
259         return;
260     }
261
262     st = pAcquireCredentialsHandleA(NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL,
263      NULL);
264     ok(st == SEC_E_SECPKG_NOT_FOUND,
265      "Expected SEC_E_SECPKG_NOT_FOUND, got %08x\n", st);
266     if (0)
267     {
268         /* Crashes on Win2K */
269         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, 0, NULL, NULL, NULL,
270          NULL, NULL, NULL);
271         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
272
273         /* Crashes on WinNT */
274         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_BOTH, NULL,
275          NULL, NULL, NULL, NULL, NULL);
276         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
277
278         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
279          NULL, NULL, NULL, NULL, NULL, NULL);
280         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
281
282         /* Crashes */
283         pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
284          NULL, NULL, NULL, NULL, NULL, NULL);
285     }
286     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
287      NULL, NULL, NULL, NULL, &cred, NULL);
288     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
289     if(st == SEC_E_OK) {
290         st = pQueryCredentialsAttributesA(&cred, SECPKG_ATTR_SUPPORTED_PROTOCOLS, NULL);
291         ok(st == SEC_E_INTERNAL_ERROR, "QueryCredentialsAttributes failed: %08x, expected SEC_E_INTERNAL_ERROR\n", st);
292
293         test_supported_protocols(&cred, 0);
294         pFreeCredentialsHandle(&cred);
295     }
296     memset(&cred, 0, sizeof(cred));
297     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
298      NULL, NULL, NULL, NULL, &cred, &exp);
299     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
300     /* expriy is indeterminate in win2k3 */
301     trace("expiry: %08x%08x\n", exp.HighPart, exp.LowPart);
302     pFreeCredentialsHandle(&cred);
303
304     /* Bad version in SCHANNEL_CRED */
305     memset(&schanCred, 0, sizeof(schanCred));
306     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
307      NULL, &schanCred, NULL, NULL, NULL, NULL);
308     ok(st == SEC_E_INTERNAL_ERROR ||
309        st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */ ||
310        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
311     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
312      NULL, &schanCred, NULL, NULL, NULL, NULL);
313     ok(st == SEC_E_INTERNAL_ERROR ||
314        st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */ ||
315        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
316
317     /* No cert in SCHANNEL_CRED succeeds for outbound.. */
318     schanCred.dwVersion = SCHANNEL_CRED_VERSION;
319     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
320      NULL, &schanCred, NULL, NULL, &cred, NULL);
321     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
322     pFreeCredentialsHandle(&cred);
323     /* but fails for inbound. */
324     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
325      NULL, &schanCred, NULL, NULL, &cred, NULL);
326     ok(st == SEC_E_NO_CREDENTIALS ||
327        st == SEC_E_OK /* Vista/win2k8 */,
328        "Expected SEC_E_NO_CREDENTIALS or SEC_E_OK, got %08x\n", st);
329
330     if (0)
331     {
332         /* Crashes with bad paCred pointer */
333         schanCred.cCreds = 1;
334         pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
335          NULL, &schanCred, NULL, NULL, NULL, NULL);
336     }
337
338     /* Bogus cert in SCHANNEL_CRED. Windows fails with
339      * SEC_E_UNKNOWN_CREDENTIALS, but I'll accept SEC_E_NO_CREDENTIALS too.
340      */
341     schanCred.cCreds = 1;
342     schanCred.paCred = &certs[0];
343     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
344      NULL, &schanCred, NULL, NULL, NULL, NULL);
345     ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
346        st == SEC_E_NO_CREDENTIALS ||
347        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
348     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
349      NULL, &schanCred, NULL, NULL, NULL, NULL);
350     ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
351        st == SEC_E_NO_CREDENTIALS ||
352        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
353
354     /* Good cert, but missing private key. Windows fails with
355      * SEC_E_NO_CREDENTIALS, but I'll accept SEC_E_UNKNOWN_CREDENTIALS too.
356      */
357     schanCred.cCreds = 1;
358     schanCred.paCred = &certs[1];
359     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
360      NULL, &schanCred, NULL, NULL, &cred, NULL);
361     ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS ||
362        st == SEC_E_INTERNAL_ERROR, /* win2k */
363      "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
364      "or SEC_E_INTERNAL_ERROR, got %08x\n", st);
365     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
366      NULL, &schanCred, NULL, NULL, NULL, NULL);
367     ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS ||
368        st == SEC_E_INTERNAL_ERROR, /* win2k */
369      "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
370      "or SEC_E_INTERNAL_ERROR, got %08x\n", st);
371
372     /* Good cert, with CRYPT_KEY_PROV_INFO set before it's had a key loaded. */
373     if (pCertSetCertificateContextProperty)
374     {
375         ret = pCertSetCertificateContextProperty(certs[1],
376               CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo);
377         schanCred.dwVersion = SCH_CRED_V3;
378         ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
379         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
380              NULL, &schanCred, NULL, NULL, &cred, NULL);
381         ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
382            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, 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_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
386            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
387     }
388
389     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
390      CRYPT_NEWKEYSET);
391     ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
392     ret = 0;
393     if (pCryptImportKey)
394     {
395         ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
396         ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
397     }
398     if (ret)
399     {
400         PCCERT_CONTEXT tmp;
401
402         if (0)
403         {
404             /* Crashes */
405             pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
406              NULL, &schanCred, NULL, NULL, NULL, NULL);
407
408             /* Crashes on WinNT */
409             /* Good cert with private key, bogus version */
410             schanCred.dwVersion = SCH_CRED_V1;
411             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
412                 NULL, &schanCred, NULL, NULL, &cred, NULL);
413             ok(st == SEC_E_INTERNAL_ERROR ||
414                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
415                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
416             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
417                 NULL, &schanCred, NULL, NULL, &cred, NULL);
418             ok(st == SEC_E_INTERNAL_ERROR ||
419                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
420                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
421             schanCred.dwVersion = SCH_CRED_V2;
422             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
423                 NULL, &schanCred, NULL, NULL, &cred, NULL);
424             ok(st == SEC_E_INTERNAL_ERROR ||
425                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
426                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
427             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
428                 NULL, &schanCred, NULL, NULL, &cred, NULL);
429             ok(st == SEC_E_INTERNAL_ERROR ||
430                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
431                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
432         }
433
434         /* Succeeds on V3 or higher */
435         schanCred.dwVersion = SCH_CRED_V3;
436         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
437          NULL, &schanCred, NULL, NULL, &cred, NULL);
438         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
439         pFreeCredentialsHandle(&cred);
440         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
441          NULL, &schanCred, NULL, NULL, &cred, NULL);
442         ok(st == SEC_E_OK ||
443            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
444            "AcquireCredentialsHandleA failed: %08x\n", st);
445         pFreeCredentialsHandle(&cred);
446         schanCred.dwVersion = SCHANNEL_CRED_VERSION;
447         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
448          NULL, &schanCred, NULL, NULL, &cred, NULL);
449         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
450         pFreeCredentialsHandle(&cred);
451         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
452          NULL, &schanCred, NULL, NULL, &cred, NULL);
453         ok(st == SEC_E_OK ||
454            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
455            "AcquireCredentialsHandleA failed: %08x\n", st);
456         if (st == SEC_E_OK) test_strength(&cred);
457         pFreeCredentialsHandle(&cred);
458
459         /* How about more than one cert? */
460         schanCred.cCreds = 2;
461         schanCred.paCred = certs;
462         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
463          NULL, &schanCred, NULL, NULL, &cred, NULL);
464         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
465            st == SEC_E_NO_CREDENTIALS /* Vista/win2k8 */ ||
466            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
467         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
468          NULL, &schanCred, NULL, NULL, &cred, NULL);
469         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
470            st == SEC_E_NO_CREDENTIALS ||
471            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
472         tmp = certs[0];
473         certs[0] = certs[1];
474         certs[1] = tmp;
475         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
476          NULL, &schanCred, NULL, NULL, &cred, NULL);
477         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
478            st == SEC_E_NO_CREDENTIALS ||
479            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
480         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
481          NULL, &schanCred, NULL, NULL, &cred, NULL);
482         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
483          "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
484         /* FIXME: what about two valid certs? */
485
486         if (pCryptDestroyKey)
487             pCryptDestroyKey(key);
488     }
489
490     if (pCryptReleaseContext)
491         pCryptReleaseContext(csp, 0);
492     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
493      CRYPT_DELETEKEYSET);
494
495     if (pCertFreeCertificateContext)
496     {
497         pCertFreeCertificateContext(certs[0]);
498         pCertFreeCertificateContext(certs[1]);
499     }
500 }
501
502 static void test_remote_cert(PCCERT_CONTEXT remote_cert)
503 {
504     PCCERT_CONTEXT iter = NULL;
505     BOOL incl_remote = FALSE;
506     unsigned cert_cnt = 0;
507
508     ok(remote_cert->hCertStore != NULL, "hCertStore == NULL\n");
509
510     while((iter = pCertEnumCertificatesInStore(remote_cert->hCertStore, iter))) {
511         if(iter == remote_cert)
512             incl_remote = TRUE;
513         cert_cnt++;
514     }
515
516     ok(cert_cnt == 2, "cert_cnt = %u\n", cert_cnt);
517     ok(incl_remote, "context does not contain cert itself\n");
518 }
519
520 static const char http_request[] = "HEAD /test.html HTTP/1.1\r\nHost: www.codeweavers.com\r\nConnection: close\r\n\r\n";
521
522 static void init_cred(SCHANNEL_CRED *cred)
523 {
524     cred->dwVersion = SCHANNEL_CRED_VERSION;
525     cred->cCreds = 0;
526     cred->paCred = 0;
527     cred->hRootStore = NULL;
528     cred->cMappers = 0;
529     cred->aphMappers = NULL;
530     cred->cSupportedAlgs = 0;
531     cred->palgSupportedAlgs = NULL;
532     cred->grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
533     cred->dwMinimumCipherStrength = 0;
534     cred->dwMaximumCipherStrength = 0;
535     cred->dwSessionLifespan = 0;
536     cred->dwFlags = 0;
537 }
538
539 static void init_buffers(SecBufferDesc *desc, unsigned count, unsigned size)
540 {
541     desc->ulVersion = SECBUFFER_VERSION;
542     desc->cBuffers = count;
543     desc->pBuffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count*sizeof(SecBuffer));
544
545     desc->pBuffers[0].cbBuffer = size;
546     desc->pBuffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, size);
547 }
548
549 static void reset_buffers(SecBufferDesc *desc)
550 {
551     unsigned i;
552
553     for (i = 0; i < desc->cBuffers; ++i)
554     {
555         desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
556         if (i > 0)
557         {
558             desc->pBuffers[i].cbBuffer = 0;
559             desc->pBuffers[i].pvBuffer = NULL;
560         }
561     }
562 }
563
564 static void free_buffers(SecBufferDesc *desc)
565 {
566     HeapFree(GetProcessHeap(), 0, desc->pBuffers[0].pvBuffer);
567     HeapFree(GetProcessHeap(), 0, desc->pBuffers);
568 }
569
570 static int receive_data(SOCKET sock, SecBuffer *buf)
571 {
572     unsigned received = 0;
573
574     while (1)
575     {
576         unsigned char *data = buf->pvBuffer;
577         unsigned expected = 0;
578         int ret;
579
580         ret = recv(sock, (char *)data+received, buf->cbBuffer-received, 0);
581         if (ret == -1)
582         {
583             skip("recv failed\n");
584             return -1;
585         }
586         else if(ret == 0)
587         {
588             skip("connection closed\n");
589             return -1;
590         }
591         received += ret;
592
593         while (expected < received)
594         {
595             unsigned frame_size = 5 + ((data[3]<<8) | data[4]);
596             expected += frame_size;
597             data += frame_size;
598         }
599
600         if (expected == received)
601             break;
602     }
603
604     buf->cbBuffer = received;
605
606     return received;
607 }
608
609 static void test_communication(void)
610 {
611     int ret;
612
613     WSADATA wsa_data;
614     SOCKET sock;
615     struct hostent *host;
616     struct sockaddr_in addr;
617
618     SECURITY_STATUS status;
619     ULONG attrs;
620
621     SCHANNEL_CRED cred;
622     CredHandle cred_handle;
623     CtxtHandle context;
624     SecPkgContext_StreamSizes sizes;
625     SecPkgContext_ConnectionInfo conn_info;
626     CERT_CONTEXT *cert;
627
628     SecBufferDesc buffers[2];
629     SecBuffer *buf;
630     unsigned buf_size = 4000;
631     unsigned char *data;
632     unsigned data_size;
633
634     if (!pAcquireCredentialsHandleA || !pFreeCredentialsHandle ||
635         !pInitializeSecurityContextA || !pDeleteSecurityContext ||
636         !pQueryContextAttributesA || !pDecryptMessage || !pEncryptMessage)
637     {
638         skip("Required secur32 functions not available\n");
639         return;
640     }
641
642     /* Create a socket and connect to www.codeweavers.com */
643     ret = WSAStartup(0x0202, &wsa_data);
644     if (ret)
645     {
646         skip("Can't init winsock 2.2\n");
647         return;
648     }
649
650     host = gethostbyname("www.codeweavers.com");
651     if (!host)
652     {
653         skip("Can't resolve www.codeweavers.com\n");
654         return;
655     }
656
657     addr.sin_family = host->h_addrtype;
658     addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
659     addr.sin_port = htons(443);
660     sock = socket(host->h_addrtype, SOCK_STREAM, 0);
661     if (sock == SOCKET_ERROR)
662     {
663         skip("Can't create socket\n");
664         return;
665     }
666
667     ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
668     if (ret == SOCKET_ERROR)
669     {
670         skip("Can't connect to www.codeweavers.com\n");
671         return;
672     }
673
674     /* Create client credentials */
675     init_cred(&cred);
676     cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
677
678     status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
679         &cred, NULL, NULL, &cred_handle, NULL);
680     ok(status == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", status);
681     if (status != SEC_E_OK) return;
682
683     test_supported_protocols(&cred_handle, SP_PROT_SSL3_CLIENT);
684
685     /* Initialize the connection */
686     init_buffers(&buffers[0], 4, buf_size);
687     init_buffers(&buffers[1], 4, buf_size);
688
689     buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
690     status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
691         ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
692         0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
693     ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
694
695     buffers[1].cBuffers = 1;
696     buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
697     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
698             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
699             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
700     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
701
702     buffers[0].pBuffers[0].cbBuffer = buf_size;
703
704     status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
705             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
706             0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
707     ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
708
709     buf = &buffers[0].pBuffers[0];
710     send(sock, buf->pvBuffer, buf->cbBuffer, 0);
711     buf->cbBuffer = buf_size;
712
713     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
714             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
715             0, 0, NULL, 0, NULL, &buffers[0], &attrs, NULL);
716     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
717     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
718     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
719
720     buffers[1].cBuffers = 4;
721     buffers[1].pBuffers[0].cbBuffer = 0;
722
723     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
724             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
725             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
726     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
727     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
728     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
729
730     buf = &buffers[1].pBuffers[0];
731     buf->cbBuffer = buf_size;
732     ret = receive_data(sock, buf);
733     if (ret == -1)
734         return;
735
736     buffers[1].pBuffers[0].cbBuffer = 4;
737     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
738             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
739             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
740     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
741     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
742     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
743
744     buffers[1].pBuffers[0].cbBuffer = 5;
745     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
746             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
747             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
748     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
749     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
750     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
751
752     buffers[1].pBuffers[0].cbBuffer = ret;
753     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
754             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
755             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
756     buffers[1].pBuffers[0].cbBuffer = buf_size;
757     while (status == SEC_I_CONTINUE_NEEDED)
758     {
759         buf = &buffers[0].pBuffers[0];
760         send(sock, buf->pvBuffer, buf->cbBuffer, 0);
761         buf->cbBuffer = buf_size;
762
763         buf = &buffers[1].pBuffers[0];
764         ret = receive_data(sock, buf);
765         if (ret == -1)
766             return;
767
768         buf->BufferType = SECBUFFER_TOKEN;
769
770         status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
771             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
772             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
773         buffers[1].pBuffers[0].cbBuffer = buf_size;
774     }
775
776     ok(status == SEC_E_OK || broken(status == SEC_E_INVALID_TOKEN) /* WinNT */,
777         "InitializeSecurityContext failed: %08x\n", status);
778     if(status != SEC_E_OK) {
779         win_skip("Handshake failed\n");
780         return;
781     }
782
783     status = pQueryContextAttributesA(&context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
784     ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed: %08x\n", status);
785     if(status == SEC_E_OK) {
786         test_remote_cert(cert);
787         pCertFreeCertificateContext(cert);
788     }
789
790     status = pQueryContextAttributesA(&context, SECPKG_ATTR_CONNECTION_INFO, (void*)&conn_info);
791     ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_CONNECTION_INFO) failed: %08x\n", status);
792     if(status == SEC_E_OK) {
793         ok(conn_info.dwCipherStrength == 128, "conn_info.dwCipherStrength = %d\n", conn_info.dwCipherStrength);
794         ok(conn_info.dwHashStrength >= 128, "conn_info.dwHashStrength = %d\n", conn_info.dwHashStrength);
795     }
796
797     pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
798
799     reset_buffers(&buffers[0]);
800
801     /* Send a simple request so we get data for testing DecryptMessage */
802     buf = &buffers[0].pBuffers[0];
803     data = buf->pvBuffer;
804     buf->BufferType = SECBUFFER_STREAM_HEADER;
805     buf->cbBuffer = sizes.cbHeader;
806     ++buf;
807     buf->BufferType = SECBUFFER_DATA;
808     buf->pvBuffer = data + sizes.cbHeader;
809     buf->cbBuffer = sizeof(http_request) - 1;
810     memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
811     ++buf;
812     buf->BufferType = SECBUFFER_STREAM_TRAILER;
813     buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
814     buf->cbBuffer = sizes.cbTrailer;
815
816     status = pEncryptMessage(&context, 0, &buffers[0], 0);
817     ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
818     if (status != SEC_E_OK)
819         return;
820
821     buf = &buffers[0].pBuffers[0];
822     send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
823
824     reset_buffers(&buffers[0]);
825     buf->cbBuffer = buf_size;
826     data_size = receive_data(sock, buf);
827
828     /* Too few buffers */
829     --buffers[0].cBuffers;
830     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
831     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
832
833     /* No data buffer */
834     ++buffers[0].cBuffers;
835     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
836     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
837
838     /* Two data buffers */
839     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
840     buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
841     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
842     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
843
844     /* Too few empty buffers */
845     buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
846     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
847     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
848
849     /* Incomplete data */
850     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
851     buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
852     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
853     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
854     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
855     ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
856
857     buffers[0].pBuffers[0].cbBuffer = data_size;
858     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
859     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
860     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
861     ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
862     if (status == SEC_E_OK)
863     {
864         ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
865         ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
866         ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected third buffer to be SECBUFFER_STREAM_TRAILER\n");
867
868         data = buffers[0].pBuffers[1].pvBuffer;
869         data[buffers[0].pBuffers[1].cbBuffer] = 0;
870     }
871
872     pDeleteSecurityContext(&context);
873     pFreeCredentialsHandle(&cred_handle);
874
875     free_buffers(&buffers[0]);
876     free_buffers(&buffers[1]);
877
878     closesocket(sock);
879 }
880
881 START_TEST(schannel)
882 {
883     InitFunctionPtrs();
884
885     testAcquireSecurityContext();
886     test_communication();
887
888     if(secdll)
889         FreeLibrary(secdll);
890     if(crypt32dll)
891         FreeLibrary(crypt32dll);
892 }