[SCHANNEL_WINETEST] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / modules / rostests / winetests / schannel / main.c
1 /*
2 * Schannel tests
3 *
4 * Copyright 2006 Yuval Fledel
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
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include <windef.h>
26 #include <winbase.h>
27 #define SECURITY_WIN32
28 #include <security.h>
29 #include <schannel.h>
30 #include <ntsecapi.h>
31 #include <ntsecpkg.h>
32
33 #include "wine/test.h"
34
35 /* Helper macros to find the size of SECPKG_FUNCTION_TABLE */
36 #define SECPKG_FUNCTION_TABLE_SIZE_1 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
37 SetContextAttributes)
38 #define SECPKG_FUNCTION_TABLE_SIZE_2 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
39 SetCredentialsAttributes)
40 #define SECPKG_FUNCTION_TABLE_SIZE_3 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
41 ChangeAccountPassword)
42 #define SECPKG_FUNCTION_TABLE_SIZE_4 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
43 QueryMetaData)
44 #define SECPKG_FUNCTION_TABLE_SIZE_5 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
45 ValidateTargetInfo)
46 #define SECPKG_FUNCTION_TABLE_SIZE_6 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
47 PostLogonUser)
48 #define SECPKG_FUNCTION_TABLE_SIZE_7 sizeof(SECPKG_FUNCTION_TABLE)
49
50 #define LSA_BASE_CAPS ( \
51 SECPKG_FLAG_INTEGRITY | \
52 SECPKG_FLAG_PRIVACY | \
53 SECPKG_FLAG_CONNECTION | \
54 SECPKG_FLAG_MULTI_REQUIRED | \
55 SECPKG_FLAG_EXTENDED_ERROR | \
56 SECPKG_FLAG_IMPERSONATION | \
57 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
58 SECPKG_FLAG_STREAM | \
59 SECPKG_FLAG_MUTUAL_AUTH )
60
61 static NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG,
62 PSECPKG_FUNCTION_TABLE*, PULONG);
63 static NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG,
64 PSECPKG_USER_FUNCTION_TABLE*, PULONG);
65
66 static void testInitialize(void)
67 {
68 PSECPKG_USER_FUNCTION_TABLE pUserTables, pUserTables2;
69 PSECPKG_FUNCTION_TABLE pTables, pTables2;
70 ULONG cTables = 0, cUserTables = 0, Version = 0;
71 NTSTATUS status;
72
73 /* Passing NULL into one of the parameters of SpLsaModeInitialize or
74 SpUserModeInitialize causes a crash. */
75
76 /* SpLsaModeInitialize does not care about the LSA version. */
77 status = pSpLsaModeInitialize(0, &Version, &pTables2, &cTables);
78 ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
79 ok(cTables == 2 ||
80 broken(cTables == 1), /* Win2k */
81 "cTables: %d\n", cTables);
82 ok(pTables2 != NULL,"pTables: %p\n", pTables2);
83
84 /* We can call it as many times we want. */
85 status = pSpLsaModeInitialize(0x10000, &Version, &pTables, &cTables);
86 ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
87 ok(cTables == 2 ||
88 broken(cTables == 1), /* Win2k */
89 "cTables: %d\n", cTables);
90 ok(pTables != NULL, "pTables: %p\n", pTables);
91 /* It will always return the same pointer. */
92 ok(pTables == pTables2, "pTables: %p, pTables2: %p\n", pTables, pTables2);
93
94 status = pSpLsaModeInitialize(0x23456, &Version, &pTables, &cTables);
95 ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
96 ok(cTables == 2 ||
97 broken(cTables == 1), /* Win2k */
98 "cTables: %d\n", cTables);
99 ok(pTables != NULL, "pTables: %p\n", pTables);
100 ok(pTables == pTables2, "pTables: %p, pTables2: %p\n", pTables, pTables2);
101
102 /* Bad versions to SpUserModeInitialize. Parameters unchanged */
103 Version = 0xdead;
104 cUserTables = 0xdead;
105 pUserTables = NULL;
106 status = pSpUserModeInitialize(0, &Version, &pUserTables, &cUserTables);
107 ok(status == STATUS_INVALID_PARAMETER, "status: 0x%x\n", status);
108 ok(Version == 0xdead, "Version: 0x%x\n", Version);
109 ok(cUserTables == 0xdead, "cTables: %d\n", cUserTables);
110 ok(pUserTables == NULL, "pUserTables: %p\n", pUserTables);
111
112 status = pSpUserModeInitialize(0x20000, &Version, &pUserTables,
113 &cUserTables);
114 ok(status == STATUS_INVALID_PARAMETER, "status: 0x%x\n", status);
115 ok(Version == 0xdead, "Version: 0x%x\n", Version);
116 ok(cUserTables == 0xdead, "cTables: %d\n", cUserTables);
117 ok(pUserTables == NULL, "pUserTables: %p\n", pUserTables);
118
119 /* Good version to SpUserModeInitialize */
120 status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &Version,
121 &pUserTables, &cUserTables);
122 ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
123 ok(Version == SECPKG_INTERFACE_VERSION, "Version: 0x%x\n", Version);
124 ok(cUserTables == 2 ||
125 broken(cUserTables == 4), /* Win2k */
126 "cUserTables: %d\n", cUserTables);
127 ok(pUserTables != NULL, "pUserTables: %p\n", pUserTables);
128
129 /* Initializing user again */
130 status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &Version,
131 &pUserTables2, &cTables);
132 ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
133 ok(pUserTables == pUserTables2, "pUserTables: %p, pUserTables2: %p\n",
134 pUserTables, pUserTables2);
135 }
136
137 /* A helper function to find the dispatch table of the next package.
138 Needed because SECPKG_FUNCTION_TABLE's size depend on the version */
139 static PSECPKG_FUNCTION_TABLE getNextSecPkgTable(PSECPKG_FUNCTION_TABLE pTable,
140 ULONG Version)
141 {
142 size_t size;
143 PSECPKG_FUNCTION_TABLE pNextTable;
144
145 if (Version == SECPKG_INTERFACE_VERSION)
146 size = SECPKG_FUNCTION_TABLE_SIZE_1;
147 else if (Version == SECPKG_INTERFACE_VERSION_2)
148 size = SECPKG_FUNCTION_TABLE_SIZE_2;
149 else if (Version == SECPKG_INTERFACE_VERSION_3)
150 size = SECPKG_FUNCTION_TABLE_SIZE_3;
151 else if (Version == SECPKG_INTERFACE_VERSION_4)
152 size = SECPKG_FUNCTION_TABLE_SIZE_4;
153 else if (Version == SECPKG_INTERFACE_VERSION_5)
154 size = SECPKG_FUNCTION_TABLE_SIZE_5;
155 else if (Version == SECPKG_INTERFACE_VERSION_6)
156 size = SECPKG_FUNCTION_TABLE_SIZE_6;
157 else if (Version == SECPKG_INTERFACE_VERSION_7)
158 size = SECPKG_FUNCTION_TABLE_SIZE_7;
159 else {
160 ok(FALSE, "Unknown package version 0x%x\n", Version);
161 return NULL;
162 }
163
164 pNextTable = (PSECPKG_FUNCTION_TABLE)((PBYTE)pTable + size);
165 /* Win7 function tables appear to be SECPKG_INTERFACE_VERSION_6 format,
166 but unfortunately SpLsaModeInitialize returns SECPKG_INTERFACE_VERSION_3.
167 We detect that by comparing the "Initialize" pointer from the old table
168 to the "FreeCredentialsHandle" pointer of the new table. These functions
169 have different numbers of arguments, so they can't possibly point to the
170 same implementation */
171 if (broken((void *) pTable->Initialize == (void *) pNextTable->FreeCredentialsHandle &&
172 pNextTable->FreeCredentialsHandle != NULL))
173 {
174 win_skip("Invalid function pointers for next package\n");
175 return NULL;
176 }
177
178 return pNextTable;
179 }
180
181 static void testGetInfo(void)
182 {
183 PSECPKG_FUNCTION_TABLE pTables;
184 SecPkgInfoW PackageInfo;
185 ULONG cTables, Version;
186 NTSTATUS status;
187
188 /* Get the dispatch table */
189 status = pSpLsaModeInitialize(0, &Version, &pTables, &cTables);
190 ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
191
192 /* Passing NULL into ->GetInfo causes a crash. */
193
194 /* First package: Unified */
195 status = pTables->GetInfo(&PackageInfo);
196 ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
197 ok(PackageInfo.fCapabilities == LSA_BASE_CAPS ||
198 PackageInfo.fCapabilities == (LSA_BASE_CAPS|SECPKG_FLAG_APPCONTAINER_PASSTHROUGH),
199 "fCapabilities: 0x%x\n", PackageInfo.fCapabilities);
200 ok(PackageInfo.wVersion == 1, "wVersion: %d\n", PackageInfo.wVersion);
201 ok(PackageInfo.wRPCID == 14, "wRPCID: %d\n", PackageInfo.wRPCID);
202 ok(PackageInfo.cbMaxToken == 0x4000 ||
203 PackageInfo.cbMaxToken == 0x6000, /* Vista */
204 "cbMaxToken: 0x%x\n",
205 PackageInfo.cbMaxToken);
206
207 /* Second package */
208 if (cTables == 1)
209 {
210 win_skip("Second package missing\n");
211 return;
212 }
213 pTables = getNextSecPkgTable(pTables, Version);
214 if (!pTables)
215 return;
216 if (!pTables->GetInfo)
217 {
218 win_skip("GetInfo function missing\n");
219 return;
220 }
221 status = pTables->GetInfo(&PackageInfo);
222 ok(SUCCEEDED(status) ||
223 status == SEC_E_UNSUPPORTED_FUNCTION, /* win2k3 */
224 "status: 0x%x\n", status);
225
226 if (SUCCEEDED(status))
227 {
228 ok(PackageInfo.fCapabilities == LSA_BASE_CAPS ||
229 PackageInfo.fCapabilities == (LSA_BASE_CAPS|SECPKG_FLAG_APPCONTAINER_PASSTHROUGH),
230 "fCapabilities: 0x%x\n", PackageInfo.fCapabilities);
231 ok(PackageInfo.wVersion == 1, "wVersion: %d\n", PackageInfo.wVersion);
232 ok(PackageInfo.wRPCID == 14, "wRPCID: %d\n", PackageInfo.wRPCID);
233 ok(PackageInfo.cbMaxToken == 0x4000 ||
234 PackageInfo.cbMaxToken == 0x6000, /* Win7 */
235 "cbMaxToken: 0x%x\n",
236 PackageInfo.cbMaxToken);
237 }
238 }
239
240 START_TEST(main)
241 {
242 HMODULE hMod = LoadLibraryA("schannel.dll");
243 if (!hMod) {
244 win_skip("schannel.dll not available\n");
245 return;
246 }
247
248 pSpLsaModeInitialize = (void *)GetProcAddress(hMod, "SpLsaModeInitialize");
249 pSpUserModeInitialize = (void *)GetProcAddress(hMod, "SpUserModeInitialize");
250
251 if (pSpLsaModeInitialize && pSpUserModeInitialize)
252 {
253 testInitialize();
254 testGetInfo();
255 }
256 else win_skip( "schannel functions not found\n" );
257
258 FreeLibrary(hMod);
259 }