0c9bcc417f8bc036c75bc31dd38daa6c70ec3e20
[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 "torture/util.h"
30 #include "auth/credentials/credentials.h"
31
32 #define BASEDIR "\\rawcontext"
33
34 #define CHECK_STATUS(status, correct) do { \
35         if (!NT_STATUS_EQUAL(status, correct)) { \
36                 printf("(%s) Incorrect status %s - should be %s\n", \
37                        __location__, nt_errstr(status), nt_errstr(correct)); \
38                 ret = False; \
39                 goto done; \
40         }} while (0)
41
42 #define CHECK_VALUE(v, correct) do { \
43         if ((v) != (correct)) { \
44                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
45                        __location__, #v, v, correct); \
46                 ret = False; \
47                 goto done; \
48         }} while (0)
49
50 #define CHECK_NOT_VALUE(v, correct) do { \
51         if ((v) == (correct)) { \
52                 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
53                        __location__, #v, v, correct); \
54                 ret = False; \
55                 goto done; \
56         }} while (0)
57
58
59 /*
60   test session ops
61 */
62 static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
63 {
64         NTSTATUS status;
65         BOOL ret = True;
66         struct smbcli_session *session;
67         struct smbcli_session *session2;
68         struct smbcli_session *session3;
69         struct smbcli_session *session4;
70         struct cli_credentials *anon_creds;
71         struct smbcli_session *sessions[15];
72         struct composite_context *composite_contexts[15];
73         struct smbcli_tree *tree;
74         struct smb_composite_sesssetup setup;
75         struct smb_composite_sesssetup setups[15];
76         union smb_open io;
77         union smb_write wr;
78         union smb_close cl;
79         int fnum;
80         const char *fname = BASEDIR "\\test.txt";
81         uint8_t c = 1;
82         int i;
83
84         printf("TESTING SESSION HANDLING\n");
85
86         if (!torture_setup_dir(cli, BASEDIR)) {
87                 return False;
88         }
89
90         printf("create a second security context on the same transport\n");
91         session = smbcli_session_init(cli->transport, mem_ctx, False);
92
93         setup.in.sesskey = cli->transport->negotiate.sesskey;
94         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
95         setup.in.workgroup = lp_workgroup();
96
97         setup.in.credentials = cmdline_credentials;
98
99         status = smb_composite_sesssetup(session, &setup);
100         CHECK_STATUS(status, NT_STATUS_OK);
101         
102         session->vuid = setup.out.vuid;
103
104         printf("create a third security context on the same transport, with vuid set\n");
105         session2 = smbcli_session_init(cli->transport, mem_ctx, False);
106
107         session2->vuid = session->vuid;
108         setup.in.sesskey = cli->transport->negotiate.sesskey;
109         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
110         setup.in.workgroup = lp_workgroup();
111
112         setup.in.credentials = cmdline_credentials;
113
114         status = smb_composite_sesssetup(session2, &setup);
115         CHECK_STATUS(status, NT_STATUS_OK);
116
117         session2->vuid = setup.out.vuid;
118         printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
119         
120         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
121                 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
122                 if (session2->vuid == session->vuid) {
123                         printf("server allows the user to re-use an existing vuid in session setup \n");
124                 }
125         } else {
126                 CHECK_NOT_VALUE(session2->vuid, session->vuid);
127         }
128         talloc_free(session2);
129
130         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
131                 printf("create a fourth security context on the same transport, without extended security\n");
132                 session3 = smbcli_session_init(cli->transport, mem_ctx, False);
133
134                 session3->vuid = session->vuid;
135                 setup.in.sesskey = cli->transport->negotiate.sesskey;
136                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
137                 setup.in.workgroup = lp_workgroup();
138         
139                 setup.in.credentials = cmdline_credentials;
140         
141
142                 status = smb_composite_sesssetup(session3, &setup);
143                 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
144
145                 printf("create a fouth anonymous security context on the same transport, without extended security\n");
146                 session4 = smbcli_session_init(cli->transport, mem_ctx, False);
147
148                 session4->vuid = session->vuid;
149                 setup.in.sesskey = cli->transport->negotiate.sesskey;
150                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
151                 setup.in.workgroup = lp_workgroup();
152                 
153                 anon_creds = cli_credentials_init(mem_ctx);
154                 cli_credentials_set_conf(anon_creds);
155                 cli_credentials_set_anonymous(anon_creds);
156
157                 setup.in.credentials = anon_creds;
158         
159                 status = smb_composite_sesssetup(session3, &setup);
160                 CHECK_STATUS(status, NT_STATUS_OK);
161
162                 talloc_free(session4);
163         }
164                 
165         printf("use the same tree as the existing connection\n");
166         tree = smbcli_tree_init(session, mem_ctx, False);
167         tree->tid = cli->tree->tid;
168
169         printf("create a file using the new vuid\n");
170         io.generic.level = RAW_OPEN_NTCREATEX;
171         io.ntcreatex.in.root_fid = 0;
172         io.ntcreatex.in.flags = 0;
173         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
174         io.ntcreatex.in.create_options = 0;
175         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
176         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
177         io.ntcreatex.in.alloc_size = 0;
178         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
179         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
180         io.ntcreatex.in.security_flags = 0;
181         io.ntcreatex.in.fname = fname;
182         status = smb_raw_open(tree, mem_ctx, &io);
183         CHECK_STATUS(status, NT_STATUS_OK);
184         fnum = io.ntcreatex.out.file.fnum;
185
186         printf("write using the old vuid\n");
187         wr.generic.level = RAW_WRITE_WRITEX;
188         wr.writex.in.file.fnum = fnum;
189         wr.writex.in.offset = 0;
190         wr.writex.in.wmode = 0;
191         wr.writex.in.remaining = 0;
192         wr.writex.in.count = 1;
193         wr.writex.in.data = &c;
194
195         status = smb_raw_write(cli->tree, &wr);
196         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
197
198         printf("write with the new vuid\n");
199         status = smb_raw_write(tree, &wr);
200         CHECK_STATUS(status, NT_STATUS_OK);
201         CHECK_VALUE(wr.writex.out.nwritten, 1);
202
203         printf("logoff the new vuid\n");
204         status = smb_raw_ulogoff(session);
205         CHECK_STATUS(status, NT_STATUS_OK);
206
207         printf("the new vuid should not now be accessible\n");
208         status = smb_raw_write(tree, &wr);
209         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
210
211         printf("second logoff for the new vuid should fail\n");
212         status = smb_raw_ulogoff(session);
213         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
214         talloc_free(session);
215
216         printf("the fnum should have been auto-closed\n");
217         cl.close.level = RAW_CLOSE_CLOSE;
218         cl.close.in.file.fnum = fnum;
219         cl.close.in.write_time = 0;
220         status = smb_raw_close(cli->tree, &cl);
221         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
222
223         printf("create %d secondary security contexts on the same transport\n", 
224                (int)ARRAY_SIZE(sessions));
225         for (i=0; i <ARRAY_SIZE(sessions); i++) {
226                 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
227                 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
228                 setups[i].in.workgroup = lp_workgroup();
229                 
230                 setups[i].in.credentials = cmdline_credentials;
231
232                 sessions[i] = smbcli_session_init(cli->transport, mem_ctx, False);
233                 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
234
235         }
236
237
238         /* flush the queue */
239         for (i=0; i < ARRAY_SIZE(sessions); i++) {
240                 event_loop_once(composite_contexts[0]->event_ctx);
241         }
242
243         printf("finishing %d secondary security contexts on the same transport\n", 
244                (int)ARRAY_SIZE(sessions));
245         for (i=0; i< ARRAY_SIZE(sessions); i++) {
246                 status = smb_composite_sesssetup_recv(composite_contexts[i]);
247                 CHECK_STATUS(status, NT_STATUS_OK);
248                 sessions[i]->vuid = setups[i].out.vuid;
249                 printf("VUID: %d\n", sessions[i]->vuid);
250                 status = smb_raw_ulogoff(sessions[i]);
251                 CHECK_STATUS(status, NT_STATUS_OK);
252         }
253
254
255         talloc_free(tree);
256         
257 done:
258         return ret;
259 }
260
261
262 /*
263   test tree ops
264 */
265 static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
266 {
267         NTSTATUS status;
268         BOOL ret = True;
269         const char *share, *host;
270         struct smbcli_tree *tree;
271         union smb_tcon tcon;
272         union smb_open io;
273         union smb_write wr;
274         union smb_close cl;
275         int fnum;
276         const char *fname = BASEDIR "\\test.txt";
277         uint8_t c = 1;
278
279         printf("TESTING TREE HANDLING\n");
280
281         if (!torture_setup_dir(cli, BASEDIR)) {
282                 return False;
283         }
284
285         share = lp_parm_string(-1, "torture", "share");
286         host  = lp_parm_string(-1, "torture", "host");
287         
288         printf("create a second tree context on the same session\n");
289         tree = smbcli_tree_init(cli->session, mem_ctx, False);
290
291         tcon.generic.level = RAW_TCON_TCONX;
292         tcon.tconx.in.flags = 0;
293         tcon.tconx.in.password = data_blob(NULL, 0);
294         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
295         tcon.tconx.in.device = "A:";    
296         status = smb_raw_tcon(tree, mem_ctx, &tcon);
297         CHECK_STATUS(status, NT_STATUS_OK);
298         
299
300         tree->tid = tcon.tconx.out.tid;
301         printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
302
303         printf("try a tconx with a bad device type\n");
304         tcon.tconx.in.device = "FOO";   
305         status = smb_raw_tcon(tree, mem_ctx, &tcon);
306         CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
307
308
309         printf("create a file using the new tid\n");
310         io.generic.level = RAW_OPEN_NTCREATEX;
311         io.ntcreatex.in.root_fid = 0;
312         io.ntcreatex.in.flags = 0;
313         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
314         io.ntcreatex.in.create_options = 0;
315         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
316         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
317         io.ntcreatex.in.alloc_size = 0;
318         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
319         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
320         io.ntcreatex.in.security_flags = 0;
321         io.ntcreatex.in.fname = fname;
322         status = smb_raw_open(tree, mem_ctx, &io);
323         CHECK_STATUS(status, NT_STATUS_OK);
324         fnum = io.ntcreatex.out.file.fnum;
325
326         printf("write using the old tid\n");
327         wr.generic.level = RAW_WRITE_WRITEX;
328         wr.writex.in.file.fnum = fnum;
329         wr.writex.in.offset = 0;
330         wr.writex.in.wmode = 0;
331         wr.writex.in.remaining = 0;
332         wr.writex.in.count = 1;
333         wr.writex.in.data = &c;
334
335         status = smb_raw_write(cli->tree, &wr);
336         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
337
338         printf("write with the new tid\n");
339         status = smb_raw_write(tree, &wr);
340         CHECK_STATUS(status, NT_STATUS_OK);
341         CHECK_VALUE(wr.writex.out.nwritten, 1);
342
343         printf("disconnect the new tid\n");
344         status = smb_tree_disconnect(tree);
345         CHECK_STATUS(status, NT_STATUS_OK);
346
347         printf("the new tid should not now be accessible\n");
348         status = smb_raw_write(tree, &wr);
349         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
350
351         printf("the fnum should have been auto-closed\n");
352         cl.close.level = RAW_CLOSE_CLOSE;
353         cl.close.in.file.fnum = fnum;
354         cl.close.in.write_time = 0;
355         status = smb_raw_close(cli->tree, &cl);
356         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
357
358         /* close down the new tree */
359         talloc_free(tree);
360         
361 done:
362         return ret;
363 }
364
365 /*
366   test tree with ulogoff
367   this demonstrates that a tcon isn't autoclosed by a ulogoff
368   the tcon can be reused using any other valid session later
369 */
370 static BOOL test_tree_ulogoff(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
371 {
372         NTSTATUS status;
373         BOOL ret = True;
374         const char *share, *host;
375         struct smbcli_session *session1;
376         struct smbcli_session *session2;
377         struct smb_composite_sesssetup setup;
378         struct smbcli_tree *tree;
379         union smb_tcon tcon;
380         union smb_open io;
381         union smb_write wr;
382         int fnum1, fnum2;
383         const char *fname1 = BASEDIR "\\test1.txt";
384         const char *fname2 = BASEDIR "\\test2.txt";
385         uint8_t c = 1;
386
387         printf("TESTING TREE with ulogoff\n");
388
389         if (!torture_setup_dir(cli, BASEDIR)) {
390                 return False;
391         }
392
393         share = lp_parm_string(-1, "torture", "share");
394         host  = lp_parm_string(-1, "torture", "host");
395
396         printf("create the first new sessions\n");
397         session1 = smbcli_session_init(cli->transport, mem_ctx, False);
398         setup.in.sesskey = cli->transport->negotiate.sesskey;
399         setup.in.capabilities = cli->transport->negotiate.capabilities;
400         setup.in.workgroup = lp_workgroup();
401         setup.in.credentials = cmdline_credentials;
402         status = smb_composite_sesssetup(session1, &setup);
403         CHECK_STATUS(status, NT_STATUS_OK);
404         session1->vuid = setup.out.vuid;
405         printf("vuid1=%d\n", session1->vuid);
406
407         printf("create a tree context on the with vuid1\n");
408         tree = smbcli_tree_init(session1, mem_ctx, False);
409         tcon.generic.level = RAW_TCON_TCONX;
410         tcon.tconx.in.flags = 0;
411         tcon.tconx.in.password = data_blob(NULL, 0);
412         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
413         tcon.tconx.in.device = "A:";
414         status = smb_raw_tcon(tree, mem_ctx, &tcon);
415         CHECK_STATUS(status, NT_STATUS_OK);
416         tree->tid = tcon.tconx.out.tid;
417         printf("tid=%d\n", tree->tid);
418
419         printf("create a file using vuid1\n");
420         io.generic.level = RAW_OPEN_NTCREATEX;
421         io.ntcreatex.in.root_fid = 0;
422         io.ntcreatex.in.flags = 0;
423         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
424         io.ntcreatex.in.create_options = 0;
425         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
426         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
427         io.ntcreatex.in.alloc_size = 0;
428         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
429         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
430         io.ntcreatex.in.security_flags = 0;
431         io.ntcreatex.in.fname = fname1;
432         status = smb_raw_open(tree, mem_ctx, &io);
433         CHECK_STATUS(status, NT_STATUS_OK);
434         fnum1 = io.ntcreatex.out.file.fnum;
435
436         printf("write using vuid1\n");
437         wr.generic.level = RAW_WRITE_WRITEX;
438         wr.writex.in.file.fnum = fnum1;
439         wr.writex.in.offset = 0;
440         wr.writex.in.wmode = 0;
441         wr.writex.in.remaining = 0;
442         wr.writex.in.count = 1;
443         wr.writex.in.data = &c;
444         status = smb_raw_write(tree, &wr);
445         CHECK_STATUS(status, NT_STATUS_OK);
446         CHECK_VALUE(wr.writex.out.nwritten, 1);
447
448         printf("ulogoff the vuid1\n");
449         status = smb_raw_ulogoff(session1);
450         CHECK_STATUS(status, NT_STATUS_OK);
451
452         printf("create the second new sessions\n");
453         session2 = smbcli_session_init(cli->transport, mem_ctx, False);
454         setup.in.sesskey = cli->transport->negotiate.sesskey;
455         setup.in.capabilities = cli->transport->negotiate.capabilities;
456         setup.in.workgroup = lp_workgroup();
457         setup.in.credentials = cmdline_credentials;
458         status = smb_composite_sesssetup(session2, &setup);
459         CHECK_STATUS(status, NT_STATUS_OK);
460         session2->vuid = setup.out.vuid;
461         printf("vuid2=%d\n", session2->vuid);
462
463         printf("use the existing tree with vuid2\n");
464         tree->session = session2;
465
466         printf("create a file using vuid2\n");
467         io.generic.level = RAW_OPEN_NTCREATEX;
468         io.ntcreatex.in.root_fid = 0;
469         io.ntcreatex.in.flags = 0;
470         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
471         io.ntcreatex.in.create_options = 0;
472         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
473         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
474         io.ntcreatex.in.alloc_size = 0;
475         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
476         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
477         io.ntcreatex.in.security_flags = 0;
478         io.ntcreatex.in.fname = fname2;
479         status = smb_raw_open(tree, mem_ctx, &io);
480         CHECK_STATUS(status, NT_STATUS_OK);
481         fnum2 = io.ntcreatex.out.file.fnum;
482
483         printf("write using vuid2\n");
484         wr.generic.level = RAW_WRITE_WRITEX;
485         wr.writex.in.file.fnum = fnum2;
486         wr.writex.in.offset = 0;
487         wr.writex.in.wmode = 0;
488         wr.writex.in.remaining = 0;
489         wr.writex.in.count = 1;
490         wr.writex.in.data = &c;
491         status = smb_raw_write(tree, &wr);
492         CHECK_STATUS(status, NT_STATUS_OK);
493         CHECK_VALUE(wr.writex.out.nwritten, 1);
494
495         printf("ulogoff the vuid2\n");
496         status = smb_raw_ulogoff(session2);
497         CHECK_STATUS(status, NT_STATUS_OK);
498
499         /* this also demonstrates that SMBtdis doesn't need a valid vuid */
500         printf("disconnect the existing tree connection\n");
501         status = smb_tree_disconnect(tree);
502         CHECK_STATUS(status, NT_STATUS_OK);
503
504         printf("disconnect the existing tree connection\n");
505         status = smb_tree_disconnect(tree);
506         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
507
508         /* close down the new tree */
509         talloc_free(tree);
510         
511 done:
512         return ret;
513 }
514
515 /*
516   test pid ops
517   this test demonstrates that exit() only sees the PID
518   used for the open() calls
519 */
520 static BOOL test_pid_exit_only_sees_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
521 {
522         NTSTATUS status;
523         BOOL ret = True;
524         union smb_open io;
525         union smb_write wr;
526         union smb_close cl;
527         int fnum;
528         const char *fname = BASEDIR "\\test.txt";
529         uint8_t c = 1;
530         uint16_t pid1, pid2;
531
532         printf("TESTING PID HANDLING exit() only cares about open() PID\n");
533
534         if (!torture_setup_dir(cli, BASEDIR)) {
535                 return False;
536         }
537
538         pid1 = cli->session->pid;
539         pid2 = pid1 + 1;
540
541         printf("pid1=%d pid2=%d\n", pid1, pid2);
542
543         printf("create a file using pid1\n");
544         cli->session->pid = pid1;
545         io.generic.level = RAW_OPEN_NTCREATEX;
546         io.ntcreatex.in.root_fid = 0;
547         io.ntcreatex.in.flags = 0;
548         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
549         io.ntcreatex.in.create_options = 0;
550         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
551         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
552         io.ntcreatex.in.alloc_size = 0;
553         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
554         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
555         io.ntcreatex.in.security_flags = 0;
556         io.ntcreatex.in.fname = fname;
557         status = smb_raw_open(cli->tree, mem_ctx, &io);
558         CHECK_STATUS(status, NT_STATUS_OK);
559         fnum = io.ntcreatex.out.file.fnum;
560
561         printf("write using pid2\n");
562         cli->session->pid = pid2;
563         wr.generic.level = RAW_WRITE_WRITEX;
564         wr.writex.in.file.fnum = fnum;
565         wr.writex.in.offset = 0;
566         wr.writex.in.wmode = 0;
567         wr.writex.in.remaining = 0;
568         wr.writex.in.count = 1;
569         wr.writex.in.data = &c;
570         status = smb_raw_write(cli->tree, &wr);
571         CHECK_STATUS(status, NT_STATUS_OK);
572         CHECK_VALUE(wr.writex.out.nwritten, 1);
573
574         printf("exit pid2\n");
575         cli->session->pid = pid2;
576         status = smb_raw_exit(cli->session);
577         CHECK_STATUS(status, NT_STATUS_OK);
578
579         printf("the fnum should still be accessible via pid2\n");
580         cli->session->pid = pid2;
581         status = smb_raw_write(cli->tree, &wr);
582         CHECK_STATUS(status, NT_STATUS_OK);
583         CHECK_VALUE(wr.writex.out.nwritten, 1);
584
585         printf("exit pid2\n");
586         cli->session->pid = pid2;
587         status = smb_raw_exit(cli->session);
588         CHECK_STATUS(status, NT_STATUS_OK);
589
590         printf("the fnum should still be accessible via pid1 and pid2\n");
591         cli->session->pid = pid1;
592         status = smb_raw_write(cli->tree, &wr);
593         CHECK_STATUS(status, NT_STATUS_OK);
594         CHECK_VALUE(wr.writex.out.nwritten, 1);
595         cli->session->pid = pid2;
596         status = smb_raw_write(cli->tree, &wr);
597         CHECK_STATUS(status, NT_STATUS_OK);
598         CHECK_VALUE(wr.writex.out.nwritten, 1);
599
600         printf("exit pid1\n");
601         cli->session->pid = pid1;
602         status = smb_raw_exit(cli->session);
603         CHECK_STATUS(status, NT_STATUS_OK);
604
605         printf("the fnum should not now be accessible via pid1 or pid2\n");
606         cli->session->pid = pid1;
607         status = smb_raw_write(cli->tree, &wr);
608         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
609         cli->session->pid = pid2;
610         status = smb_raw_write(cli->tree, &wr);
611         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
612
613         printf("the fnum should have been auto-closed\n");
614         cli->session->pid = pid1;
615         cl.close.level = RAW_CLOSE_CLOSE;
616         cl.close.in.file.fnum = fnum;
617         cl.close.in.write_time = 0;
618         status = smb_raw_close(cli->tree, &cl);
619         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
620
621 done:
622         return ret;
623 }
624
625 /*
626   test pid ops with 2 sessions
627 */
628 static BOOL test_pid_2sess(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
629 {
630         NTSTATUS status;
631         BOOL ret = True;
632         struct smbcli_session *session;
633         struct smb_composite_sesssetup setup;
634         union smb_open io;
635         union smb_write wr;
636         union smb_close cl;
637         int fnum;
638         const char *fname = BASEDIR "\\test.txt";
639         uint8_t c = 1;
640         uint16_t vuid1, vuid2;
641
642         printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
643
644         if (!torture_setup_dir(cli, BASEDIR)) {
645                 return False;
646         }
647
648         printf("create a second security context on the same transport\n");
649         session = smbcli_session_init(cli->transport, mem_ctx, False);
650
651         setup.in.sesskey = cli->transport->negotiate.sesskey;
652         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
653         setup.in.workgroup = lp_workgroup();
654
655         setup.in.credentials = cmdline_credentials;
656
657         status = smb_composite_sesssetup(session, &setup);
658         CHECK_STATUS(status, NT_STATUS_OK);     
659         session->vuid = setup.out.vuid;
660
661         vuid1 = cli->session->vuid;
662         vuid2 = session->vuid;
663
664         printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
665
666         printf("create a file using the vuid1\n");
667         cli->session->vuid = vuid1;
668         io.generic.level = RAW_OPEN_NTCREATEX;
669         io.ntcreatex.in.root_fid = 0;
670         io.ntcreatex.in.flags = 0;
671         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
672         io.ntcreatex.in.create_options = 0;
673         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
674         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
675         io.ntcreatex.in.alloc_size = 0;
676         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
677         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
678         io.ntcreatex.in.security_flags = 0;
679         io.ntcreatex.in.fname = fname;
680         status = smb_raw_open(cli->tree, mem_ctx, &io);
681         CHECK_STATUS(status, NT_STATUS_OK);
682         fnum = io.ntcreatex.out.file.fnum;
683
684         printf("write using the vuid1 (fnum=%d)\n", fnum);
685         cli->session->vuid = vuid1;
686         wr.generic.level = RAW_WRITE_WRITEX;
687         wr.writex.in.file.fnum = fnum;
688         wr.writex.in.offset = 0;
689         wr.writex.in.wmode = 0;
690         wr.writex.in.remaining = 0;
691         wr.writex.in.count = 1;
692         wr.writex.in.data = &c;
693
694         status = smb_raw_write(cli->tree, &wr);
695         CHECK_STATUS(status, NT_STATUS_OK);
696         CHECK_VALUE(wr.writex.out.nwritten, 1);
697
698         printf("exit the pid with vuid2\n");
699         cli->session->vuid = vuid2;
700         status = smb_raw_exit(cli->session);
701         CHECK_STATUS(status, NT_STATUS_OK);
702
703         printf("the fnum should still be accessible\n");
704         cli->session->vuid = vuid1;
705         status = smb_raw_write(cli->tree, &wr);
706         CHECK_STATUS(status, NT_STATUS_OK);
707         CHECK_VALUE(wr.writex.out.nwritten, 1);
708
709         printf("exit the pid with vuid1\n");
710         cli->session->vuid = vuid1;
711         status = smb_raw_exit(cli->session);
712         CHECK_STATUS(status, NT_STATUS_OK);
713
714         printf("the fnum should not now be accessible\n");
715         status = smb_raw_write(cli->tree, &wr);
716         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
717
718         printf("the fnum should have been auto-closed\n");
719         cl.close.level = RAW_CLOSE_CLOSE;
720         cl.close.in.file.fnum = fnum;
721         cl.close.in.write_time = 0;
722         status = smb_raw_close(cli->tree, &cl);
723         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
724
725 done:
726         return ret;
727 }
728
729 /*
730   test pid ops with 2 tcons
731 */
732 static BOOL test_pid_2tcon(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
733 {
734         NTSTATUS status;
735         BOOL ret = True;
736         const char *share, *host;
737         struct smbcli_tree *tree;
738         union smb_tcon tcon;
739         union smb_open io;
740         union smb_write wr;
741         union smb_close cl;
742         int fnum1, fnum2;
743         const char *fname1 = BASEDIR "\\test1.txt";
744         const char *fname2 = BASEDIR "\\test2.txt";
745         uint8_t c = 1;
746         uint16_t tid1, tid2;
747
748         printf("TESTING PID HANDLING WITH 2 TCONS\n");
749
750         if (!torture_setup_dir(cli, BASEDIR)) {
751                 return False;
752         }
753
754         share = lp_parm_string(-1, "torture", "share");
755         host  = lp_parm_string(-1, "torture", "host");
756         
757         printf("create a second tree context on the same session\n");
758         tree = smbcli_tree_init(cli->session, mem_ctx, False);
759
760         tcon.generic.level = RAW_TCON_TCONX;
761         tcon.tconx.in.flags = 0;
762         tcon.tconx.in.password = data_blob(NULL, 0);
763         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
764         tcon.tconx.in.device = "A:";    
765         status = smb_raw_tcon(tree, mem_ctx, &tcon);
766         CHECK_STATUS(status, NT_STATUS_OK);     
767
768         tree->tid = tcon.tconx.out.tid;
769
770         tid1 = cli->tree->tid;
771         tid2 = tree->tid;
772         printf("tid1=%d tid2=%d\n", tid1, tid2);
773
774         printf("create a file using the tid1\n");
775         cli->tree->tid = tid1;
776         io.generic.level = RAW_OPEN_NTCREATEX;
777         io.ntcreatex.in.root_fid = 0;
778         io.ntcreatex.in.flags = 0;
779         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
780         io.ntcreatex.in.create_options = 0;
781         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
782         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
783         io.ntcreatex.in.alloc_size = 0;
784         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
785         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
786         io.ntcreatex.in.security_flags = 0;
787         io.ntcreatex.in.fname = fname1;
788         status = smb_raw_open(cli->tree, mem_ctx, &io);
789         CHECK_STATUS(status, NT_STATUS_OK);
790         fnum1 = io.ntcreatex.out.file.fnum;
791
792         printf("write using the tid1\n");
793         wr.generic.level = RAW_WRITE_WRITEX;
794         wr.writex.in.file.fnum = fnum1;
795         wr.writex.in.offset = 0;
796         wr.writex.in.wmode = 0;
797         wr.writex.in.remaining = 0;
798         wr.writex.in.count = 1;
799         wr.writex.in.data = &c;
800
801         status = smb_raw_write(cli->tree, &wr);
802         CHECK_STATUS(status, NT_STATUS_OK);
803         CHECK_VALUE(wr.writex.out.nwritten, 1);
804
805         printf("create a file using the tid2\n");
806         cli->tree->tid = tid2;
807         io.generic.level = RAW_OPEN_NTCREATEX;
808         io.ntcreatex.in.root_fid = 0;
809         io.ntcreatex.in.flags = 0;
810         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
811         io.ntcreatex.in.create_options = 0;
812         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
813         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
814         io.ntcreatex.in.alloc_size = 0;
815         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
816         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
817         io.ntcreatex.in.security_flags = 0;
818         io.ntcreatex.in.fname = fname2;
819         status = smb_raw_open(cli->tree, mem_ctx, &io);
820         CHECK_STATUS(status, NT_STATUS_OK);
821         fnum2 = io.ntcreatex.out.file.fnum;
822
823         printf("write using the tid2\n");
824         wr.generic.level = RAW_WRITE_WRITEX;
825         wr.writex.in.file.fnum = fnum2;
826         wr.writex.in.offset = 0;
827         wr.writex.in.wmode = 0;
828         wr.writex.in.remaining = 0;
829         wr.writex.in.count = 1;
830         wr.writex.in.data = &c;
831
832         status = smb_raw_write(cli->tree, &wr);
833         CHECK_STATUS(status, NT_STATUS_OK);
834         CHECK_VALUE(wr.writex.out.nwritten, 1);
835
836         printf("exit the pid\n");
837         status = smb_raw_exit(cli->session);
838         CHECK_STATUS(status, NT_STATUS_OK);
839
840         printf("the fnum1 on tid1 should not be accessible\n");
841         cli->tree->tid = tid1;
842         wr.writex.in.file.fnum = fnum1;
843         status = smb_raw_write(cli->tree, &wr);
844         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
845
846         printf("the fnum1 on tid1 should have been auto-closed\n");
847         cl.close.level = RAW_CLOSE_CLOSE;
848         cl.close.in.file.fnum = fnum1;
849         cl.close.in.write_time = 0;
850         status = smb_raw_close(cli->tree, &cl);
851         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
852
853         printf("the fnum2 on tid2 should not be accessible\n");
854         cli->tree->tid = tid2;
855         wr.writex.in.file.fnum = fnum2;
856         status = smb_raw_write(cli->tree, &wr);
857         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
858
859         printf("the fnum2 on tid2 should have been auto-closed\n");
860         cl.close.level = RAW_CLOSE_CLOSE;
861         cl.close.in.file.fnum = fnum2;
862         cl.close.in.write_time = 0;
863         status = smb_raw_close(cli->tree, &cl);
864         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
865
866 done:
867         return ret;
868 }
869
870
871 /* 
872    basic testing of session/tree context calls
873 */
874 static BOOL torture_raw_context_int(void)
875 {
876         struct smbcli_state *cli;
877         BOOL ret = True;
878         TALLOC_CTX *mem_ctx;
879
880         if (!torture_open_connection(&cli)) {
881                 return False;
882         }
883
884         mem_ctx = talloc_init("torture_raw_context");
885
886         ret &= test_session(cli, mem_ctx);
887         ret &= test_tree(cli, mem_ctx);
888         ret &= test_tree_ulogoff(cli, mem_ctx);
889         ret &= test_pid_exit_only_sees_open(cli, mem_ctx);
890         ret &= test_pid_2sess(cli, mem_ctx);
891         ret &= test_pid_2tcon(cli, mem_ctx);
892
893         smb_raw_exit(cli->session);
894         smbcli_deltree(cli->tree, BASEDIR);
895
896         torture_close_connection(cli);
897         talloc_free(mem_ctx);
898
899         return ret;
900 }
901 /* 
902    basic testing of session/tree context calls
903 */
904 BOOL torture_raw_context(struct torture_context *torture)
905 {
906         BOOL ret = True;
907         if (lp_use_spnego()) {
908                 ret &= torture_raw_context_int();
909                 lp_set_cmdline("use spnego", "False");
910         }
911
912         ret &= torture_raw_context_int();
913
914         return ret;
915 }