Release 1.4.1.
[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", st);
245
246         /* Crashes on WinNT */
247         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_BOTH, NULL,
248          NULL, NULL, NULL, NULL, NULL);
249         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
250
251         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
252          NULL, NULL, NULL, NULL, NULL, NULL);
253         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
254
255         /* Crashes */
256         pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
257          NULL, NULL, NULL, NULL, NULL, NULL);
258     }
259     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
260      NULL, NULL, NULL, NULL, &cred, NULL);
261     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
262     if(st == SEC_E_OK)
263         pFreeCredentialsHandle(&cred);
264     memset(&cred, 0, sizeof(cred));
265     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
266      NULL, NULL, NULL, NULL, &cred, &exp);
267     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
268     /* expriy is indeterminate in win2k3 */
269     trace("expiry: %08x%08x\n", exp.HighPart, exp.LowPart);
270     pFreeCredentialsHandle(&cred);
271
272     /* Bad version in SCHANNEL_CRED */
273     memset(&schanCred, 0, sizeof(schanCred));
274     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
275      NULL, &schanCred, NULL, NULL, NULL, NULL);
276     ok(st == SEC_E_INTERNAL_ERROR ||
277        st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */ ||
278        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
279     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
280      NULL, &schanCred, NULL, NULL, NULL, NULL);
281     ok(st == SEC_E_INTERNAL_ERROR ||
282        st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */ ||
283        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
284
285     /* No cert in SCHANNEL_CRED succeeds for outbound.. */
286     schanCred.dwVersion = SCHANNEL_CRED_VERSION;
287     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
288      NULL, &schanCred, NULL, NULL, &cred, NULL);
289     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
290     pFreeCredentialsHandle(&cred);
291     /* but fails for inbound. */
292     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
293      NULL, &schanCred, NULL, NULL, &cred, NULL);
294     ok(st == SEC_E_NO_CREDENTIALS ||
295        st == SEC_E_OK /* Vista/win2k8 */,
296        "Expected SEC_E_NO_CREDENTIALS or SEC_E_OK, got %08x\n", st);
297
298     if (0)
299     {
300         /* Crashes with bad paCred pointer */
301         schanCred.cCreds = 1;
302         pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
303          NULL, &schanCred, NULL, NULL, NULL, NULL);
304     }
305
306     /* Bogus cert in SCHANNEL_CRED. Windows fails with
307      * SEC_E_UNKNOWN_CREDENTIALS, but I'll accept SEC_E_NO_CREDENTIALS too.
308      */
309     schanCred.cCreds = 1;
310     schanCred.paCred = &certs[0];
311     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
312      NULL, &schanCred, NULL, NULL, NULL, NULL);
313     ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
314        st == SEC_E_NO_CREDENTIALS ||
315        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
316     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
317      NULL, &schanCred, NULL, NULL, NULL, NULL);
318     ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
319        st == SEC_E_NO_CREDENTIALS ||
320        st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
321
322     /* Good cert, but missing private key. Windows fails with
323      * SEC_E_NO_CREDENTIALS, but I'll accept SEC_E_UNKNOWN_CREDENTIALS too.
324      */
325     schanCred.cCreds = 1;
326     schanCred.paCred = &certs[1];
327     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
328      NULL, &schanCred, NULL, NULL, &cred, NULL);
329     ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS ||
330        st == SEC_E_INTERNAL_ERROR, /* win2k */
331      "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
332      "or SEC_E_INTERNAL_ERROR, got %08x\n", st);
333     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
334      NULL, &schanCred, NULL, NULL, NULL, NULL);
335     ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS ||
336        st == SEC_E_INTERNAL_ERROR, /* win2k */
337      "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
338      "or SEC_E_INTERNAL_ERROR, got %08x\n", st);
339
340     /* Good cert, with CRYPT_KEY_PROV_INFO set before it's had a key loaded. */
341     if (pCertSetCertificateContextProperty)
342     {
343         ret = pCertSetCertificateContextProperty(certs[1],
344               CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo);
345         schanCred.dwVersion = SCH_CRED_V3;
346         ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
347         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
348              NULL, &schanCred, NULL, NULL, &cred, NULL);
349         ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
350            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
351         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
352              NULL, &schanCred, NULL, NULL, &cred, NULL);
353         ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
354            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
355     }
356
357     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
358      CRYPT_NEWKEYSET);
359     ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
360     ret = 0;
361     if (pCryptImportKey)
362     {
363         ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
364         ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
365     }
366     if (ret)
367     {
368         PCCERT_CONTEXT tmp;
369
370         if (0)
371         {
372             /* Crashes */
373             pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
374              NULL, &schanCred, NULL, NULL, NULL, NULL);
375
376             /* Crashes on WinNT */
377             /* Good cert with private key, bogus version */
378             schanCred.dwVersion = SCH_CRED_V1;
379             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
380                 NULL, &schanCred, NULL, NULL, &cred, NULL);
381             ok(st == SEC_E_INTERNAL_ERROR ||
382                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
383                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
384             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
385                 NULL, &schanCred, NULL, NULL, &cred, NULL);
386             ok(st == SEC_E_INTERNAL_ERROR ||
387                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
388                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
389             schanCred.dwVersion = SCH_CRED_V2;
390             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
391                 NULL, &schanCred, NULL, NULL, &cred, NULL);
392             ok(st == SEC_E_INTERNAL_ERROR ||
393                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
394                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
395             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
396                 NULL, &schanCred, NULL, NULL, &cred, NULL);
397             ok(st == SEC_E_INTERNAL_ERROR ||
398                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
399                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
400         }
401
402         /* Succeeds on V3 or higher */
403         schanCred.dwVersion = SCH_CRED_V3;
404         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
405          NULL, &schanCred, NULL, NULL, &cred, NULL);
406         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
407         pFreeCredentialsHandle(&cred);
408         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
409          NULL, &schanCred, NULL, NULL, &cred, NULL);
410         ok(st == SEC_E_OK ||
411            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
412            "AcquireCredentialsHandleA failed: %08x\n", st);
413         pFreeCredentialsHandle(&cred);
414         schanCred.dwVersion = SCHANNEL_CRED_VERSION;
415         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
416          NULL, &schanCred, NULL, NULL, &cred, NULL);
417         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
418         pFreeCredentialsHandle(&cred);
419         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
420          NULL, &schanCred, NULL, NULL, &cred, NULL);
421         ok(st == SEC_E_OK ||
422            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
423            "AcquireCredentialsHandleA failed: %08x\n", st);
424         if (st == SEC_E_OK) test_strength(&cred);
425         pFreeCredentialsHandle(&cred);
426
427         /* How about more than one cert? */
428         schanCred.cCreds = 2;
429         schanCred.paCred = certs;
430         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
431          NULL, &schanCred, NULL, NULL, &cred, NULL);
432         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
433            st == SEC_E_NO_CREDENTIALS /* Vista/win2k8 */ ||
434            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
435         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
436          NULL, &schanCred, NULL, NULL, &cred, NULL);
437         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
438            st == SEC_E_NO_CREDENTIALS ||
439            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
440         tmp = certs[0];
441         certs[0] = certs[1];
442         certs[1] = tmp;
443         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
444          NULL, &schanCred, NULL, NULL, &cred, NULL);
445         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
446            st == SEC_E_NO_CREDENTIALS ||
447            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
448         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
449          NULL, &schanCred, NULL, NULL, &cred, NULL);
450         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
451          "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
452         /* FIXME: what about two valid certs? */
453
454         if (pCryptDestroyKey)
455             pCryptDestroyKey(key);
456     }
457
458     if (pCryptReleaseContext)
459         pCryptReleaseContext(csp, 0);
460     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
461      CRYPT_DELETEKEYSET);
462
463     if (pCertFreeCertificateContext)
464     {
465         pCertFreeCertificateContext(certs[0]);
466         pCertFreeCertificateContext(certs[1]);
467     }
468 }
469
470 static const char http_request[] = "HEAD /test.html HTTP/1.1\r\nHost: www.codeweavers.com\r\nConnection: close\r\n\r\n";
471
472 static void init_cred(SCHANNEL_CRED *cred)
473 {
474     cred->dwVersion = SCHANNEL_CRED_VERSION;
475     cred->cCreds = 0;
476     cred->paCred = 0;
477     cred->hRootStore = NULL;
478     cred->cMappers = 0;
479     cred->aphMappers = NULL;
480     cred->cSupportedAlgs = 0;
481     cred->palgSupportedAlgs = NULL;
482     cred->grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
483     cred->dwMinimumCipherStrength = 0;
484     cred->dwMaximumCipherStrength = 0;
485     cred->dwSessionLifespan = 0;
486     cred->dwFlags = 0;
487 }
488
489 static void init_buffers(SecBufferDesc *desc, unsigned count, unsigned size)
490 {
491     desc->ulVersion = SECBUFFER_VERSION;
492     desc->cBuffers = count;
493     desc->pBuffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count*sizeof(SecBuffer));
494
495     desc->pBuffers[0].cbBuffer = size;
496     desc->pBuffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, size);
497 }
498
499 static void reset_buffers(SecBufferDesc *desc)
500 {
501     unsigned i;
502
503     for (i = 0; i < desc->cBuffers; ++i)
504     {
505         desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
506         if (i > 0)
507         {
508             desc->pBuffers[i].cbBuffer = 0;
509             desc->pBuffers[i].pvBuffer = NULL;
510         }
511     }
512 }
513
514 static void free_buffers(SecBufferDesc *desc)
515 {
516     HeapFree(GetProcessHeap(), 0, desc->pBuffers[0].pvBuffer);
517     HeapFree(GetProcessHeap(), 0, desc->pBuffers);
518 }
519
520 static int receive_data(SOCKET sock, SecBuffer *buf)
521 {
522     unsigned received = 0;
523
524     while (1)
525     {
526         unsigned char *data = buf->pvBuffer;
527         unsigned expected = 0;
528         int ret;
529
530         ret = recv(sock, (char *)data+received, buf->cbBuffer-received, 0);
531         if (ret == -1)
532         {
533             skip("recv failed\n");
534             return -1;
535         }
536         else if(ret == 0)
537         {
538             skip("connection closed\n");
539             return -1;
540         }
541         received += ret;
542
543         while (expected < received)
544         {
545             unsigned frame_size = 5 + ((data[3]<<8) | data[4]);
546             expected += frame_size;
547             data += frame_size;
548         }
549
550         if (expected == received)
551             break;
552     }
553
554     buf->cbBuffer = received;
555
556     return received;
557 }
558
559 static void test_communication(void)
560 {
561     int ret;
562
563     WSADATA wsa_data;
564     SOCKET sock;
565     struct hostent *host;
566     struct sockaddr_in addr;
567
568     SECURITY_STATUS status;
569     ULONG attrs;
570
571     SCHANNEL_CRED cred;
572     CredHandle cred_handle;
573     CtxtHandle context;
574     SecPkgContext_StreamSizes sizes;
575
576     SecBufferDesc buffers[2];
577     SecBuffer *buf;
578     unsigned buf_size = 4000;
579     unsigned char *data;
580     unsigned data_size;
581
582     if (!pAcquireCredentialsHandleA || !pFreeCredentialsHandle ||
583         !pInitializeSecurityContextA || !pDeleteSecurityContext ||
584         !pQueryContextAttributesA || !pDecryptMessage || !pEncryptMessage)
585     {
586         skip("Required secur32 functions not available\n");
587         return;
588     }
589
590     /* Create a socket and connect to www.codeweavers.com */
591     ret = WSAStartup(0x0202, &wsa_data);
592     if (ret)
593     {
594         skip("Can't init winsock 2.2\n");
595         return;
596     }
597
598     host = gethostbyname("www.codeweavers.com");
599     if (!host)
600     {
601         skip("Can't resolve www.codeweavers.com\n");
602         return;
603     }
604
605     addr.sin_family = host->h_addrtype;
606     addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
607     addr.sin_port = htons(443);
608     sock = socket(host->h_addrtype, SOCK_STREAM, 0);
609     if (sock == SOCKET_ERROR)
610     {
611         skip("Can't create socket\n");
612         return;
613     }
614
615     ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
616     if (ret == SOCKET_ERROR)
617     {
618         skip("Can't connect to www.codeweavers.com\n");
619         return;
620     }
621
622     /* Create client credentials */
623     init_cred(&cred);
624     cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
625
626     status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
627         &cred, NULL, NULL, &cred_handle, NULL);
628     ok(status == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", status);
629     if (status != SEC_E_OK) return;
630
631     /* Initialize the connection */
632     init_buffers(&buffers[0], 4, buf_size);
633     init_buffers(&buffers[1], 4, buf_size);
634
635     buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
636     status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
637         ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
638         0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
639     ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
640
641     buffers[1].cBuffers = 1;
642     buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
643     data_size = buffers[0].pBuffers[0].cbBuffer;
644     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
645             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
646             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
647     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
648
649     buffers[0].pBuffers[0].cbBuffer = buf_size;
650     buffers[1].cBuffers = 4;
651     buffers[1].pBuffers[0].cbBuffer = buf_size;
652
653     status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
654             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
655             0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
656     ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
657
658     while (status == SEC_I_CONTINUE_NEEDED)
659     {
660         buf = &buffers[0].pBuffers[0];
661         send(sock, buf->pvBuffer, buf->cbBuffer, 0);
662         buf->cbBuffer = buf_size;
663
664         buf = &buffers[1].pBuffers[0];
665         ret = receive_data(sock, buf);
666         if (ret == -1)
667             return;
668
669         buf->BufferType = SECBUFFER_TOKEN;
670
671         status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
672             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
673             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
674         buffers[1].pBuffers[0].cbBuffer = buf_size;
675     }
676
677     ok(status == SEC_E_OK || broken(status == SEC_E_INVALID_TOKEN) /* WinNT */,
678         "InitializeSecurityContext failed: %08x\n", status);
679     if(status != SEC_E_OK) {
680         win_skip("Handshake failed\n");
681         return;
682     }
683
684     pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
685
686     reset_buffers(&buffers[0]);
687
688     /* Send a simple request so we get data for testing DecryptMessage */
689     buf = &buffers[0].pBuffers[0];
690     data = buf->pvBuffer;
691     buf->BufferType = SECBUFFER_STREAM_HEADER;
692     buf->cbBuffer = sizes.cbHeader;
693     ++buf;
694     buf->BufferType = SECBUFFER_DATA;
695     buf->pvBuffer = data + sizes.cbHeader;
696     buf->cbBuffer = sizeof(http_request) - 1;
697     memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
698     ++buf;
699     buf->BufferType = SECBUFFER_STREAM_TRAILER;
700     buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
701     buf->cbBuffer = sizes.cbTrailer;
702
703     status = pEncryptMessage(&context, 0, &buffers[0], 0);
704     ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
705     if (status != SEC_E_OK)
706         return;
707
708     buf = &buffers[0].pBuffers[0];
709     send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
710
711     reset_buffers(&buffers[0]);
712     buf->cbBuffer = buf_size;
713     data_size = receive_data(sock, buf);
714
715     /* Too few buffers */
716     --buffers[0].cBuffers;
717     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
718     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
719
720     /* No data buffer */
721     ++buffers[0].cBuffers;
722     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
723     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
724
725     /* Two data buffers */
726     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
727     buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
728     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
729     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
730
731     /* Too few empty buffers */
732     buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
733     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
734     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
735
736     /* Incomplete data */
737     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
738     buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
739     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
740     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
741     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
742     ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
743
744     buffers[0].pBuffers[0].cbBuffer = data_size;
745     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
746     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
747     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
748     ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
749     if (status == SEC_E_OK)
750     {
751         ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
752         ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
753         ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected third buffer to be SECBUFFER_STREAM_TRAILER\n");
754
755         data = buffers[0].pBuffers[1].pvBuffer;
756         data[buffers[0].pBuffers[1].cbBuffer] = 0;
757     }
758
759     pDeleteSecurityContext(&context);
760     pFreeCredentialsHandle(&cred_handle);
761
762     free_buffers(&buffers[0]);
763     free_buffers(&buffers[1]);
764
765     closesocket(sock);
766 }
767
768 START_TEST(schannel)
769 {
770     InitFunctionPtrs();
771
772     testAcquireSecurityContext();
773     test_communication();
774
775     if(secdll)
776         FreeLibrary(secdll);
777     if(crypt32dll)
778         FreeLibrary(crypt32dll);
779 }