include/msvcrt: Define more CPU control word flags.
[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         st = 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         st = 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         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
347              NULL, &schanCred, NULL, NULL, &cred, NULL);
348         ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
349            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
350         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
351              NULL, &schanCred, NULL, NULL, &cred, NULL);
352         ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
353            "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
354     }
355
356     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
357      CRYPT_NEWKEYSET);
358     ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
359     ret = 0;
360     if (pCryptImportKey)
361     {
362         ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
363         ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
364     }
365     if (ret)
366     {
367         PCCERT_CONTEXT tmp;
368
369         if (0)
370         {
371             /* Crashes */
372             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
373              NULL, &schanCred, NULL, NULL, NULL, NULL);
374
375             /* Crashes on WinNT */
376             /* Good cert with private key, bogus version */
377             schanCred.dwVersion = SCH_CRED_V1;
378             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
379                 NULL, &schanCred, NULL, NULL, &cred, NULL);
380             ok(st == SEC_E_INTERNAL_ERROR ||
381                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
382                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
383             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
384                 NULL, &schanCred, NULL, NULL, &cred, NULL);
385             ok(st == SEC_E_INTERNAL_ERROR ||
386                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
387                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
388             schanCred.dwVersion = SCH_CRED_V2;
389             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
390                 NULL, &schanCred, NULL, NULL, &cred, NULL);
391             ok(st == SEC_E_INTERNAL_ERROR ||
392                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
393                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
394             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
395                 NULL, &schanCred, NULL, NULL, &cred, NULL);
396             ok(st == SEC_E_INTERNAL_ERROR ||
397                 st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
398                 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
399         }
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            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %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            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %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            st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %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 www.codeweavers.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     buffers[1].cBuffers = 1;
640     buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
641     data_size = buffers[0].pBuffers[0].cbBuffer;
642     status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
643             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
644             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
645     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
646
647     buffers[0].pBuffers[0].cbBuffer = buf_size;
648     buffers[1].cBuffers = 4;
649     buffers[1].pBuffers[0].cbBuffer = buf_size;
650
651     status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
652             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
653             0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
654     ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
655
656     while (status == SEC_I_CONTINUE_NEEDED)
657     {
658         buf = &buffers[0].pBuffers[0];
659         send(sock, buf->pvBuffer, buf->cbBuffer, 0);
660         buf->cbBuffer = buf_size;
661
662         buf = &buffers[1].pBuffers[0];
663         ret = receive_data(sock, buf);
664         if (ret == -1)
665             return;
666
667         buf->BufferType = SECBUFFER_TOKEN;
668
669         status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
670             ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
671             0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
672         buffers[1].pBuffers[0].cbBuffer = buf_size;
673     }
674
675     ok(status == SEC_E_OK || broken(status == SEC_E_INVALID_TOKEN) /* WinNT */,
676         "InitializeSecurityContext failed: %08x\n", status);
677     if(status != SEC_E_OK) {
678         win_skip("Handshake failed\n");
679         return;
680     }
681
682     pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
683
684     reset_buffers(&buffers[0]);
685
686     /* Send a simple request so we get data for testing DecryptMessage */
687     buf = &buffers[0].pBuffers[0];
688     data = buf->pvBuffer;
689     buf->BufferType = SECBUFFER_STREAM_HEADER;
690     buf->cbBuffer = sizes.cbHeader;
691     ++buf;
692     buf->BufferType = SECBUFFER_DATA;
693     buf->pvBuffer = data + sizes.cbHeader;
694     buf->cbBuffer = sizeof(http_request) - 1;
695     memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
696     ++buf;
697     buf->BufferType = SECBUFFER_STREAM_TRAILER;
698     buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
699     buf->cbBuffer = sizes.cbTrailer;
700
701     status = pEncryptMessage(&context, 0, &buffers[0], 0);
702     ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
703     if (status != SEC_E_OK)
704         return;
705
706     buf = &buffers[0].pBuffers[0];
707     send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
708
709     reset_buffers(&buffers[0]);
710     buf->cbBuffer = buf_size;
711     data_size = receive_data(sock, buf);
712
713     /* Too few buffers */
714     --buffers[0].cBuffers;
715     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
716     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
717
718     /* No data buffer */
719     ++buffers[0].cBuffers;
720     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
721     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
722
723     /* Two data buffers */
724     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
725     buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
726     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
727     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
728
729     /* Too few empty buffers */
730     buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
731     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
732     ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
733
734     /* Incomplete data */
735     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
736     buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
737     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
738     ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
739     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
740     ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
741
742     buffers[0].pBuffers[0].cbBuffer = data_size;
743     buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
744     buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
745     status = pDecryptMessage(&context, &buffers[0], 0, NULL);
746     ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
747     ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
748     ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
749     ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected first buffer to be SECBUFFER_STREAM_TRAILER\n");
750
751     data = buffers[0].pBuffers[1].pvBuffer;
752     data[buffers[0].pBuffers[1].cbBuffer] = 0;
753
754     pDeleteSecurityContext(&context);
755     pFreeCredentialsHandle(&cred_handle);
756
757     free_buffers(&buffers[0]);
758     free_buffers(&buffers[1]);
759
760     closesocket(sock);
761 }
762
763 START_TEST(schannel)
764 {
765     InitFunctionPtrs();
766
767     testAcquireSecurityContext();
768     test_communication();
769
770     if(secdll)
771         FreeLibrary(secdll);
772     if(crypt32dll)
773         FreeLibrary(crypt32dll);
774 }