r25026: Move param/param.h out of includes.h
[jelmer/samba4-debian.git] / source / 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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/composite/composite.h"
24 #include "libcli/smb_composite/smb_composite.h"
25 #include "lib/cmdline/popt_common.h"
26 #include "lib/events/events.h"
27 #include "libcli/libcli.h"
28 #include "torture/util.h"
29 #include "auth/credentials/credentials.h"
30 #include "param/param.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         printf("finishing %d secondary security contexts on the same transport\n", 
239                (int)ARRAY_SIZE(sessions));
240         for (i=0; i< ARRAY_SIZE(sessions); i++) {
241                 status = smb_composite_sesssetup_recv(composite_contexts[i]);
242                 CHECK_STATUS(status, NT_STATUS_OK);
243                 sessions[i]->vuid = setups[i].out.vuid;
244                 printf("VUID: %d\n", sessions[i]->vuid);
245                 status = smb_raw_ulogoff(sessions[i]);
246                 CHECK_STATUS(status, NT_STATUS_OK);
247         }
248
249
250         talloc_free(tree);
251         
252 done:
253         return ret;
254 }
255
256
257 /*
258   test tree ops
259 */
260 static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
261 {
262         NTSTATUS status;
263         BOOL ret = True;
264         const char *share, *host;
265         struct smbcli_tree *tree;
266         union smb_tcon tcon;
267         union smb_open io;
268         union smb_write wr;
269         union smb_close cl;
270         int fnum;
271         const char *fname = BASEDIR "\\test.txt";
272         uint8_t c = 1;
273
274         printf("TESTING TREE HANDLING\n");
275
276         if (!torture_setup_dir(cli, BASEDIR)) {
277                 return False;
278         }
279
280         share = lp_parm_string(-1, "torture", "share");
281         host  = lp_parm_string(-1, "torture", "host");
282         
283         printf("create a second tree context on the same session\n");
284         tree = smbcli_tree_init(cli->session, mem_ctx, False);
285
286         tcon.generic.level = RAW_TCON_TCONX;
287         tcon.tconx.in.flags = 0;
288         tcon.tconx.in.password = data_blob(NULL, 0);
289         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
290         tcon.tconx.in.device = "A:";    
291         status = smb_raw_tcon(tree, mem_ctx, &tcon);
292         CHECK_STATUS(status, NT_STATUS_OK);
293         
294
295         tree->tid = tcon.tconx.out.tid;
296         printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
297
298         printf("try a tconx with a bad device type\n");
299         tcon.tconx.in.device = "FOO";   
300         status = smb_raw_tcon(tree, mem_ctx, &tcon);
301         CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
302
303
304         printf("create a file using the new tid\n");
305         io.generic.level = RAW_OPEN_NTCREATEX;
306         io.ntcreatex.in.root_fid = 0;
307         io.ntcreatex.in.flags = 0;
308         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
309         io.ntcreatex.in.create_options = 0;
310         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
311         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
312         io.ntcreatex.in.alloc_size = 0;
313         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
314         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
315         io.ntcreatex.in.security_flags = 0;
316         io.ntcreatex.in.fname = fname;
317         status = smb_raw_open(tree, mem_ctx, &io);
318         CHECK_STATUS(status, NT_STATUS_OK);
319         fnum = io.ntcreatex.out.file.fnum;
320
321         printf("write using the old tid\n");
322         wr.generic.level = RAW_WRITE_WRITEX;
323         wr.writex.in.file.fnum = fnum;
324         wr.writex.in.offset = 0;
325         wr.writex.in.wmode = 0;
326         wr.writex.in.remaining = 0;
327         wr.writex.in.count = 1;
328         wr.writex.in.data = &c;
329
330         status = smb_raw_write(cli->tree, &wr);
331         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
332
333         printf("write with the new tid\n");
334         status = smb_raw_write(tree, &wr);
335         CHECK_STATUS(status, NT_STATUS_OK);
336         CHECK_VALUE(wr.writex.out.nwritten, 1);
337
338         printf("disconnect the new tid\n");
339         status = smb_tree_disconnect(tree);
340         CHECK_STATUS(status, NT_STATUS_OK);
341
342         printf("the new tid should not now be accessible\n");
343         status = smb_raw_write(tree, &wr);
344         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
345
346         printf("the fnum should have been auto-closed\n");
347         cl.close.level = RAW_CLOSE_CLOSE;
348         cl.close.in.file.fnum = fnum;
349         cl.close.in.write_time = 0;
350         status = smb_raw_close(cli->tree, &cl);
351         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
352
353         /* close down the new tree */
354         talloc_free(tree);
355         
356 done:
357         return ret;
358 }
359
360 /*
361   test tree with ulogoff
362   this demonstrates that a tcon isn't autoclosed by a ulogoff
363   the tcon can be reused using any other valid session later
364 */
365 static BOOL test_tree_ulogoff(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
366 {
367         NTSTATUS status;
368         BOOL ret = True;
369         const char *share, *host;
370         struct smbcli_session *session1;
371         struct smbcli_session *session2;
372         struct smb_composite_sesssetup setup;
373         struct smbcli_tree *tree;
374         union smb_tcon tcon;
375         union smb_open io;
376         union smb_write wr;
377         int fnum1, fnum2;
378         const char *fname1 = BASEDIR "\\test1.txt";
379         const char *fname2 = BASEDIR "\\test2.txt";
380         uint8_t c = 1;
381
382         printf("TESTING TREE with ulogoff\n");
383
384         if (!torture_setup_dir(cli, BASEDIR)) {
385                 return False;
386         }
387
388         share = lp_parm_string(-1, "torture", "share");
389         host  = lp_parm_string(-1, "torture", "host");
390
391         printf("create the first new sessions\n");
392         session1 = smbcli_session_init(cli->transport, mem_ctx, False);
393         setup.in.sesskey = cli->transport->negotiate.sesskey;
394         setup.in.capabilities = cli->transport->negotiate.capabilities;
395         setup.in.workgroup = lp_workgroup();
396         setup.in.credentials = cmdline_credentials;
397         status = smb_composite_sesssetup(session1, &setup);
398         CHECK_STATUS(status, NT_STATUS_OK);
399         session1->vuid = setup.out.vuid;
400         printf("vuid1=%d\n", session1->vuid);
401
402         printf("create a tree context on the with vuid1\n");
403         tree = smbcli_tree_init(session1, mem_ctx, False);
404         tcon.generic.level = RAW_TCON_TCONX;
405         tcon.tconx.in.flags = 0;
406         tcon.tconx.in.password = data_blob(NULL, 0);
407         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
408         tcon.tconx.in.device = "A:";
409         status = smb_raw_tcon(tree, mem_ctx, &tcon);
410         CHECK_STATUS(status, NT_STATUS_OK);
411         tree->tid = tcon.tconx.out.tid;
412         printf("tid=%d\n", tree->tid);
413
414         printf("create a file using vuid1\n");
415         io.generic.level = RAW_OPEN_NTCREATEX;
416         io.ntcreatex.in.root_fid = 0;
417         io.ntcreatex.in.flags = 0;
418         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
419         io.ntcreatex.in.create_options = 0;
420         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
421         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
422         io.ntcreatex.in.alloc_size = 0;
423         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
424         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
425         io.ntcreatex.in.security_flags = 0;
426         io.ntcreatex.in.fname = fname1;
427         status = smb_raw_open(tree, mem_ctx, &io);
428         CHECK_STATUS(status, NT_STATUS_OK);
429         fnum1 = io.ntcreatex.out.file.fnum;
430
431         printf("write using vuid1\n");
432         wr.generic.level = RAW_WRITE_WRITEX;
433         wr.writex.in.file.fnum = fnum1;
434         wr.writex.in.offset = 0;
435         wr.writex.in.wmode = 0;
436         wr.writex.in.remaining = 0;
437         wr.writex.in.count = 1;
438         wr.writex.in.data = &c;
439         status = smb_raw_write(tree, &wr);
440         CHECK_STATUS(status, NT_STATUS_OK);
441         CHECK_VALUE(wr.writex.out.nwritten, 1);
442
443         printf("ulogoff the vuid1\n");
444         status = smb_raw_ulogoff(session1);
445         CHECK_STATUS(status, NT_STATUS_OK);
446
447         printf("create the second new sessions\n");
448         session2 = smbcli_session_init(cli->transport, mem_ctx, False);
449         setup.in.sesskey = cli->transport->negotiate.sesskey;
450         setup.in.capabilities = cli->transport->negotiate.capabilities;
451         setup.in.workgroup = lp_workgroup();
452         setup.in.credentials = cmdline_credentials;
453         status = smb_composite_sesssetup(session2, &setup);
454         CHECK_STATUS(status, NT_STATUS_OK);
455         session2->vuid = setup.out.vuid;
456         printf("vuid2=%d\n", session2->vuid);
457
458         printf("use the existing tree with vuid2\n");
459         tree->session = session2;
460
461         printf("create a file using vuid2\n");
462         io.generic.level = RAW_OPEN_NTCREATEX;
463         io.ntcreatex.in.root_fid = 0;
464         io.ntcreatex.in.flags = 0;
465         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
466         io.ntcreatex.in.create_options = 0;
467         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
468         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
469         io.ntcreatex.in.alloc_size = 0;
470         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
471         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
472         io.ntcreatex.in.security_flags = 0;
473         io.ntcreatex.in.fname = fname2;
474         status = smb_raw_open(tree, mem_ctx, &io);
475         CHECK_STATUS(status, NT_STATUS_OK);
476         fnum2 = io.ntcreatex.out.file.fnum;
477
478         printf("write using vuid2\n");
479         wr.generic.level = RAW_WRITE_WRITEX;
480         wr.writex.in.file.fnum = fnum2;
481         wr.writex.in.offset = 0;
482         wr.writex.in.wmode = 0;
483         wr.writex.in.remaining = 0;
484         wr.writex.in.count = 1;
485         wr.writex.in.data = &c;
486         status = smb_raw_write(tree, &wr);
487         CHECK_STATUS(status, NT_STATUS_OK);
488         CHECK_VALUE(wr.writex.out.nwritten, 1);
489
490         printf("ulogoff the vuid2\n");
491         status = smb_raw_ulogoff(session2);
492         CHECK_STATUS(status, NT_STATUS_OK);
493
494         /* this also demonstrates that SMBtdis doesn't need a valid vuid */
495         printf("disconnect the existing tree connection\n");
496         status = smb_tree_disconnect(tree);
497         CHECK_STATUS(status, NT_STATUS_OK);
498
499         printf("disconnect the existing tree connection\n");
500         status = smb_tree_disconnect(tree);
501         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
502
503         /* close down the new tree */
504         talloc_free(tree);
505         
506 done:
507         return ret;
508 }
509
510 /*
511   test pid ops
512   this test demonstrates that exit() only sees the PID
513   used for the open() calls
514 */
515 static BOOL test_pid_exit_only_sees_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
516 {
517         NTSTATUS status;
518         BOOL ret = True;
519         union smb_open io;
520         union smb_write wr;
521         union smb_close cl;
522         int fnum;
523         const char *fname = BASEDIR "\\test.txt";
524         uint8_t c = 1;
525         uint16_t pid1, pid2;
526
527         printf("TESTING PID HANDLING exit() only cares about open() PID\n");
528
529         if (!torture_setup_dir(cli, BASEDIR)) {
530                 return False;
531         }
532
533         pid1 = cli->session->pid;
534         pid2 = pid1 + 1;
535
536         printf("pid1=%d pid2=%d\n", pid1, pid2);
537
538         printf("create a file using pid1\n");
539         cli->session->pid = pid1;
540         io.generic.level = RAW_OPEN_NTCREATEX;
541         io.ntcreatex.in.root_fid = 0;
542         io.ntcreatex.in.flags = 0;
543         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
544         io.ntcreatex.in.create_options = 0;
545         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
546         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
547         io.ntcreatex.in.alloc_size = 0;
548         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
549         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
550         io.ntcreatex.in.security_flags = 0;
551         io.ntcreatex.in.fname = fname;
552         status = smb_raw_open(cli->tree, mem_ctx, &io);
553         CHECK_STATUS(status, NT_STATUS_OK);
554         fnum = io.ntcreatex.out.file.fnum;
555
556         printf("write using pid2\n");
557         cli->session->pid = pid2;
558         wr.generic.level = RAW_WRITE_WRITEX;
559         wr.writex.in.file.fnum = fnum;
560         wr.writex.in.offset = 0;
561         wr.writex.in.wmode = 0;
562         wr.writex.in.remaining = 0;
563         wr.writex.in.count = 1;
564         wr.writex.in.data = &c;
565         status = smb_raw_write(cli->tree, &wr);
566         CHECK_STATUS(status, NT_STATUS_OK);
567         CHECK_VALUE(wr.writex.out.nwritten, 1);
568
569         printf("exit pid2\n");
570         cli->session->pid = pid2;
571         status = smb_raw_exit(cli->session);
572         CHECK_STATUS(status, NT_STATUS_OK);
573
574         printf("the fnum should still be accessible via pid2\n");
575         cli->session->pid = pid2;
576         status = smb_raw_write(cli->tree, &wr);
577         CHECK_STATUS(status, NT_STATUS_OK);
578         CHECK_VALUE(wr.writex.out.nwritten, 1);
579
580         printf("exit pid2\n");
581         cli->session->pid = pid2;
582         status = smb_raw_exit(cli->session);
583         CHECK_STATUS(status, NT_STATUS_OK);
584
585         printf("the fnum should still be accessible via pid1 and pid2\n");
586         cli->session->pid = pid1;
587         status = smb_raw_write(cli->tree, &wr);
588         CHECK_STATUS(status, NT_STATUS_OK);
589         CHECK_VALUE(wr.writex.out.nwritten, 1);
590         cli->session->pid = pid2;
591         status = smb_raw_write(cli->tree, &wr);
592         CHECK_STATUS(status, NT_STATUS_OK);
593         CHECK_VALUE(wr.writex.out.nwritten, 1);
594
595         printf("exit pid1\n");
596         cli->session->pid = pid1;
597         status = smb_raw_exit(cli->session);
598         CHECK_STATUS(status, NT_STATUS_OK);
599
600         printf("the fnum should not now be accessible via pid1 or pid2\n");
601         cli->session->pid = pid1;
602         status = smb_raw_write(cli->tree, &wr);
603         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
604         cli->session->pid = pid2;
605         status = smb_raw_write(cli->tree, &wr);
606         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
607
608         printf("the fnum should have been auto-closed\n");
609         cli->session->pid = pid1;
610         cl.close.level = RAW_CLOSE_CLOSE;
611         cl.close.in.file.fnum = fnum;
612         cl.close.in.write_time = 0;
613         status = smb_raw_close(cli->tree, &cl);
614         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
615
616 done:
617         return ret;
618 }
619
620 /*
621   test pid ops with 2 sessions
622 */
623 static BOOL test_pid_2sess(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
624 {
625         NTSTATUS status;
626         BOOL ret = True;
627         struct smbcli_session *session;
628         struct smb_composite_sesssetup setup;
629         union smb_open io;
630         union smb_write wr;
631         union smb_close cl;
632         int fnum;
633         const char *fname = BASEDIR "\\test.txt";
634         uint8_t c = 1;
635         uint16_t vuid1, vuid2;
636
637         printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
638
639         if (!torture_setup_dir(cli, BASEDIR)) {
640                 return False;
641         }
642
643         printf("create a second security context on the same transport\n");
644         session = smbcli_session_init(cli->transport, mem_ctx, False);
645
646         setup.in.sesskey = cli->transport->negotiate.sesskey;
647         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
648         setup.in.workgroup = lp_workgroup();
649
650         setup.in.credentials = cmdline_credentials;
651
652         status = smb_composite_sesssetup(session, &setup);
653         CHECK_STATUS(status, NT_STATUS_OK);     
654         session->vuid = setup.out.vuid;
655
656         vuid1 = cli->session->vuid;
657         vuid2 = session->vuid;
658
659         printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
660
661         printf("create a file using the vuid1\n");
662         cli->session->vuid = vuid1;
663         io.generic.level = RAW_OPEN_NTCREATEX;
664         io.ntcreatex.in.root_fid = 0;
665         io.ntcreatex.in.flags = 0;
666         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
667         io.ntcreatex.in.create_options = 0;
668         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
669         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
670         io.ntcreatex.in.alloc_size = 0;
671         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
672         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
673         io.ntcreatex.in.security_flags = 0;
674         io.ntcreatex.in.fname = fname;
675         status = smb_raw_open(cli->tree, mem_ctx, &io);
676         CHECK_STATUS(status, NT_STATUS_OK);
677         fnum = io.ntcreatex.out.file.fnum;
678
679         printf("write using the vuid1 (fnum=%d)\n", fnum);
680         cli->session->vuid = vuid1;
681         wr.generic.level = RAW_WRITE_WRITEX;
682         wr.writex.in.file.fnum = fnum;
683         wr.writex.in.offset = 0;
684         wr.writex.in.wmode = 0;
685         wr.writex.in.remaining = 0;
686         wr.writex.in.count = 1;
687         wr.writex.in.data = &c;
688
689         status = smb_raw_write(cli->tree, &wr);
690         CHECK_STATUS(status, NT_STATUS_OK);
691         CHECK_VALUE(wr.writex.out.nwritten, 1);
692
693         printf("exit the pid with vuid2\n");
694         cli->session->vuid = vuid2;
695         status = smb_raw_exit(cli->session);
696         CHECK_STATUS(status, NT_STATUS_OK);
697
698         printf("the fnum should still be accessible\n");
699         cli->session->vuid = vuid1;
700         status = smb_raw_write(cli->tree, &wr);
701         CHECK_STATUS(status, NT_STATUS_OK);
702         CHECK_VALUE(wr.writex.out.nwritten, 1);
703
704         printf("exit the pid with vuid1\n");
705         cli->session->vuid = vuid1;
706         status = smb_raw_exit(cli->session);
707         CHECK_STATUS(status, NT_STATUS_OK);
708
709         printf("the fnum should not now be accessible\n");
710         status = smb_raw_write(cli->tree, &wr);
711         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
712
713         printf("the fnum should have been auto-closed\n");
714         cl.close.level = RAW_CLOSE_CLOSE;
715         cl.close.in.file.fnum = fnum;
716         cl.close.in.write_time = 0;
717         status = smb_raw_close(cli->tree, &cl);
718         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
719
720 done:
721         return ret;
722 }
723
724 /*
725   test pid ops with 2 tcons
726 */
727 static BOOL test_pid_2tcon(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
728 {
729         NTSTATUS status;
730         BOOL ret = True;
731         const char *share, *host;
732         struct smbcli_tree *tree;
733         union smb_tcon tcon;
734         union smb_open io;
735         union smb_write wr;
736         union smb_close cl;
737         int fnum1, fnum2;
738         const char *fname1 = BASEDIR "\\test1.txt";
739         const char *fname2 = BASEDIR "\\test2.txt";
740         uint8_t c = 1;
741         uint16_t tid1, tid2;
742
743         printf("TESTING PID HANDLING WITH 2 TCONS\n");
744
745         if (!torture_setup_dir(cli, BASEDIR)) {
746                 return False;
747         }
748
749         share = lp_parm_string(-1, "torture", "share");
750         host  = lp_parm_string(-1, "torture", "host");
751         
752         printf("create a second tree context on the same session\n");
753         tree = smbcli_tree_init(cli->session, mem_ctx, False);
754
755         tcon.generic.level = RAW_TCON_TCONX;
756         tcon.tconx.in.flags = 0;
757         tcon.tconx.in.password = data_blob(NULL, 0);
758         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
759         tcon.tconx.in.device = "A:";    
760         status = smb_raw_tcon(tree, mem_ctx, &tcon);
761         CHECK_STATUS(status, NT_STATUS_OK);     
762
763         tree->tid = tcon.tconx.out.tid;
764
765         tid1 = cli->tree->tid;
766         tid2 = tree->tid;
767         printf("tid1=%d tid2=%d\n", tid1, tid2);
768
769         printf("create a file using the tid1\n");
770         cli->tree->tid = tid1;
771         io.generic.level = RAW_OPEN_NTCREATEX;
772         io.ntcreatex.in.root_fid = 0;
773         io.ntcreatex.in.flags = 0;
774         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
775         io.ntcreatex.in.create_options = 0;
776         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
777         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
778         io.ntcreatex.in.alloc_size = 0;
779         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
780         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
781         io.ntcreatex.in.security_flags = 0;
782         io.ntcreatex.in.fname = fname1;
783         status = smb_raw_open(cli->tree, mem_ctx, &io);
784         CHECK_STATUS(status, NT_STATUS_OK);
785         fnum1 = io.ntcreatex.out.file.fnum;
786
787         printf("write using the tid1\n");
788         wr.generic.level = RAW_WRITE_WRITEX;
789         wr.writex.in.file.fnum = fnum1;
790         wr.writex.in.offset = 0;
791         wr.writex.in.wmode = 0;
792         wr.writex.in.remaining = 0;
793         wr.writex.in.count = 1;
794         wr.writex.in.data = &c;
795
796         status = smb_raw_write(cli->tree, &wr);
797         CHECK_STATUS(status, NT_STATUS_OK);
798         CHECK_VALUE(wr.writex.out.nwritten, 1);
799
800         printf("create a file using the tid2\n");
801         cli->tree->tid = tid2;
802         io.generic.level = RAW_OPEN_NTCREATEX;
803         io.ntcreatex.in.root_fid = 0;
804         io.ntcreatex.in.flags = 0;
805         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
806         io.ntcreatex.in.create_options = 0;
807         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
808         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
809         io.ntcreatex.in.alloc_size = 0;
810         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
811         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
812         io.ntcreatex.in.security_flags = 0;
813         io.ntcreatex.in.fname = fname2;
814         status = smb_raw_open(cli->tree, mem_ctx, &io);
815         CHECK_STATUS(status, NT_STATUS_OK);
816         fnum2 = io.ntcreatex.out.file.fnum;
817
818         printf("write using the tid2\n");
819         wr.generic.level = RAW_WRITE_WRITEX;
820         wr.writex.in.file.fnum = fnum2;
821         wr.writex.in.offset = 0;
822         wr.writex.in.wmode = 0;
823         wr.writex.in.remaining = 0;
824         wr.writex.in.count = 1;
825         wr.writex.in.data = &c;
826
827         status = smb_raw_write(cli->tree, &wr);
828         CHECK_STATUS(status, NT_STATUS_OK);
829         CHECK_VALUE(wr.writex.out.nwritten, 1);
830
831         printf("exit the pid\n");
832         status = smb_raw_exit(cli->session);
833         CHECK_STATUS(status, NT_STATUS_OK);
834
835         printf("the fnum1 on tid1 should not be accessible\n");
836         cli->tree->tid = tid1;
837         wr.writex.in.file.fnum = fnum1;
838         status = smb_raw_write(cli->tree, &wr);
839         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
840
841         printf("the fnum1 on tid1 should have been auto-closed\n");
842         cl.close.level = RAW_CLOSE_CLOSE;
843         cl.close.in.file.fnum = fnum1;
844         cl.close.in.write_time = 0;
845         status = smb_raw_close(cli->tree, &cl);
846         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
847
848         printf("the fnum2 on tid2 should not be accessible\n");
849         cli->tree->tid = tid2;
850         wr.writex.in.file.fnum = fnum2;
851         status = smb_raw_write(cli->tree, &wr);
852         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
853
854         printf("the fnum2 on tid2 should have been auto-closed\n");
855         cl.close.level = RAW_CLOSE_CLOSE;
856         cl.close.in.file.fnum = fnum2;
857         cl.close.in.write_time = 0;
858         status = smb_raw_close(cli->tree, &cl);
859         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
860
861 done:
862         return ret;
863 }
864
865
866 /* 
867    basic testing of session/tree context calls
868 */
869 static bool torture_raw_context_int(struct torture_context *tctx, 
870                                                                         struct smbcli_state *cli)
871 {
872         BOOL ret = True;
873
874         ret &= test_session(cli, tctx);
875         ret &= test_tree(cli, tctx);
876         ret &= test_tree_ulogoff(cli, tctx);
877         ret &= test_pid_exit_only_sees_open(cli, tctx);
878         ret &= test_pid_2sess(cli, tctx);
879         ret &= test_pid_2tcon(cli, tctx);
880
881         smb_raw_exit(cli->session);
882         smbcli_deltree(cli->tree, BASEDIR);
883
884         return ret;
885 }
886 /* 
887    basic testing of session/tree context calls
888 */
889 bool torture_raw_context(struct torture_context *torture, 
890                          struct smbcli_state *cli)
891 {
892         bool ret = true;
893         if (lp_use_spnego()) {
894                 ret &= torture_raw_context_int(torture, cli);
895                 lp_set_cmdline("use spnego", "False");
896         }
897
898         ret &= torture_raw_context_int(torture, cli);
899
900         return ret;
901 }