r14363: Remove credentials.h from the global includes.
[gd/samba-autobuild/.git] / source4 / torture / raw / context.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for session setup operations
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program 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
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/composite/composite.h"
25 #include "libcli/smb_composite/smb_composite.h"
26 #include "lib/cmdline/popt_common.h"
27 #include "lib/events/events.h"
28 #include "libcli/libcli.h"
29 #include "auth/credentials/credentials.h"
30
31 #define BASEDIR "\\rawcontext"
32
33 #define CHECK_STATUS(status, correct) do { \
34         if (!NT_STATUS_EQUAL(status, correct)) { \
35                 printf("(%s) Incorrect status %s - should be %s\n", \
36                        __location__, nt_errstr(status), nt_errstr(correct)); \
37                 ret = False; \
38                 goto done; \
39         }} while (0)
40
41 #define CHECK_VALUE(v, correct) do { \
42         if ((v) != (correct)) { \
43                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
44                        __location__, #v, v, correct); \
45                 ret = False; \
46                 goto done; \
47         }} while (0)
48
49 #define CHECK_NOT_VALUE(v, correct) do { \
50         if ((v) == (correct)) { \
51                 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
52                        __location__, #v, v, correct); \
53                 ret = False; \
54                 goto done; \
55         }} while (0)
56
57
58 /*
59   test session ops
60 */
61 static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
62 {
63         NTSTATUS status;
64         BOOL ret = True;
65         struct smbcli_session *session;
66         struct smbcli_session *session2;
67         struct smbcli_session *session3;
68         struct smbcli_session *session4;
69         struct cli_credentials *anon_creds;
70         struct smbcli_session *sessions[15];
71         struct composite_context *composite_contexts[15];
72         struct smbcli_tree *tree;
73         struct smb_composite_sesssetup setup;
74         struct smb_composite_sesssetup setups[15];
75         union smb_open io;
76         union smb_write wr;
77         union smb_close cl;
78         int fnum;
79         const char *fname = BASEDIR "\\test.txt";
80         uint8_t c = 1;
81         int i;
82
83         printf("TESTING SESSION HANDLING\n");
84
85         if (!torture_setup_dir(cli, BASEDIR)) {
86                 return False;
87         }
88
89         printf("create a second security context on the same transport\n");
90         session = smbcli_session_init(cli->transport, mem_ctx, False);
91
92         setup.in.sesskey = cli->transport->negotiate.sesskey;
93         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
94         setup.in.workgroup = lp_workgroup();
95
96         setup.in.credentials = cmdline_credentials;
97
98         status = smb_composite_sesssetup(session, &setup);
99         CHECK_STATUS(status, NT_STATUS_OK);
100         
101         session->vuid = setup.out.vuid;
102
103         printf("create a third security context on the same transport, with vuid set\n");
104         session2 = smbcli_session_init(cli->transport, mem_ctx, False);
105
106         session2->vuid = session->vuid;
107         setup.in.sesskey = cli->transport->negotiate.sesskey;
108         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
109         setup.in.workgroup = lp_workgroup();
110
111         setup.in.credentials = cmdline_credentials;
112
113         status = smb_composite_sesssetup(session2, &setup);
114         CHECK_STATUS(status, NT_STATUS_OK);
115
116         session2->vuid = setup.out.vuid;
117         printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
118         
119         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
120                 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
121                 if (session2->vuid == session->vuid) {
122                         printf("server allows the user to re-use an existing vuid in session setup \n");
123                 }
124         } else {
125                 CHECK_NOT_VALUE(session2->vuid, session->vuid);
126         }
127         talloc_free(session2);
128
129         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
130                 printf("create a fourth security context on the same transport, without extended security\n");
131                 session3 = smbcli_session_init(cli->transport, mem_ctx, False);
132
133                 session3->vuid = session->vuid;
134                 setup.in.sesskey = cli->transport->negotiate.sesskey;
135                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
136                 setup.in.workgroup = lp_workgroup();
137         
138                 setup.in.credentials = cmdline_credentials;
139         
140
141                 status = smb_composite_sesssetup(session3, &setup);
142                 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
143
144                 printf("create a fouth anonymous security context on the same transport, without extended security\n");
145                 session4 = smbcli_session_init(cli->transport, mem_ctx, False);
146
147                 session4->vuid = session->vuid;
148                 setup.in.sesskey = cli->transport->negotiate.sesskey;
149                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
150                 setup.in.workgroup = lp_workgroup();
151                 
152                 anon_creds = cli_credentials_init(mem_ctx);
153                 cli_credentials_set_conf(anon_creds);
154                 cli_credentials_set_anonymous(anon_creds);
155
156                 setup.in.credentials = anon_creds;
157         
158                 status = smb_composite_sesssetup(session3, &setup);
159                 CHECK_STATUS(status, NT_STATUS_OK);
160
161                 talloc_free(session4);
162         }
163                 
164         printf("use the same tree as the existing connection\n");
165         tree = smbcli_tree_init(session, mem_ctx, False);
166         tree->tid = cli->tree->tid;
167
168         printf("create a file using the new vuid\n");
169         io.generic.level = RAW_OPEN_NTCREATEX;
170         io.ntcreatex.in.root_fid = 0;
171         io.ntcreatex.in.flags = 0;
172         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
173         io.ntcreatex.in.create_options = 0;
174         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
175         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
176         io.ntcreatex.in.alloc_size = 0;
177         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
178         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
179         io.ntcreatex.in.security_flags = 0;
180         io.ntcreatex.in.fname = fname;
181         status = smb_raw_open(tree, mem_ctx, &io);
182         CHECK_STATUS(status, NT_STATUS_OK);
183         fnum = io.ntcreatex.out.file.fnum;
184
185         printf("write using the old vuid\n");
186         wr.generic.level = RAW_WRITE_WRITEX;
187         wr.writex.in.file.fnum = fnum;
188         wr.writex.in.offset = 0;
189         wr.writex.in.wmode = 0;
190         wr.writex.in.remaining = 0;
191         wr.writex.in.count = 1;
192         wr.writex.in.data = &c;
193
194         status = smb_raw_write(cli->tree, &wr);
195         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
196
197         printf("write with the new vuid\n");
198         status = smb_raw_write(tree, &wr);
199         CHECK_STATUS(status, NT_STATUS_OK);
200         CHECK_VALUE(wr.writex.out.nwritten, 1);
201
202         printf("logoff the new vuid\n");
203         status = smb_raw_ulogoff(session);
204         CHECK_STATUS(status, NT_STATUS_OK);
205
206         printf("the new vuid should not now be accessible\n");
207         status = smb_raw_write(tree, &wr);
208         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
209
210         printf("second logoff for the new vuid should fail\n");
211         status = smb_raw_ulogoff(session);
212         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
213         talloc_free(session);
214
215         printf("the fnum should have been auto-closed\n");
216         cl.close.level = RAW_CLOSE_CLOSE;
217         cl.close.in.file.fnum = fnum;
218         cl.close.in.write_time = 0;
219         status = smb_raw_close(cli->tree, &cl);
220         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
221
222         printf("create %d secondary security contexts on the same transport\n", 
223                (int)ARRAY_SIZE(sessions));
224         for (i=0; i <ARRAY_SIZE(sessions); i++) {
225                 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
226                 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
227                 setups[i].in.workgroup = lp_workgroup();
228                 
229                 setups[i].in.credentials = cmdline_credentials;
230
231                 sessions[i] = smbcli_session_init(cli->transport, mem_ctx, False);
232                 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
233
234         }
235
236
237         /* flush the queue */
238         for (i=0; i < ARRAY_SIZE(sessions); i++) {
239                 event_loop_once(composite_contexts[0]->event_ctx);
240         }
241
242         printf("finishing %d secondary security contexts on the same transport\n", 
243                (int)ARRAY_SIZE(sessions));
244         for (i=0; i< ARRAY_SIZE(sessions); i++) {
245                 status = smb_composite_sesssetup_recv(composite_contexts[i]);
246                 CHECK_STATUS(status, NT_STATUS_OK);
247                 sessions[i]->vuid = setups[i].out.vuid;
248                 printf("VUID: %d\n", sessions[i]->vuid);
249                 status = smb_raw_ulogoff(sessions[i]);
250                 CHECK_STATUS(status, NT_STATUS_OK);
251         }
252
253
254         talloc_free(tree);
255         
256 done:
257         return ret;
258 }
259
260
261 /*
262   test tree ops
263 */
264 static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
265 {
266         NTSTATUS status;
267         BOOL ret = True;
268         const char *share, *host;
269         struct smbcli_tree *tree;
270         union smb_tcon tcon;
271         union smb_open io;
272         union smb_write wr;
273         union smb_close cl;
274         int fnum;
275         const char *fname = BASEDIR "\\test.txt";
276         uint8_t c = 1;
277
278         printf("TESTING TREE HANDLING\n");
279
280         if (!torture_setup_dir(cli, BASEDIR)) {
281                 return False;
282         }
283
284         share = lp_parm_string(-1, "torture", "share");
285         host  = lp_parm_string(-1, "torture", "host");
286         
287         printf("create a second tree context on the same session\n");
288         tree = smbcli_tree_init(cli->session, mem_ctx, False);
289
290         tcon.generic.level = RAW_TCON_TCONX;
291         tcon.tconx.in.flags = 0;
292         tcon.tconx.in.password = data_blob(NULL, 0);
293         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
294         tcon.tconx.in.device = "A:";    
295         status = smb_raw_tcon(tree, mem_ctx, &tcon);
296         CHECK_STATUS(status, NT_STATUS_OK);
297         
298
299         tree->tid = tcon.tconx.out.tid;
300         printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
301
302         printf("try a tconx with a bad device type\n");
303         tcon.tconx.in.device = "FOO";   
304         status = smb_raw_tcon(tree, mem_ctx, &tcon);
305         CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
306
307
308         printf("create a file using the new tid\n");
309         io.generic.level = RAW_OPEN_NTCREATEX;
310         io.ntcreatex.in.root_fid = 0;
311         io.ntcreatex.in.flags = 0;
312         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
313         io.ntcreatex.in.create_options = 0;
314         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
315         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
316         io.ntcreatex.in.alloc_size = 0;
317         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
318         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
319         io.ntcreatex.in.security_flags = 0;
320         io.ntcreatex.in.fname = fname;
321         status = smb_raw_open(tree, mem_ctx, &io);
322         CHECK_STATUS(status, NT_STATUS_OK);
323         fnum = io.ntcreatex.out.file.fnum;
324
325         printf("write using the old tid\n");
326         wr.generic.level = RAW_WRITE_WRITEX;
327         wr.writex.in.file.fnum = fnum;
328         wr.writex.in.offset = 0;
329         wr.writex.in.wmode = 0;
330         wr.writex.in.remaining = 0;
331         wr.writex.in.count = 1;
332         wr.writex.in.data = &c;
333
334         status = smb_raw_write(cli->tree, &wr);
335         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
336
337         printf("write with the new tid\n");
338         status = smb_raw_write(tree, &wr);
339         CHECK_STATUS(status, NT_STATUS_OK);
340         CHECK_VALUE(wr.writex.out.nwritten, 1);
341
342         printf("disconnect the new tid\n");
343         status = smb_tree_disconnect(tree);
344         CHECK_STATUS(status, NT_STATUS_OK);
345
346         printf("the new tid should not now be accessible\n");
347         status = smb_raw_write(tree, &wr);
348         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
349
350         printf("the fnum should have been auto-closed\n");
351         cl.close.level = RAW_CLOSE_CLOSE;
352         cl.close.in.file.fnum = fnum;
353         cl.close.in.write_time = 0;
354         status = smb_raw_close(cli->tree, &cl);
355         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
356
357         /* close down the new tree */
358         talloc_free(tree);
359         
360 done:
361         return ret;
362 }
363
364
365 /*
366   test pid ops
367 */
368 static BOOL test_pid(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
369 {
370         NTSTATUS status;
371         BOOL ret = True;
372         union smb_open io;
373         union smb_write wr;
374         union smb_close cl;
375         int fnum;
376         const char *fname = BASEDIR "\\test.txt";
377         uint8_t c = 1;
378         uint16_t pid1, pid2;
379
380         printf("TESTING PID HANDLING\n");
381
382         if (!torture_setup_dir(cli, BASEDIR)) {
383                 return False;
384         }
385
386         printf("create a second pid\n");
387         pid1 = cli->session->pid;
388         pid2 = pid1+1;
389
390         printf("pid1=%d pid2=%d\n", pid1, pid2);
391
392         printf("create a file using the new pid\n");
393         cli->session->pid = pid2;
394         io.generic.level = RAW_OPEN_NTCREATEX;
395         io.ntcreatex.in.root_fid = 0;
396         io.ntcreatex.in.flags = 0;
397         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
398         io.ntcreatex.in.create_options = 0;
399         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
400         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
401         io.ntcreatex.in.alloc_size = 0;
402         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
403         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
404         io.ntcreatex.in.security_flags = 0;
405         io.ntcreatex.in.fname = fname;
406         status = smb_raw_open(cli->tree, mem_ctx, &io);
407         CHECK_STATUS(status, NT_STATUS_OK);
408         fnum = io.ntcreatex.out.file.fnum;
409
410         printf("write using the old pid\n");
411         cli->session->pid = pid1;
412         wr.generic.level = RAW_WRITE_WRITEX;
413         wr.writex.in.file.fnum = fnum;
414         wr.writex.in.offset = 0;
415         wr.writex.in.wmode = 0;
416         wr.writex.in.remaining = 0;
417         wr.writex.in.count = 1;
418         wr.writex.in.data = &c;
419
420         status = smb_raw_write(cli->tree, &wr);
421         CHECK_STATUS(status, NT_STATUS_OK);
422         CHECK_VALUE(wr.writex.out.nwritten, 1);
423
424         printf("write with the new pid\n");
425         cli->session->pid = pid2;
426         status = smb_raw_write(cli->tree, &wr);
427         CHECK_STATUS(status, NT_STATUS_OK);
428         CHECK_VALUE(wr.writex.out.nwritten, 1);
429
430         printf("exit the old pid\n");
431         cli->session->pid = pid1;
432         status = smb_raw_exit(cli->session);
433         CHECK_STATUS(status, NT_STATUS_OK);
434
435         printf("the fnum should still be accessible\n");
436         cli->session->pid = pid1;
437         status = smb_raw_write(cli->tree, &wr);
438         CHECK_STATUS(status, NT_STATUS_OK);
439         CHECK_VALUE(wr.writex.out.nwritten, 1);
440
441         printf("exit the new pid\n");
442         cli->session->pid = pid2;
443         status = smb_raw_exit(cli->session);
444         CHECK_STATUS(status, NT_STATUS_OK);
445
446         printf("the fnum should not now be accessible\n");
447         cli->session->pid = pid1;
448         status = smb_raw_write(cli->tree, &wr);
449         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
450
451         printf("the fnum should have been auto-closed\n");
452         cl.close.level = RAW_CLOSE_CLOSE;
453         cl.close.in.file.fnum = fnum;
454         cl.close.in.write_time = 0;
455         status = smb_raw_close(cli->tree, &cl);
456         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
457
458 done:
459         return ret;
460 }
461
462
463 /* 
464    basic testing of session/tree context calls
465 */
466 static BOOL torture_raw_context_int(void)
467 {
468         struct smbcli_state *cli;
469         BOOL ret = True;
470         TALLOC_CTX *mem_ctx;
471
472         if (!torture_open_connection(&cli)) {
473                 return False;
474         }
475
476         mem_ctx = talloc_init("torture_raw_context");
477
478         if (!test_session(cli, mem_ctx)) {
479                 ret = False;
480         }
481
482         if (!test_tree(cli, mem_ctx)) {
483                 ret = False;
484         }
485
486         if (!test_pid(cli, mem_ctx)) {
487                 ret = False;
488         }
489
490         smb_raw_exit(cli->session);
491         smbcli_deltree(cli->tree, BASEDIR);
492
493         torture_close_connection(cli);
494         talloc_free(mem_ctx);
495
496         return ret;
497 }
498 /* 
499    basic testing of session/tree context calls
500 */
501 BOOL torture_raw_context(void)
502 {
503         BOOL ret = True;
504         if (lp_use_spnego()) {
505                 ret &= torture_raw_context_int();
506                 lp_set_cmdline("use spnego", "False");
507         }
508
509         ret &= torture_raw_context_int();
510
511         return ret;
512 }