msi: Set all folders' source paths to the root directory if the source type is compre...
[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
28 #include "wine/test.h"
29
30 static HMODULE secdll, crypt32dll;
31
32 static ACQUIRE_CREDENTIALS_HANDLE_FN_A pAcquireCredentialsHandleA;
33 static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
34 static QUERY_CREDENTIALS_ATTRIBUTES_FN_A pQueryCredentialsAttributesA;
35
36 static PCCERT_CONTEXT (WINAPI *pCertCreateCertificateContext)(DWORD,const BYTE*,DWORD);
37 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT);
38 static BOOL (WINAPI *pCertSetCertificateContextProperty)(PCCERT_CONTEXT,DWORD,DWORD,const void*);
39
40 static BOOL (WINAPI *pCryptAcquireContextW)(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD);
41 static BOOL (WINAPI *pCryptDestroyKey)(HCRYPTKEY);
42 static BOOL (WINAPI *pCryptImportKey)(HCRYPTPROV,CONST BYTE*,DWORD,HCRYPTKEY,DWORD,HCRYPTKEY*);
43 static BOOL (WINAPI *pCryptReleaseContext)(HCRYPTPROV,ULONG_PTR);
44
45 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
46  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
47  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
48  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
49  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
50  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
51  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
52  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
53  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
54  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
55 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
56  'm','p',0 };
57 static BYTE privKey[] = {
58  0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
59  0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
60  0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
61  0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
62  0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
63  0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
64  0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
65  0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
66  0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
67  0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
68  0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
69  0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
70  0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
71  0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
72  0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
73  0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
74  0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
75  0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
76  0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
77  0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
78  0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
79  0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
80  0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
81  0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
82
83 static const BYTE selfSignedCert[] = {
84  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
85  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
86  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
87  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
88  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
89  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
90  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
91  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
92  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
93  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
94  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
95  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
96  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
97  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
98  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
99  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
100  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
101  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
102  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
103  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
104  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
105  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
106  0xa8, 0x76, 0x57, 0x92, 0x36 };
107
108 static void InitFunctionPtrs(void)
109 {
110     HMODULE advapi32dll;
111
112     crypt32dll = LoadLibraryA("crypt32.dll");
113     secdll = LoadLibraryA("secur32.dll");
114     if(!secdll)
115         secdll = LoadLibraryA("security.dll");
116     advapi32dll = GetModuleHandleA("advapi32.dll");
117
118 #define GET_PROC(h, func)  p ## func = (void*)GetProcAddress(h, #func)
119
120     if(secdll)
121     {
122         GET_PROC(secdll, AcquireCredentialsHandleA);
123         GET_PROC(secdll, FreeCredentialsHandle);
124         GET_PROC(secdll, QueryCredentialsAttributesA);
125     }
126
127     GET_PROC(advapi32dll, CryptAcquireContextW);
128     GET_PROC(advapi32dll, CryptDestroyKey);
129     GET_PROC(advapi32dll, CryptImportKey);
130     GET_PROC(advapi32dll, CryptReleaseContext);
131
132     GET_PROC(crypt32dll, CertFreeCertificateContext);
133     GET_PROC(crypt32dll, CertSetCertificateContextProperty);
134     GET_PROC(crypt32dll, CertCreateCertificateContext);
135
136 #undef GET_PROC
137 }
138
139 static void test_strength(PCredHandle handle)
140 {
141     SecPkgCred_CipherStrengths strength = {-1,-1};
142     SECURITY_STATUS st;
143
144     st = pQueryCredentialsAttributesA(handle, SECPKG_ATTR_CIPHER_STRENGTHS, &strength);
145     ok(st == SEC_E_OK, "QueryCredentialsAttributesA failed: %u\n", GetLastError());
146     ok(strength.dwMinimumCipherStrength, "dwMinimumCipherStrength not changed\n");
147     ok(strength.dwMaximumCipherStrength, "dwMaximumCipherStrength not changed\n");
148     trace("strength %d - %d\n", strength.dwMinimumCipherStrength, strength.dwMaximumCipherStrength);
149 }
150
151 static void testAcquireSecurityContext(void)
152 {
153     SECURITY_STATUS st;
154     CredHandle cred;
155     TimeStamp exp;
156     SCHANNEL_CRED schanCred;
157     PCCERT_CONTEXT certs[2];
158     HCRYPTPROV csp;
159     static CHAR unisp_name_a[] = UNISP_NAME_A;
160     WCHAR ms_def_prov_w[MAX_PATH];
161     BOOL ret;
162     HCRYPTKEY key;
163     CRYPT_KEY_PROV_INFO keyProvInfo;
164
165     if (!pAcquireCredentialsHandleA || !pCertCreateCertificateContext ||
166         !pFreeCredentialsHandle || !pCryptAcquireContextW)
167     {
168         skip("Needed functions are not available\n");
169         return;
170     }
171
172     lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
173
174     keyProvInfo.pwszContainerName = cspNameW;
175     keyProvInfo.pwszProvName = ms_def_prov_w;
176     keyProvInfo.dwProvType = PROV_RSA_FULL;
177     keyProvInfo.dwFlags = 0;
178     keyProvInfo.cProvParam = 0;
179     keyProvInfo.rgProvParam = NULL;
180     keyProvInfo.dwKeySpec = AT_SIGNATURE;
181
182     certs[0] = pCertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
183      sizeof(bigCert));
184     certs[1] = pCertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
185      sizeof(selfSignedCert));
186
187     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
188      CRYPT_DELETEKEYSET);
189
190     st = pAcquireCredentialsHandleA(NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL,
191      NULL);
192     ok(st == SEC_E_SECPKG_NOT_FOUND,
193      "Expected SEC_E_SECPKG_NOT_FOUND, got %08x\n", st);
194     if (0)
195     {
196         /* Crashes on Win2K */
197         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, 0, NULL, NULL, NULL,
198          NULL, NULL, NULL);
199         ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n",
200          st);
201     }
202     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_BOTH, NULL,
203      NULL, NULL, NULL, NULL, NULL);
204     ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n",
205      st);
206     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
207      NULL, NULL, NULL, NULL, NULL, NULL);
208     ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n",
209      st);
210     if (0)
211     {
212         /* Crashes */
213         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
214          NULL, NULL, NULL, NULL, NULL, NULL);
215     }
216     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
217      NULL, NULL, NULL, NULL, &cred, NULL);
218     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
219     if(st == SEC_E_OK)
220         pFreeCredentialsHandle(&cred);
221     memset(&cred, 0, sizeof(cred));
222     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
223      NULL, NULL, NULL, NULL, &cred, &exp);
224     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
225     /* expriy is indeterminate in win2k3 */
226     trace("expiry: %08lx%08lx\n", exp.HighPart, exp.LowPart);
227     pFreeCredentialsHandle(&cred);
228
229     /* Bad version in SCHANNEL_CRED */
230     memset(&schanCred, 0, sizeof(schanCred));
231     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
232      NULL, &schanCred, NULL, NULL, NULL, NULL);
233     ok(st == SEC_E_INTERNAL_ERROR, "Expected SEC_E_INTERNAL_ERROR, got %08x\n",
234      st);
235     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
236      NULL, &schanCred, NULL, NULL, NULL, NULL);
237     ok(st == SEC_E_INTERNAL_ERROR, "Expected SEC_E_INTERNAL_ERROR, got %08x\n",
238      st);
239
240     /* No cert in SCHANNEL_CRED succeeds for outbound.. */
241     schanCred.dwVersion = SCHANNEL_CRED_VERSION;
242     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
243      NULL, &schanCred, NULL, NULL, &cred, NULL);
244     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
245     pFreeCredentialsHandle(&cred);
246     /* but fails for inbound. */
247     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
248      NULL, &schanCred, NULL, NULL, NULL, NULL);
249     ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n",
250      st);
251
252     if (0)
253     {
254         /* Crashes with bad paCred pointer */
255         schanCred.cCreds = 1;
256         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
257          NULL, &schanCred, NULL, NULL, NULL, NULL);
258     }
259
260     /* Bogus cert in SCHANNEL_CRED. Windows fails with
261      * SEC_E_UNKNOWN_CREDENTIALS, but I'll accept SEC_E_NO_CREDENTIALS too.
262      */
263     schanCred.cCreds = 1;
264     schanCred.paCred = &certs[0];
265     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
266      NULL, &schanCred, NULL, NULL, NULL, NULL);
267     ok(st == SEC_E_UNKNOWN_CREDENTIALS || SEC_E_NO_CREDENTIALS,
268      "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
269      st);
270     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
271      NULL, &schanCred, NULL, NULL, NULL, NULL);
272     ok(st == SEC_E_UNKNOWN_CREDENTIALS || SEC_E_NO_CREDENTIALS,
273      "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
274      st);
275
276     /* Good cert, but missing private key. Windows fails with
277      * SEC_E_NO_CREDENTIALS, but I'll accept SEC_E_UNKNOWN_CREDENTIALS too.
278      */
279     schanCred.cCreds = 1;
280     schanCred.paCred = &certs[1];
281     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
282      NULL, &schanCred, NULL, NULL, &cred, NULL);
283     ok(st == SEC_E_UNKNOWN_CREDENTIALS || SEC_E_NO_CREDENTIALS,
284      "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
285      st);
286     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
287      NULL, &schanCred, NULL, NULL, NULL, NULL);
288     ok(st == SEC_E_UNKNOWN_CREDENTIALS || SEC_E_NO_CREDENTIALS,
289      "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
290      st);
291
292     /* Good cert, with CRYPT_KEY_PROV_INFO set before it's had a key loaded. */
293     if (pCertSetCertificateContextProperty)
294     {
295         ret = pCertSetCertificateContextProperty(certs[1],
296               CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo);
297         schanCred.dwVersion = SCH_CRED_V3;
298         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
299              NULL, &schanCred, NULL, NULL, &cred, NULL);
300         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
301            "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
302         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
303              NULL, &schanCred, NULL, NULL, &cred, NULL);
304         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
305            "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
306     }
307
308     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
309      CRYPT_NEWKEYSET);
310     ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
311     ret = 0;
312     if (pCryptImportKey)
313     {
314         ret = pCryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
315         ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
316     }
317     if (ret)
318     {
319         PCCERT_CONTEXT tmp;
320
321         if (0)
322         {
323             /* Crashes */
324             st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
325              NULL, &schanCred, NULL, NULL, NULL, NULL);
326         }
327         /* Good cert with private key, bogus version */
328         schanCred.dwVersion = SCH_CRED_V1;
329         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
330          NULL, &schanCred, NULL, NULL, &cred, NULL);
331         ok(st == SEC_E_INTERNAL_ERROR,
332          "Expected SEC_E_INTERNAL_ERROR, got %08x\n", st);
333         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
334          NULL, &schanCred, NULL, NULL, &cred, NULL);
335         ok(st == SEC_E_INTERNAL_ERROR,
336          "Expected SEC_E_INTERNAL_ERROR, got %08x\n", st);
337         schanCred.dwVersion = SCH_CRED_V2;
338         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
339          NULL, &schanCred, NULL, NULL, &cred, NULL);
340         ok(st == SEC_E_INTERNAL_ERROR,
341          "Expected SEC_E_INTERNAL_ERROR, got %08x\n", st);
342         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
343          NULL, &schanCred, NULL, NULL, &cred, NULL);
344         ok(st == SEC_E_INTERNAL_ERROR,
345          "Expected SEC_E_INTERNAL_ERROR, got %08x\n", st);
346
347         /* Succeeds on V3 or higher */
348         schanCred.dwVersion = SCH_CRED_V3;
349         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
350          NULL, &schanCred, NULL, NULL, &cred, NULL);
351         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
352         pFreeCredentialsHandle(&cred);
353         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
354          NULL, &schanCred, NULL, NULL, &cred, NULL);
355         ok(st == SEC_E_OK ||
356            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
357            "AcquireCredentialsHandleA failed: %08x\n", st);
358         pFreeCredentialsHandle(&cred);
359         schanCred.dwVersion = SCHANNEL_CRED_VERSION;
360         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
361          NULL, &schanCred, NULL, NULL, &cred, NULL);
362         ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
363         pFreeCredentialsHandle(&cred);
364         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
365          NULL, &schanCred, NULL, NULL, &cred, NULL);
366         ok(st == SEC_E_OK ||
367            st == SEC_E_UNKNOWN_CREDENTIALS, /* win2k3 */
368            "AcquireCredentialsHandleA failed: %08x\n", st);
369         if (st == SEC_E_OK) test_strength(&cred);
370         pFreeCredentialsHandle(&cred);
371
372         /* How about more than one cert? */
373         schanCred.cCreds = 2;
374         schanCred.paCred = certs;
375         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
376          NULL, &schanCred, NULL, NULL, &cred, NULL);
377         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
378          "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
379         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
380          NULL, &schanCred, NULL, NULL, &cred, NULL);
381         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
382          "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
383         tmp = certs[0];
384         certs[0] = certs[1];
385         certs[1] = tmp;
386         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
387          NULL, &schanCred, NULL, NULL, &cred, NULL);
388         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
389          "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
390         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
391          NULL, &schanCred, NULL, NULL, &cred, NULL);
392         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
393          "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
394         /* FIXME: what about two valid certs? */
395
396         if (pCryptDestroyKey)
397             pCryptDestroyKey(key);
398     }
399
400     if (pCryptReleaseContext)
401         pCryptReleaseContext(csp, 0);
402     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
403      CRYPT_DELETEKEYSET);
404
405     if (pCertFreeCertificateContext)
406     {
407         pCertFreeCertificateContext(certs[0]);
408         pCertFreeCertificateContext(certs[1]);
409     }
410 }
411
412 START_TEST(schannel)
413 {
414     InitFunctionPtrs();
415
416     testAcquireSecurityContext();
417
418     if(secdll)
419         FreeLibrary(secdll);
420     if(crypt32dll)
421         FreeLibrary(crypt32dll);
422 }