secur32: Add some more schannel tests.
[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
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);
53
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 };
91
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 };
116
117 static void InitFunctionPtrs(void)
118 {
119     HMODULE advapi32dll;
120
121     crypt32dll = LoadLibraryA("crypt32.dll");
122     secdll = LoadLibraryA("secur32.dll");
123     if(!secdll)
124         secdll = LoadLibraryA("security.dll");
125     advapi32dll = GetModuleHandleA("advapi32.dll");
126
127 #define GET_PROC(h, func)  p ## func = (void*)GetProcAddress(h, #func)
128
129     if(secdll)
130     {
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);
141     }
142
143     GET_PROC(advapi32dll, CryptAcquireContextW);
144     GET_PROC(advapi32dll, CryptDestroyKey);
145     GET_PROC(advapi32dll, CryptImportKey);
146     GET_PROC(advapi32dll, CryptReleaseContext);
147
148     GET_PROC(crypt32dll, CertFreeCertificateContext);
149     GET_PROC(crypt32dll, CertSetCertificateContextProperty);
150     GET_PROC(crypt32dll, CertCreateCertificateContext);
151
152 #undef GET_PROC
153 }
154
155 static void test_strength(PCredHandle handle)
156 {
157     SecPkgCred_CipherStrengths strength = {-1,-1};
158     SECURITY_STATUS st;
159
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);
165 }
166
167 static void testAcquireSecurityContext(void)
168 {
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;
183
184     if (!pAcquireCredentialsHandleA || !pCertCreateCertificateContext ||
185         !pEnumerateSecurityPackagesA || !pFreeContextBuffer ||
186         !pFreeCredentialsHandle || !pCryptAcquireContextW)
187     {
188         win_skip("Needed functions are not available\n");
189         return;
190     }
191
192     if (SUCCEEDED(pEnumerateSecurityPackagesA(&i, &package_info)))
193     {
194         while(i--)
195         {
196             if (!strcmp(package_info[i].Name, unisp_name_a))
197             {
198                 has_schannel = TRUE;
199                 break;
200             }
201         }
202         pFreeContextBuffer(package_info);
203     }
204     if (!has_schannel)
205     {
206         skip("Schannel not available\n");
207         return;
208     }
209
210     lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
211
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;
219
220     certs[0] = pCertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
221      sizeof(bigCert));
222     certs[1] = pCertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
223      sizeof(selfSignedCert));
224
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)
229     {
230         /* WinMe would crash on some tests */
231         win_skip("CryptAcquireContextW is not implemented\n");
232         return;
233     }
234
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)
240     {
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",
245          st);
246     }
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",
250      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",
254      st);
255     if (0)
256     {
257         /* Crashes */
258         st = 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        "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
281     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
282      NULL, &schanCred, NULL, NULL, NULL, NULL);
283     ok(st == SEC_E_INTERNAL_ERROR ||
284        st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
285        "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
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         st = 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 || st == SEC_E_NO_CREDENTIALS,
316      "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
317      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 || st == SEC_E_NO_CREDENTIALS,
321      "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
322      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         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
349              NULL, &schanCred, NULL, NULL, &cred, NULL);
350         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
351            "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
352         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
353              NULL, &schanCred, NULL, NULL, &cred, NULL);
354         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
355            "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
356     }
357
358     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
359      CRYPT_NEWKEYSET);
360     ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
361     ret = 0;
362     if (pCryptImportKey)
363     {
364         ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
365         ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
366     }
367     if (ret)
368     {
369         PCCERT_CONTEXT tmp;
370
371         if (0)
372         {
373             /* Crashes */
374             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
375              NULL, &schanCred, NULL, NULL, NULL, NULL);
376         }
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);
400
401         /* Succeeds on V3 or higher */
402         schanCred.dwVersion = SCH_CRED_V3;
403         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
404          NULL, &schanCred, NULL, NULL, &cred, NULL);
405         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
406         pFreeCredentialsHandle(&cred);
407         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
408          NULL, &schanCred, NULL, NULL, &cred, NULL);
409         ok(st == SEC_E_OK ||
410            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
411            "AcquireCredentialsHandleA failed: %08x\n", st);
412         pFreeCredentialsHandle(&cred);
413         schanCred.dwVersion = SCHANNEL_CRED_VERSION;
414         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
415          NULL, &schanCred, NULL, NULL, &cred, NULL);
416         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
417         pFreeCredentialsHandle(&cred);
418         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
419          NULL, &schanCred, NULL, NULL, &cred, NULL);
420         ok(st == SEC_E_OK ||
421            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
422            "AcquireCredentialsHandleA failed: %08x\n", st);
423         if (st == SEC_E_OK) test_strength(&cred);
424         pFreeCredentialsHandle(&cred);
425
426         /* How about more than one cert? */
427         schanCred.cCreds = 2;
428         schanCred.paCred = certs;
429         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
430          NULL, &schanCred, NULL, NULL, &cred, NULL);
431         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
432            st == SEC_E_NO_CREDENTIALS /* Vista/win2k8 */,
433            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n", st);
434         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
435          NULL, &schanCred, NULL, NULL, &cred, NULL);
436         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
437            st == SEC_E_NO_CREDENTIALS,
438            "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
439         tmp = certs[0];
440         certs[0] = certs[1];
441         certs[1] = tmp;
442         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
443          NULL, &schanCred, NULL, NULL, &cred, NULL);
444         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
445            st == SEC_E_NO_CREDENTIALS,
446            "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
447         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
448          NULL, &schanCred, NULL, NULL, &cred, NULL);
449         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
450          "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
451         /* FIXME: what about two valid certs? */
452
453         if (pCryptDestroyKey)
454             pCryptDestroyKey(key);
455     }
456
457     if (pCryptReleaseContext)
458         pCryptReleaseContext(csp, 0);
459     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
460      CRYPT_DELETEKEYSET);
461
462     if (pCertFreeCertificateContext)
463     {
464         pCertFreeCertificateContext(certs[0]);
465         pCertFreeCertificateContext(certs[1]);
466     }
467 }
468
469 static const char http_request[] = "HEAD /test.html HTTP/1.1\r\nHost: www.codeweavers.com\r\nConnection: close\r\n\r\n";
470
471 static void init_cred(SCHANNEL_CRED *cred)
472 {
473     cred->dwVersion = SCHANNEL_CRED_VERSION;
474     cred->cCreds = 0;
475     cred->paCred = 0;
476     cred->hRootStore = NULL;
477     cred->cMappers = 0;
478     cred->aphMappers = NULL;
479     cred->cSupportedAlgs = 0;
480     cred->palgSupportedAlgs = NULL;
481     cred->grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
482     cred->dwMinimumCipherStrength = 0;
483     cred->dwMaximumCipherStrength = 0;
484     cred->dwSessionLifespan = 0;
485     cred->dwFlags = 0;
486 }
487
488 static void init_buffers(SecBufferDesc *desc, unsigned count, unsigned size)
489 {
490     desc->ulVersion = SECBUFFER_VERSION;
491     desc->cBuffers = count;
492     desc->pBuffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count*sizeof(SecBuffer));
493
494     desc->pBuffers[0].cbBuffer = size;
495     desc->pBuffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, size);
496 }
497
498 static void reset_buffers(SecBufferDesc *desc)
499 {
500     unsigned i;
501
502     for (i = 0; i < desc->cBuffers; ++i)
503     {
504         desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
505         if (i > 0)
506         {
507             desc->pBuffers[i].cbBuffer = 0;
508             desc->pBuffers[i].pvBuffer = NULL;
509         }
510     }
511 }
512
513 static void free_buffers(SecBufferDesc *desc)
514 {
515     HeapFree(GetProcessHeap(), 0, desc->pBuffers[0].pvBuffer);
516     HeapFree(GetProcessHeap(), 0, desc->pBuffers);
517 }
518
519 static int receive_data(SOCKET sock, SecBuffer *buf)
520 {
521     unsigned received = 0;
522
523     while (1)
524     {
525         unsigned char *data = buf->pvBuffer;
526         unsigned expected = 0;
527         int ret;
528
529         ret = recv(sock, (char *)data+received, buf->cbBuffer-received, 0);
530         if (ret == -1)
531         {
532             skip("recv failed\n");
533             return -1;
534         }
535         else if(ret == 0)
536         {
537             skip("connection closed\n");
538             return -1;
539         }
540         received += ret;
541
542         while (expected < received)
543         {
544             unsigned frame_size = 5 + ((data[3]<<8) | data[4]);
545             expected += frame_size;
546             data += frame_size;
547         }
548
549         if (expected == received)
550             break;
551     }
552
553     buf->cbBuffer = received;
554
555     return received;
556 }
557
558 static void test_communication(void)
559 {
560     int ret;
561
562     WSADATA wsa_data;
563     SOCKET sock;
564     struct hostent *host;
565     struct sockaddr_in addr;
566
567     SECURITY_STATUS status;
568     ULONG attrs;
569
570     SCHANNEL_CRED cred;
571     CredHandle cred_handle;
572     CtxtHandle context;
573     SecPkgContext_StreamSizes sizes;
574
575     SecBufferDesc buffers[2];
576     SecBuffer *buf;
577     unsigned buf_size = 4000;
578     unsigned char *data;
579     unsigned data_size;
580
581     if (!pAcquireCredentialsHandleA || !pFreeCredentialsHandle ||
582         !pInitializeSecurityContextA || !pDeleteSecurityContext ||
583         !pQueryContextAttributesA || !pDecryptMessage || !pEncryptMessage)
584     {
585         skip("Required secur32 functions not available\n");
586         return;
587     }
588
589     /* Create a socket and connect to mail.google.com */
590     ret = WSAStartup(0x0202, &wsa_data);
591     if (ret)
592     {
593         skip("Can't init winsock 2.2\n");
594         return;
595     }
596
597     host = gethostbyname("www.codeweavers.com");
598     if (!host)
599     {
600         skip("Can't resolve www.codeweavers.com\n");
601         return;
602     }
603
604     addr.sin_family = host->h_addrtype;
605     addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
606     addr.sin_port = htons(443);
607     sock = socket(host->h_addrtype, SOCK_STREAM, 0);
608     if (sock == SOCKET_ERROR)
609     {
610         skip("Can't create socket\n");
611         return;
612     }
613
614     ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
615     if (ret == SOCKET_ERROR)
616     {
617         skip("Can't connect to www.codeweavers.com\n");
618         return;
619     }
620
621     /* Create client credentials */
622     init_cred(&cred);
623     cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
624
625     status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
626         &cred, NULL, NULL, &cred_handle, NULL);
627     ok(status == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", status);
628
629     /* Initialize the connection */
630     init_buffers(&buffers[0], 4, buf_size);
631     init_buffers(&buffers[1], 4, buf_size);
632
633     buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
634     status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
635         ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
636         0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
637     ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
638
639     while (status == SEC_I_CONTINUE_NEEDED)
640     {
641         buf = &buffers[0].pBuffers[0];
642         send(sock, buf->pvBuffer, buf->cbBuffer, 0);
643         buf->cbBuffer = buf_size;
644
645         buf = &buffers[1].pBuffers[0];
646         ret = receive_data(sock, buf);
647         if (ret == -1)
648             return;
649
650         buf->BufferType = SECBUFFER_TOKEN;
651
652         status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
653             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
654             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
655         buffers[1].pBuffers[0].cbBuffer = buf_size;
656     }
657
658     ok(status == SEC_E_OK, "InitializeSecurityContext failed: %08x\n", status);
659
660     pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
661
662     reset_buffers(&buffers[0]);
663
664     /* Send a simple request so we get data for testing DecryptMessage */
665     buf = &buffers[0].pBuffers[0];
666     data = buf->pvBuffer;
667     buf->BufferType = SECBUFFER_STREAM_HEADER;
668     buf->cbBuffer = sizes.cbHeader;
669     ++buf;
670     buf->BufferType = SECBUFFER_DATA;
671     buf->pvBuffer = data + sizes.cbHeader;
672     buf->cbBuffer = sizeof(http_request) - 1;
673     memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
674     ++buf;
675     buf->BufferType = SECBUFFER_STREAM_TRAILER;
676     buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
677     buf->cbBuffer = sizes.cbTrailer;
678
679     status = pEncryptMessage(&context, 0, &buffers[0], 0);
680     ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
681     if (status != SEC_E_OK)
682         return;
683
684     buf = &buffers[0].pBuffers[0];
685     send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
686
687     reset_buffers(&buffers[0]);
688     buf->cbBuffer = buf_size;
689     data_size = receive_data(sock, buf);
690
691     /* Too few buffers */
692     --buffers[0].cBuffers;
693     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
694     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
695
696     /* No data buffer */
697     ++buffers[0].cBuffers;
698     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
699     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
700
701     /* Two data buffers */
702     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
703     buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
704     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
705     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
706
707     /* Too few empty buffers */
708     buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
709     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
710     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
711
712     /* Incomplete data */
713     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
714     buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
715     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
716     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
717     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
718     ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
719
720     buffers[0].pBuffers[0].cbBuffer = data_size;
721     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
722     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
723     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
724     ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
725     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
726     ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
727     ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected first buffer to be SECBUFFER_STREAM_TRAILER\n");
728
729     data = buffers[0].pBuffers[1].pvBuffer;
730     data[buffers[0].pBuffers[1].cbBuffer] = 0;
731
732     pDeleteSecurityContext(&context);
733     pFreeCredentialsHandle(&cred_handle);
734
735     free_buffers(&buffers[0]);
736     free_buffers(&buffers[1]);
737
738     closesocket(sock);
739 }
740
741 START_TEST(schannel)
742 {
743     InitFunctionPtrs();
744
745     testAcquireSecurityContext();
746     test_communication();
747
748     if(secdll)
749         FreeLibrary(secdll);
750     if(crypt32dll)
751         FreeLibrary(crypt32dll);
752 }