2 * Miscellaneous secur32 tests
4 * Copyright 2005 Kai Blin
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define SECURITY_WIN32
26 #include "wine/test.h"
30 #define BUFF_SIZE 2048
31 #define MAX_MESSAGE 12000
33 static HMODULE secdll;
34 static PSecurityFunctionTableA (SEC_ENTRY * pInitSecurityInterfaceA)(void);
35 static SECURITY_STATUS (SEC_ENTRY * pEnumerateSecurityPackagesA)(PULONG, PSecPkgInfoA*);
36 static SECURITY_STATUS (SEC_ENTRY * pFreeContextBuffer)(PVOID pv);
37 static SECURITY_STATUS (SEC_ENTRY * pQuerySecurityPackageInfoA)(SEC_CHAR*, PSecPkgInfoA*);
39 void InitFunctionPtrs(void)
41 secdll = LoadLibraryA("secur32.dll");
43 secdll = LoadLibraryA("security.dll");
46 pInitSecurityInterfaceA = (PVOID)GetProcAddress(secdll, "InitSecurityInterfaceA");
47 pEnumerateSecurityPackagesA = (PVOID)GetProcAddress(secdll, "EnumerateSecurityPackagesA");
48 pFreeContextBuffer = (PVOID)GetProcAddress(secdll, "FreeContextBuffer");
49 pQuerySecurityPackageInfoA = (PVOID)GetProcAddress(secdll, "QuerySecurityPackageInfo");
53 /*---------------------------------------------------------*/
54 /* General helper functions */
56 static const char* getSecStatusError(SECURITY_STATUS status)
58 #define _SEC_ERR(x) case (x): return #x;
62 _SEC_ERR(SEC_E_INSUFFICIENT_MEMORY);
63 _SEC_ERR(SEC_E_INVALID_HANDLE);
64 _SEC_ERR(SEC_E_UNSUPPORTED_FUNCTION);
65 _SEC_ERR(SEC_E_TARGET_UNKNOWN);
66 _SEC_ERR(SEC_E_INTERNAL_ERROR);
67 _SEC_ERR(SEC_E_SECPKG_NOT_FOUND);
68 _SEC_ERR(SEC_E_NOT_OWNER);
69 _SEC_ERR(SEC_E_CANNOT_INSTALL);
70 _SEC_ERR(SEC_E_INVALID_TOKEN);
71 _SEC_ERR(SEC_E_CANNOT_PACK);
72 _SEC_ERR(SEC_E_QOP_NOT_SUPPORTED);
73 _SEC_ERR(SEC_E_NO_IMPERSONATION);
74 _SEC_ERR(SEC_I_CONTINUE_NEEDED);
76 trace("Error = %ld\n", status);
77 return "Unknown error";
82 /*---------------------------------------------------------*/
83 /* Helper for testQuerySecurityPagageInfo */
85 static SECURITY_STATUS setupPackageA(SEC_CHAR *p_package_name,
86 PSecPkgInfo *p_pkg_info)
88 SECURITY_STATUS ret = SEC_E_SECPKG_NOT_FOUND;
90 ret = pQuerySecurityPackageInfoA( p_package_name, p_pkg_info);
94 /*---------------------------------------------------------*/
95 /* Helper for testAuthentication */
97 static int genClientContext(PBYTE in, DWORD in_count, PBYTE out,
98 DWORD *out_count, BOOL *done, char *target, CredHandle *cred_handle,
99 PCtxtHandle ctxt_handle, PSecurityFunctionTable sft)
101 SECURITY_STATUS sec_status;
103 SecBufferDesc in_sec_buff_desc, out_sec_buff_desc;
104 SecBuffer in_sec_buff, out_sec_buff;
108 sec_status = (sft->AcquireCredentialsHandle)(NULL, "Negotiate",
109 SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, cred_handle,
111 ok(sec_status == SEC_E_OK,
112 "Client AcquireCredentialsHandle should not return %s\n",
113 getSecStatusError(sec_status) );
116 out_sec_buff_desc.ulVersion = 0;
117 out_sec_buff_desc.cBuffers = 1;
118 out_sec_buff_desc.pBuffers = &out_sec_buff;
120 out_sec_buff.cbBuffer = *out_count;
121 out_sec_buff.BufferType = SECBUFFER_TOKEN;
122 out_sec_buff.pvBuffer = out;
125 /* we got some data, initialize input buffer, too. */
126 in_sec_buff_desc.ulVersion = 0;
127 in_sec_buff_desc.cBuffers = 1;
128 in_sec_buff_desc.pBuffers = &in_sec_buff;
130 in_sec_buff.cbBuffer = in_count;
131 in_sec_buff.BufferType = SECBUFFER_TOKEN;
132 in_sec_buff.pvBuffer = in;
134 sec_status = (sft->InitializeSecurityContext)( cred_handle, ctxt_handle,
135 target,ISC_REQ_CONFIDENTIALITY, 0, SECURITY_NATIVE_DREP,
136 &in_sec_buff_desc, 0, ctxt_handle, &out_sec_buff_desc,
137 &context_attr, &ttl);
141 sec_status = (sft->InitializeSecurityContext)( cred_handle, NULL,
142 target, ISC_REQ_CONFIDENTIALITY, 0, SECURITY_NATIVE_DREP, NULL,
143 0, ctxt_handle, &out_sec_buff_desc, &context_attr, &ttl);
146 if( (sec_status == SEC_I_COMPLETE_NEEDED) ||
147 (sec_status == SEC_I_COMPLETE_AND_CONTINUE)){
148 if(sft->CompleteAuthToken != NULL){
149 sec_status = (sft->CompleteAuthToken)( ctxt_handle,
151 ok((sec_status == SEC_E_OK)||(sec_status == SEC_I_CONTINUE_NEEDED),
152 "CompleteAuthToken should not return %s\n",
153 getSecStatusError(sec_status));
159 *out_count = out_sec_buff.cbBuffer;
160 *done = !( (sec_status == SEC_I_CONTINUE_NEEDED) ||
161 (sec_status == SEC_I_COMPLETE_AND_CONTINUE));
167 static int genServerContext(PBYTE in, DWORD in_count, PBYTE out,
168 DWORD *out_count, BOOL *done, BOOL *new_conn, CredHandle *cred_handle,
169 PCtxtHandle ctxt_handle, PSecurityFunctionTable sft)
171 SECURITY_STATUS sec_status;
173 SecBufferDesc in_sec_buff_desc, out_sec_buff_desc;
174 SecBuffer in_sec_buff, out_sec_buff;
177 out_sec_buff_desc.ulVersion = 0;
178 out_sec_buff_desc.cBuffers = 1;
179 out_sec_buff_desc.pBuffers = &out_sec_buff;
181 out_sec_buff.cbBuffer = *out_count;
182 out_sec_buff.BufferType = SECBUFFER_TOKEN;
183 out_sec_buff.pvBuffer = out;
185 in_sec_buff_desc.ulVersion = 0;
186 in_sec_buff_desc.cBuffers = 1;
187 in_sec_buff_desc.pBuffers = &in_sec_buff;
189 in_sec_buff.cbBuffer = in_count;
190 in_sec_buff.BufferType = SECBUFFER_TOKEN;
191 in_sec_buff.pvBuffer = in;
193 sec_status = (sft->AcceptSecurityContext)( cred_handle,
194 *new_conn ? NULL : ctxt_handle, /* maybe use an if here? */
195 &in_sec_buff_desc, 0, SECURITY_NATIVE_DREP,
196 ctxt_handle, &out_sec_buff_desc, &ctxt_attr, &ttl);
198 ok((sec_status == SEC_E_OK) || (sec_status == SEC_I_CONTINUE_NEEDED),
199 "AcceptSecurityContext returned %s\n",
200 getSecStatusError(sec_status));
202 if( (sec_status == SEC_I_COMPLETE_NEEDED) ||
203 (sec_status == SEC_I_COMPLETE_AND_CONTINUE)){
204 if(sft->CompleteAuthToken != NULL){
205 sec_status = (sft->CompleteAuthToken)( ctxt_handle,
208 ok((sec_status ==SEC_E_OK) || (sec_status ==SEC_I_CONTINUE_NEEDED),
209 "CompleteAuthToken should not return %s\n",
210 getSecStatusError(sec_status));
214 *out_count = out_sec_buff.cbBuffer;
215 *done = !( (sec_status == SEC_I_CONTINUE_NEEDED) ||
216 (sec_status == SEC_I_COMPLETE_AND_CONTINUE));
223 /*--------------------------------------------------------- */
224 /* The test functions */
226 static void testInitSecurityInterface(void)
228 PSecurityFunctionTable sec_fun_table = NULL;
230 sec_fun_table = pInitSecurityInterfaceA();
231 ok(sec_fun_table != NULL, "InitSecurityInterface() returned NULL.\n");
235 static void testEnumerateSecurityPackages(void)
238 SECURITY_STATUS sec_status;
239 ULONG num_packages, i;
240 PSecPkgInfo pkg_info = NULL;
242 trace("Running testEnumerateSecurityPackages\n");
244 sec_status = pEnumerateSecurityPackagesA(&num_packages, &pkg_info);
246 ok(sec_status == SEC_E_OK,
247 "EnumerateSecurityPackages() should return %ld, not %08lx\n",
248 (LONG)SEC_E_OK, (LONG)sec_status);
250 ok(num_packages > 0, "Number of sec packages should be > 0 ,but is %ld\n",
254 "pkg_info should not be NULL after EnumerateSecurityPackages\n");
256 trace("Number of packages: %ld\n", num_packages);
257 for(i = 0; i < num_packages; ++i){
258 trace("%ld: Package \"%s\"\n", i, pkg_info[i].Name);
259 trace("Supported flags:\n");
260 if(pkg_info[i].fCapabilities & SECPKG_FLAG_INTEGRITY)
261 trace("\tSECPKG_FLAG_INTEGRITY\n");
262 if(pkg_info[i].fCapabilities & SECPKG_FLAG_PRIVACY)
263 trace("\tSECPKG_FLAG_PRIVACY\n");
264 if(pkg_info[i].fCapabilities & SECPKG_FLAG_TOKEN_ONLY)
265 trace("\tSECPKG_FLAG_TOKEN_ONLY\n");
266 if(pkg_info[i].fCapabilities & SECPKG_FLAG_DATAGRAM)
267 trace("\tSECPKG_FLAG_DATAGRAM\n");
268 if(pkg_info[i].fCapabilities & SECPKG_FLAG_CONNECTION)
269 trace("\tSECPKG_FLAG_CONNECTION\n");
270 if(pkg_info[i].fCapabilities & SECPKG_FLAG_MULTI_REQUIRED)
271 trace("\tSECPKG_FLAG_MULTI_REQUIRED\n");
272 if(pkg_info[i].fCapabilities & SECPKG_FLAG_CLIENT_ONLY)
273 trace("\tSECPKG_FLAG_CLIENT_ONLY\n");
274 if(pkg_info[i].fCapabilities & SECPKG_FLAG_EXTENDED_ERROR)
275 trace("\tSECPKG_FLAG_EXTENDED_ERROR\n");
276 if(pkg_info[i].fCapabilities & SECPKG_FLAG_IMPERSONATION)
277 trace("\tSECPKG_FLAG_IMPERSONATION\n");
278 if(pkg_info[i].fCapabilities & SECPKG_FLAG_ACCEPT_WIN32_NAME)
279 trace("\tSECPKG_FLAG_ACCEPT_WIN32_NAME\n");
280 if(pkg_info[i].fCapabilities & SECPKG_FLAG_STREAM)
281 trace("\tSECPKG_FLAG_STREAM\n");
282 if(pkg_info[i].fCapabilities & SECPKG_FLAG_READONLY_WITH_CHECKSUM)
283 trace("\tSECPKG_FLAG_READONLY_WITH_CHECKSUM\n");
284 trace("Comment: %s\n", pkg_info[i].Comment);
288 pFreeContextBuffer(pkg_info);
292 static void testQuerySecurityPackageInfo(void)
294 SECURITY_STATUS sec_status;
295 SEC_CHAR sec_pkg_name[256];
296 PSecPkgInfo pkg_info = NULL;
300 trace("Running testQuerySecurityPackageInfo\n");
302 /* Test with an existing package. Test should pass */
304 lstrcpy(sec_pkg_name, "Negotiate");
306 sec_status = setupPackageA(sec_pkg_name, &pkg_info);
308 ok(sec_status == SEC_E_OK,
309 "Return value of QuerySecurityPackageInfo() shouldn't be %s\n",
310 getSecStatusError(sec_status) );
312 "QuerySecurityPackageInfo should give struct SecPkgInfo, but is NULL\n");
314 if(pkg_info != NULL){
315 max_token = pkg_info->cbMaxToken;
316 version = pkg_info->wVersion;
319 ok(version == 1, "wVersion always should be 1, but is %d\n", version);
320 ok(max_token == 12000, "cbMaxToken for Negotiate is %ld, not 12000.\n",
323 sec_status = pFreeContextBuffer(&pkg_info);
325 ok( sec_status == SEC_E_OK,
326 "Return value of FreeContextBuffer() shouldn't be %s\n",
327 getSecStatusError(sec_status) );
329 /* Test with a nonexistent package, test should fail */
331 lstrcpy(sec_pkg_name, "Winetest");
333 sec_status = pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info);
335 ok( sec_status != SEC_E_OK,
336 "Return value of QuerySecurityPackageInfo() should not be %s for a nonexistent package\n", getSecStatusError(SEC_E_OK));
338 sec_status = pFreeContextBuffer(&pkg_info);
340 ok( sec_status == SEC_E_OK,
341 "Return value of FreeContextBuffer() shouldn't be %s\n",
342 getSecStatusError(sec_status) );
347 void testAuthentication(void)
349 CredHandle server_cred, client_cred;
350 CtxtHandle server_ctxt, client_ctxt;
351 BYTE server_buff[MAX_MESSAGE];
352 BYTE client_buff[MAX_MESSAGE];
353 SECURITY_STATUS sec_status;
354 DWORD count_server = MAX_MESSAGE;
355 DWORD count_client = MAX_MESSAGE;
356 BOOL done = FALSE, new_conn = TRUE;
357 TimeStamp server_ttl;
358 PSecurityFunctionTable sft = NULL;
360 trace("Running testAuthentication\n");
362 sft = pInitSecurityInterfaceA();
364 ok(sft != NULL, "InitSecurityInterface() returned NULL!\n");
366 memset(&server_cred, 0, sizeof(CredHandle));
367 memset(&client_cred, 0, sizeof(CredHandle));
368 memset(&server_ctxt, 0, sizeof(CtxtHandle));
369 memset(&client_ctxt, 0, sizeof(CtxtHandle));
371 sec_status = (sft->AcquireCredentialsHandle)(NULL, "Negotiate",
372 SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &server_cred,
375 ok(sec_status == SEC_E_OK,
376 "Server's AcquireCredentialsHandle returned %s.\n",
377 getSecStatusError(sec_status) );
380 genClientContext(NULL, 0, server_buff, &count_server, &done, "foo",
381 &client_cred, &client_ctxt, sft);
384 genServerContext(server_buff, count_server, client_buff,
385 &count_client, &done, &new_conn, &server_cred, &server_ctxt,
388 genClientContext(client_buff, count_client, server_buff,
389 &count_server, &done, "foo", &client_cred, &client_ctxt, sft);
392 pFreeContextBuffer(&client_buff);
393 pFreeContextBuffer(&server_buff);
400 if(pInitSecurityInterfaceA)
401 testInitSecurityInterface();
402 if(pFreeContextBuffer)
404 if(pEnumerateSecurityPackagesA)
405 testEnumerateSecurityPackages();
406 if(pQuerySecurityPackageInfoA)
407 testQuerySecurityPackageInfo();
408 if(pInitSecurityInterfaceA)
409 testAuthentication();