Make secur32.dll tests load on nt 4.0.
[wine] / dlls / secur32 / tests / main.c
1 /*
2  * Miscellaneous secur32 tests
3  *
4  * Copyright 2005 Kai Blin
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define SECURITY_WIN32
22
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <windows.h>
26 #include "wine/test.h"
27 #include <winbase.h>
28 #include <sspi.h>
29
30 #define BUFF_SIZE 2048
31 #define MAX_MESSAGE 12000
32
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*);
38
39 void InitFunctionPtrs(void)
40 {
41     secdll = LoadLibraryA("secur32.dll");
42     if(!secdll)
43         secdll = LoadLibraryA("security.dll");
44     if(secdll)
45     {
46         pInitSecurityInterfaceA = (PVOID)GetProcAddress(secdll, "InitSecurityInterfaceA");
47         pEnumerateSecurityPackagesA = (PVOID)GetProcAddress(secdll, "EnumerateSecurityPackagesA");
48         pFreeContextBuffer = (PVOID)GetProcAddress(secdll, "FreeContextBuffer");
49         pQuerySecurityPackageInfoA = (PVOID)GetProcAddress(secdll, "QuerySecurityPackageInfo");
50     }
51 }
52
53 /*---------------------------------------------------------*/
54 /* General helper functions */
55
56 static const char* getSecStatusError(SECURITY_STATUS status)
57 {
58 #define _SEC_ERR(x) case (x): return #x;
59     switch(status)
60     {
61         _SEC_ERR(SEC_E_OK);
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);
75         default:
76             trace("Error = %ld\n", status);
77             return "Unknown error";
78     }
79 #undef _SEC_ERR
80 }
81
82 /*---------------------------------------------------------*/
83 /* Helper for testQuerySecurityPagageInfo */
84
85 static SECURITY_STATUS setupPackageA(SEC_CHAR *p_package_name, 
86         PSecPkgInfo *p_pkg_info)
87 {
88     SECURITY_STATUS ret = SEC_E_SECPKG_NOT_FOUND;
89     
90     ret = pQuerySecurityPackageInfoA( p_package_name, p_pkg_info);
91     return ret;
92 }
93
94 /*---------------------------------------------------------*/
95 /* Helper for testAuthentication */
96
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)
100 {
101     SECURITY_STATUS sec_status;
102     TimeStamp       ttl;
103     SecBufferDesc   in_sec_buff_desc, out_sec_buff_desc;
104     SecBuffer       in_sec_buff, out_sec_buff;
105     ULONG           context_attr;
106
107     if(in == NULL){
108         sec_status = (sft->AcquireCredentialsHandle)(NULL, "Negotiate", 
109                 SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, cred_handle,
110                 &ttl);
111         ok(sec_status == SEC_E_OK, 
112                 "Client AcquireCredentialsHandle should not return %s\n",
113                 getSecStatusError(sec_status) );
114     }
115
116     out_sec_buff_desc.ulVersion = 0;
117     out_sec_buff_desc.cBuffers  = 1;
118     out_sec_buff_desc.pBuffers  = &out_sec_buff;
119
120     out_sec_buff.cbBuffer   = *out_count;
121     out_sec_buff.BufferType = SECBUFFER_TOKEN;
122     out_sec_buff.pvBuffer = out;
123
124     if(in){
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;
129
130         in_sec_buff.cbBuffer   = in_count;
131         in_sec_buff.BufferType = SECBUFFER_TOKEN;
132         in_sec_buff.pvBuffer = in;
133         
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);
138
139     }
140     else {
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);
144     }
145
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, 
150                     &out_sec_buff_desc);
151             ok((sec_status == SEC_E_OK)||(sec_status == SEC_I_CONTINUE_NEEDED),
152                     "CompleteAuthToken should not return %s\n", 
153                     getSecStatusError(sec_status));
154
155         }
156
157     }
158
159     *out_count = out_sec_buff.cbBuffer;
160     *done = !( (sec_status == SEC_I_CONTINUE_NEEDED) || 
161             (sec_status == SEC_I_COMPLETE_AND_CONTINUE));
162
163     return 0;
164
165 }
166
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)
170 {
171     SECURITY_STATUS sec_status;
172     TimeStamp       ttl;
173     SecBufferDesc   in_sec_buff_desc, out_sec_buff_desc;
174     SecBuffer       in_sec_buff, out_sec_buff;
175     DWORD           ctxt_attr;
176
177     out_sec_buff_desc.ulVersion = 0;
178     out_sec_buff_desc.cBuffers  = 1;
179     out_sec_buff_desc.pBuffers  = &out_sec_buff;
180
181     out_sec_buff.cbBuffer   = *out_count;
182     out_sec_buff.BufferType = SECBUFFER_TOKEN;
183     out_sec_buff.pvBuffer = out;
184
185     in_sec_buff_desc.ulVersion = 0;
186     in_sec_buff_desc.cBuffers  = 1;
187     in_sec_buff_desc.pBuffers  = &in_sec_buff;
188
189     in_sec_buff.cbBuffer   = in_count;
190     in_sec_buff.BufferType = SECBUFFER_TOKEN;
191     in_sec_buff.pvBuffer = in;
192         
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);
197
198    ok((sec_status == SEC_E_OK) || (sec_status == SEC_I_CONTINUE_NEEDED), 
199            "AcceptSecurityContext returned %s\n",
200            getSecStatusError(sec_status));
201
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, 
206                     &out_sec_buff_desc);
207
208             ok((sec_status ==SEC_E_OK) || (sec_status ==SEC_I_CONTINUE_NEEDED),
209                     "CompleteAuthToken should not return %s\n",
210                     getSecStatusError(sec_status));
211         }
212     }
213
214     *out_count = out_sec_buff.cbBuffer;
215     *done = !( (sec_status == SEC_I_CONTINUE_NEEDED) || 
216             (sec_status == SEC_I_COMPLETE_AND_CONTINUE));
217
218     return 0;
219
220 }
221
222
223 /*--------------------------------------------------------- */
224 /* The test functions */
225
226 static void testInitSecurityInterface(void)
227 {
228     PSecurityFunctionTable sec_fun_table = NULL;
229
230     sec_fun_table = pInitSecurityInterfaceA();
231     ok(sec_fun_table != NULL, "InitSecurityInterface() returned NULL.\n");
232
233 }
234
235 static void testEnumerateSecurityPackages(void)
236 {
237
238     SECURITY_STATUS sec_status;
239     ULONG           num_packages, i;
240     PSecPkgInfo     pkg_info = NULL;
241
242     trace("Running testEnumerateSecurityPackages\n");
243     
244     sec_status = pEnumerateSecurityPackagesA(&num_packages, &pkg_info);
245
246     ok(sec_status == SEC_E_OK, 
247             "EnumerateSecurityPackages() should return %ld, not %08lx\n",
248             (LONG)SEC_E_OK, (LONG)sec_status);
249
250     ok(num_packages > 0, "Number of sec packages should be > 0 ,but is %ld\n",
251             num_packages);
252
253     ok(pkg_info != NULL, 
254             "pkg_info should not be NULL after EnumerateSecurityPackages\n");
255     
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);
285         trace("\n");
286     }
287
288     pFreeContextBuffer(pkg_info);
289 }
290
291
292 static void testQuerySecurityPackageInfo(void)
293 {
294     SECURITY_STATUS     sec_status;
295     SEC_CHAR            sec_pkg_name[256];
296     PSecPkgInfo         pkg_info = NULL;
297     ULONG               max_token = 0;
298     USHORT              version = 0;
299     
300     trace("Running testQuerySecurityPackageInfo\n");
301     
302     /* Test with an existing package. Test should pass */
303     
304     lstrcpy(sec_pkg_name, "Negotiate");
305     
306     sec_status = setupPackageA(sec_pkg_name, &pkg_info);
307
308     ok(sec_status == SEC_E_OK, 
309        "Return value of QuerySecurityPackageInfo() shouldn't be %s\n",
310        getSecStatusError(sec_status) );
311     ok(pkg_info != NULL, 
312                 "QuerySecurityPackageInfo should give struct SecPkgInfo, but is NULL\n");
313     
314     if(pkg_info != NULL){
315         max_token = pkg_info->cbMaxToken;
316         version   = pkg_info->wVersion;
317     }
318     
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",
321             max_token);
322
323     sec_status = pFreeContextBuffer(&pkg_info);
324     
325     ok( sec_status == SEC_E_OK,
326         "Return value of FreeContextBuffer() shouldn't be %s\n",
327         getSecStatusError(sec_status) );
328
329     /* Test with a nonexistent package, test should fail */
330    
331     lstrcpy(sec_pkg_name, "Winetest");
332
333     sec_status = pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info);
334
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));
337
338     sec_status = pFreeContextBuffer(&pkg_info);
339     
340     ok( sec_status == SEC_E_OK,
341         "Return value of FreeContextBuffer() shouldn't be %s\n",
342         getSecStatusError(sec_status) );
343
344
345 }
346
347 void testAuthentication(void)
348 {
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;
359
360     trace("Running testAuthentication\n");
361
362     sft = pInitSecurityInterfaceA();
363
364     ok(sft != NULL, "InitSecurityInterface() returned NULL!\n");
365
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));
370     
371     sec_status = (sft->AcquireCredentialsHandle)(NULL, "Negotiate", 
372             SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &server_cred, 
373             &server_ttl);
374
375     ok(sec_status == SEC_E_OK, 
376             "Server's AcquireCredentialsHandle returned %s.\n", 
377             getSecStatusError(sec_status) );
378
379     
380     genClientContext(NULL, 0, server_buff, &count_server, &done, "foo", 
381             &client_cred, &client_ctxt, sft);
382
383     while(!done){
384         genServerContext(server_buff, count_server, client_buff, 
385                 &count_client, &done, &new_conn, &server_cred, &server_ctxt, 
386                 sft);
387         new_conn = FALSE;
388         genClientContext(client_buff, count_client, server_buff, 
389                 &count_server, &done, "foo", &client_cred, &client_ctxt, sft);
390     }
391
392     pFreeContextBuffer(&client_buff);
393     pFreeContextBuffer(&server_buff);
394
395 }
396
397 START_TEST(main)
398 {
399     InitFunctionPtrs();
400     if(pInitSecurityInterfaceA)
401         testInitSecurityInterface();
402     if(pFreeContextBuffer)
403     {
404         if(pEnumerateSecurityPackagesA)
405             testEnumerateSecurityPackages();
406         if(pQuerySecurityPackageInfoA)
407             testQuerySecurityPackageInfo();
408         if(pInitSecurityInterfaceA)
409             testAuthentication();
410     }
411     if(secdll)
412         FreeLibrary(secdll);
413 }