jscript: Rename jsheap_t to heap_pool_t.
[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 testAcquireSecurityContext(void)
170 {
171     BOOL has_schannel = FALSE;
172     SecPkgInfoA *package_info;
173     ULONG i;
174     SECURITY_STATUS st;
175     CredHandle cred;
176     TimeStamp exp;
177     SCHANNEL_CRED schanCred;
178     PCCERT_CONTEXT certs[2];
179     HCRYPTPROV csp;
180     static CHAR unisp_name_a[] = UNISP_NAME_A;
181     WCHAR ms_def_prov_w[MAX_PATH];
182     BOOL ret;
183     HCRYPTKEY key;
184     CRYPT_KEY_PROV_INFO keyProvInfo;
185
186     if (!pAcquireCredentialsHandleA || !pCertCreateCertificateContext ||
187         !pEnumerateSecurityPackagesA || !pFreeContextBuffer ||
188         !pFreeCredentialsHandle || !pCryptAcquireContextW)
189     {
190         win_skip("Needed functions are not available\n");
191         return;
192     }
193
194     if (SUCCEEDED(pEnumerateSecurityPackagesA(&i, &package_info)))
195     {
196         while(i--)
197         {
198             if (!strcmp(package_info[i].Name, unisp_name_a))
199             {
200                 has_schannel = TRUE;
201                 break;
202             }
203         }
204         pFreeContextBuffer(package_info);
205     }
206     if (!has_schannel)
207     {
208         skip("Schannel not available\n");
209         return;
210     }
211
212     lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
213
214     keyProvInfo.pwszContainerName = cspNameW;
215     keyProvInfo.pwszProvName = ms_def_prov_w;
216     keyProvInfo.dwProvType = PROV_RSA_FULL;
217     keyProvInfo.dwFlags = 0;
218     keyProvInfo.cProvParam = 0;
219     keyProvInfo.rgProvParam = NULL;
220     keyProvInfo.dwKeySpec = AT_SIGNATURE;
221
222     certs[0] = pCertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
223      sizeof(bigCert));
224     certs[1] = pCertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
225      sizeof(selfSignedCert));
226
227     SetLastError(0xdeadbeef);
228     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
229      CRYPT_DELETEKEYSET);
230     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
231     {
232         /* WinMe would crash on some tests */
233         win_skip("CryptAcquireContextW is not implemented\n");
234         return;
235     }
236
237     st = pAcquireCredentialsHandleA(NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL,
238      NULL);
239     ok(st == SEC_E_SECPKG_NOT_FOUND,
240      "Expected SEC_E_SECPKG_NOT_FOUND, got %08x\n", st);
241     if (0)
242     {
243         /* Crashes on Win2K */
244         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, 0, NULL, NULL, NULL,
245          NULL, NULL, NULL);
246         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
247
248         /* Crashes on WinNT */
249         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_BOTH, NULL,
250          NULL, NULL, NULL, NULL, NULL);
251         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
252
253         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
254          NULL, NULL, NULL, NULL, NULL, NULL);
255         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
256
257         /* Crashes */
258         pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
259          NULL, NULL, NULL, NULL, NULL, NULL);
260     }
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);
264     if(st == SEC_E_OK)
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);
273
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        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %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        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
286
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);
299
300     if (0)
301     {
302         /* Crashes with bad paCred pointer */
303         schanCred.cCreds = 1;
304         pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
305          NULL, &schanCred, NULL, NULL, NULL, NULL);
306     }
307
308     /* Bogus cert in SCHANNEL_CRED. Windows fails with
309      * SEC_E_UNKNOWN_CREDENTIALS, but I'll accept SEC_E_NO_CREDENTIALS too.
310      */
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 ||
316        st == SEC_E_NO_CREDENTIALS ||
317        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
318     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
319      NULL, &schanCred, NULL, NULL, NULL, NULL);
320     ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
321        st == SEC_E_NO_CREDENTIALS ||
322        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
323
324     /* Good cert, but missing private key. Windows fails with
325      * SEC_E_NO_CREDENTIALS, but I'll accept SEC_E_UNKNOWN_CREDENTIALS too.
326      */
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);
341
342     /* Good cert, with CRYPT_KEY_PROV_INFO set before it's had a key loaded. */
343     if (pCertSetCertificateContextProperty)
344     {
345         ret = pCertSetCertificateContextProperty(certs[1],
346               CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo);
347         schanCred.dwVersion = SCH_CRED_V3;
348         ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
349         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
350              NULL, &schanCred, NULL, NULL, &cred, NULL);
351         ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
352            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
353         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
354              NULL, &schanCred, NULL, NULL, &cred, NULL);
355         ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
356            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
357     }
358
359     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
360      CRYPT_NEWKEYSET);
361     ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
362     ret = 0;
363     if (pCryptImportKey)
364     {
365         ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
366         ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
367     }
368     if (ret)
369     {
370         PCCERT_CONTEXT tmp;
371
372         if (0)
373         {
374             /* Crashes */
375             pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
376              NULL, &schanCred, NULL, NULL, NULL, NULL);
377
378             /* Crashes on WinNT */
379             /* Good cert with private key, bogus version */
380             schanCred.dwVersion = SCH_CRED_V1;
381             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
382                 NULL, &schanCred, NULL, NULL, &cred, NULL);
383             ok(st == SEC_E_INTERNAL_ERROR ||
384                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
385                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
386             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
387                 NULL, &schanCred, NULL, NULL, &cred, NULL);
388             ok(st == SEC_E_INTERNAL_ERROR ||
389                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
390                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
391             schanCred.dwVersion = SCH_CRED_V2;
392             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
393                 NULL, &schanCred, NULL, NULL, &cred, NULL);
394             ok(st == SEC_E_INTERNAL_ERROR ||
395                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
396                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
397             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
398                 NULL, &schanCred, NULL, NULL, &cred, NULL);
399             ok(st == SEC_E_INTERNAL_ERROR ||
400                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
401                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
402         }
403
404         /* Succeeds on V3 or higher */
405         schanCred.dwVersion = SCH_CRED_V3;
406         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
407          NULL, &schanCred, NULL, NULL, &cred, NULL);
408         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
409         pFreeCredentialsHandle(&cred);
410         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
411          NULL, &schanCred, NULL, NULL, &cred, NULL);
412         ok(st == SEC_E_OK ||
413            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
414            "AcquireCredentialsHandleA failed: %08x\n", st);
415         pFreeCredentialsHandle(&cred);
416         schanCred.dwVersion = SCHANNEL_CRED_VERSION;
417         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
418          NULL, &schanCred, NULL, NULL, &cred, NULL);
419         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
420         pFreeCredentialsHandle(&cred);
421         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
422          NULL, &schanCred, NULL, NULL, &cred, NULL);
423         ok(st == SEC_E_OK ||
424            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
425            "AcquireCredentialsHandleA failed: %08x\n", st);
426         if (st == SEC_E_OK) test_strength(&cred);
427         pFreeCredentialsHandle(&cred);
428
429         /* How about more than one cert? */
430         schanCred.cCreds = 2;
431         schanCred.paCred = certs;
432         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
433          NULL, &schanCred, NULL, NULL, &cred, NULL);
434         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
435            st == SEC_E_NO_CREDENTIALS /* Vista/win2k8 */ ||
436            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
437         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
438          NULL, &schanCred, NULL, NULL, &cred, NULL);
439         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
440            st == SEC_E_NO_CREDENTIALS ||
441            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
442         tmp = certs[0];
443         certs[0] = certs[1];
444         certs[1] = tmp;
445         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
446          NULL, &schanCred, NULL, NULL, &cred, NULL);
447         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
448            st == SEC_E_NO_CREDENTIALS ||
449            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
450         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
451          NULL, &schanCred, NULL, NULL, &cred, NULL);
452         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
453          "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
454         /* FIXME: what about two valid certs? */
455
456         if (pCryptDestroyKey)
457             pCryptDestroyKey(key);
458     }
459
460     if (pCryptReleaseContext)
461         pCryptReleaseContext(csp, 0);
462     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
463      CRYPT_DELETEKEYSET);
464
465     if (pCertFreeCertificateContext)
466     {
467         pCertFreeCertificateContext(certs[0]);
468         pCertFreeCertificateContext(certs[1]);
469     }
470 }
471
472 static void test_remote_cert(PCCERT_CONTEXT remote_cert)
473 {
474     PCCERT_CONTEXT iter = NULL;
475     BOOL incl_remote = FALSE;
476     unsigned cert_cnt = 0;
477
478     ok(remote_cert->hCertStore != NULL, "hCertStore == NULL\n");
479
480     while((iter = pCertEnumCertificatesInStore(remote_cert->hCertStore, iter))) {
481         if(iter == remote_cert)
482             incl_remote = TRUE;
483         cert_cnt++;
484     }
485
486     ok(cert_cnt == 2, "cert_cnt = %u\n", cert_cnt);
487     ok(incl_remote, "context does not contain cert itself\n");
488 }
489
490 static const char http_request[] = "HEAD /test.html HTTP/1.1\r\nHost: www.codeweavers.com\r\nConnection: close\r\n\r\n";
491
492 static void init_cred(SCHANNEL_CRED *cred)
493 {
494     cred->dwVersion = SCHANNEL_CRED_VERSION;
495     cred->cCreds = 0;
496     cred->paCred = 0;
497     cred->hRootStore = NULL;
498     cred->cMappers = 0;
499     cred->aphMappers = NULL;
500     cred->cSupportedAlgs = 0;
501     cred->palgSupportedAlgs = NULL;
502     cred->grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
503     cred->dwMinimumCipherStrength = 0;
504     cred->dwMaximumCipherStrength = 0;
505     cred->dwSessionLifespan = 0;
506     cred->dwFlags = 0;
507 }
508
509 static void init_buffers(SecBufferDesc *desc, unsigned count, unsigned size)
510 {
511     desc->ulVersion = SECBUFFER_VERSION;
512     desc->cBuffers = count;
513     desc->pBuffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count*sizeof(SecBuffer));
514
515     desc->pBuffers[0].cbBuffer = size;
516     desc->pBuffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, size);
517 }
518
519 static void reset_buffers(SecBufferDesc *desc)
520 {
521     unsigned i;
522
523     for (i = 0; i < desc->cBuffers; ++i)
524     {
525         desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
526         if (i > 0)
527         {
528             desc->pBuffers[i].cbBuffer = 0;
529             desc->pBuffers[i].pvBuffer = NULL;
530         }
531     }
532 }
533
534 static void free_buffers(SecBufferDesc *desc)
535 {
536     HeapFree(GetProcessHeap(), 0, desc->pBuffers[0].pvBuffer);
537     HeapFree(GetProcessHeap(), 0, desc->pBuffers);
538 }
539
540 static int receive_data(SOCKET sock, SecBuffer *buf)
541 {
542     unsigned received = 0;
543
544     while (1)
545     {
546         unsigned char *data = buf->pvBuffer;
547         unsigned expected = 0;
548         int ret;
549
550         ret = recv(sock, (char *)data+received, buf->cbBuffer-received, 0);
551         if (ret == -1)
552         {
553             skip("recv failed\n");
554             return -1;
555         }
556         else if(ret == 0)
557         {
558             skip("connection closed\n");
559             return -1;
560         }
561         received += ret;
562
563         while (expected < received)
564         {
565             unsigned frame_size = 5 + ((data[3]<<8) | data[4]);
566             expected += frame_size;
567             data += frame_size;
568         }
569
570         if (expected == received)
571             break;
572     }
573
574     buf->cbBuffer = received;
575
576     return received;
577 }
578
579 static void test_communication(void)
580 {
581     int ret;
582
583     WSADATA wsa_data;
584     SOCKET sock;
585     struct hostent *host;
586     struct sockaddr_in addr;
587
588     SECURITY_STATUS status;
589     ULONG attrs;
590
591     SCHANNEL_CRED cred;
592     CredHandle cred_handle;
593     CtxtHandle context;
594     SecPkgContext_StreamSizes sizes;
595     CERT_CONTEXT *cert;
596
597     SecBufferDesc buffers[2];
598     SecBuffer *buf;
599     unsigned buf_size = 4000;
600     unsigned char *data;
601     unsigned data_size;
602
603     if (!pAcquireCredentialsHandleA || !pFreeCredentialsHandle ||
604         !pInitializeSecurityContextA || !pDeleteSecurityContext ||
605         !pQueryContextAttributesA || !pDecryptMessage || !pEncryptMessage)
606     {
607         skip("Required secur32 functions not available\n");
608         return;
609     }
610
611     /* Create a socket and connect to www.codeweavers.com */
612     ret = WSAStartup(0x0202, &wsa_data);
613     if (ret)
614     {
615         skip("Can't init winsock 2.2\n");
616         return;
617     }
618
619     host = gethostbyname("www.codeweavers.com");
620     if (!host)
621     {
622         skip("Can't resolve www.codeweavers.com\n");
623         return;
624     }
625
626     addr.sin_family = host->h_addrtype;
627     addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
628     addr.sin_port = htons(443);
629     sock = socket(host->h_addrtype, SOCK_STREAM, 0);
630     if (sock == SOCKET_ERROR)
631     {
632         skip("Can't create socket\n");
633         return;
634     }
635
636     ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
637     if (ret == SOCKET_ERROR)
638     {
639         skip("Can't connect to www.codeweavers.com\n");
640         return;
641     }
642
643     /* Create client credentials */
644     init_cred(&cred);
645     cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
646
647     status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
648         &cred, NULL, NULL, &cred_handle, NULL);
649     ok(status == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", status);
650     if (status != SEC_E_OK) return;
651
652     /* Initialize the connection */
653     init_buffers(&buffers[0], 4, buf_size);
654     init_buffers(&buffers[1], 4, buf_size);
655
656     buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
657     status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
658         ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
659         0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
660     ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
661
662     buffers[1].cBuffers = 1;
663     buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
664     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
665             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
666             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
667     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
668
669     buffers[0].pBuffers[0].cbBuffer = buf_size;
670
671     status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
672             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
673             0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
674     ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
675
676     buf = &buffers[0].pBuffers[0];
677     send(sock, buf->pvBuffer, buf->cbBuffer, 0);
678     buf->cbBuffer = buf_size;
679
680     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
681             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
682             0, 0, NULL, 0, NULL, &buffers[0], &attrs, NULL);
683     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
684     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
685     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
686
687     buffers[1].cBuffers = 4;
688     buffers[1].pBuffers[0].cbBuffer = 0;
689
690     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
691             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
692             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
693     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
694     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
695     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
696
697     buf = &buffers[1].pBuffers[0];
698     buf->cbBuffer = buf_size;
699     ret = receive_data(sock, buf);
700     if (ret == -1)
701         return;
702
703     buffers[1].pBuffers[0].cbBuffer = 4;
704     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
705             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
706             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
707     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
708     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
709     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
710
711     buffers[1].pBuffers[0].cbBuffer = 5;
712     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
713             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
714             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
715     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
716     ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
717     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
718
719     buffers[1].pBuffers[0].cbBuffer = ret;
720     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
721             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
722             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
723     buffers[1].pBuffers[0].cbBuffer = buf_size;
724     while (status == SEC_I_CONTINUE_NEEDED)
725     {
726         buf = &buffers[0].pBuffers[0];
727         send(sock, buf->pvBuffer, buf->cbBuffer, 0);
728         buf->cbBuffer = buf_size;
729
730         buf = &buffers[1].pBuffers[0];
731         ret = receive_data(sock, buf);
732         if (ret == -1)
733             return;
734
735         buf->BufferType = SECBUFFER_TOKEN;
736
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         buffers[1].pBuffers[0].cbBuffer = buf_size;
741     }
742
743     ok(status == SEC_E_OK || broken(status == SEC_E_INVALID_TOKEN) /* WinNT */,
744         "InitializeSecurityContext failed: %08x\n", status);
745     if(status != SEC_E_OK) {
746         win_skip("Handshake failed\n");
747         return;
748     }
749
750     status = pQueryContextAttributesA(&context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
751     ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed: %08x\n", status);
752     if(status == SEC_E_OK) {
753         test_remote_cert(cert);
754         pCertFreeCertificateContext(cert);
755     }
756
757     pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
758
759     reset_buffers(&buffers[0]);
760
761     /* Send a simple request so we get data for testing DecryptMessage */
762     buf = &buffers[0].pBuffers[0];
763     data = buf->pvBuffer;
764     buf->BufferType = SECBUFFER_STREAM_HEADER;
765     buf->cbBuffer = sizes.cbHeader;
766     ++buf;
767     buf->BufferType = SECBUFFER_DATA;
768     buf->pvBuffer = data + sizes.cbHeader;
769     buf->cbBuffer = sizeof(http_request) - 1;
770     memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
771     ++buf;
772     buf->BufferType = SECBUFFER_STREAM_TRAILER;
773     buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
774     buf->cbBuffer = sizes.cbTrailer;
775
776     status = pEncryptMessage(&context, 0, &buffers[0], 0);
777     ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
778     if (status != SEC_E_OK)
779         return;
780
781     buf = &buffers[0].pBuffers[0];
782     send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
783
784     reset_buffers(&buffers[0]);
785     buf->cbBuffer = buf_size;
786     data_size = receive_data(sock, buf);
787
788     /* Too few buffers */
789     --buffers[0].cBuffers;
790     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
791     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
792
793     /* No data buffer */
794     ++buffers[0].cBuffers;
795     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
796     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
797
798     /* Two data buffers */
799     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
800     buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
801     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
802     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
803
804     /* Too few empty buffers */
805     buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
806     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
807     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
808
809     /* Incomplete data */
810     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
811     buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
812     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
813     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
814     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
815     ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
816
817     buffers[0].pBuffers[0].cbBuffer = data_size;
818     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
819     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
820     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
821     ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
822     if (status == SEC_E_OK)
823     {
824         ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
825         ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
826         ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected third buffer to be SECBUFFER_STREAM_TRAILER\n");
827
828         data = buffers[0].pBuffers[1].pvBuffer;
829         data[buffers[0].pBuffers[1].cbBuffer] = 0;
830     }
831
832     pDeleteSecurityContext(&context);
833     pFreeCredentialsHandle(&cred_handle);
834
835     free_buffers(&buffers[0]);
836     free_buffers(&buffers[1]);
837
838     closesocket(sock);
839 }
840
841 START_TEST(schannel)
842 {
843     InitFunctionPtrs();
844
845     testAcquireSecurityContext();
846     test_communication();
847
848     if(secdll)
849         FreeLibrary(secdll);
850     if(crypt32dll)
851         FreeLibrary(crypt32dll);
852 }