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