Merge branch 'master' of ssh://git.samba.org/data/git/samba
[kai/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         struct smbcli_session_options options;
85
86         printf("TESTING SESSION HANDLING\n");
87
88         if (!torture_setup_dir(cli, BASEDIR)) {
89                 return false;
90         }
91
92         printf("create a second security context on the same transport\n");
93
94         lp_smbcli_session_options(tctx->lp_ctx, &options);
95
96         session = smbcli_session_init(cli->transport, tctx, false, options);
97
98         setup.in.sesskey = cli->transport->negotiate.sesskey;
99         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
100         setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
101
102         setup.in.credentials = cmdline_credentials;
103
104         status = smb_composite_sesssetup(session, &setup);
105         CHECK_STATUS(status, NT_STATUS_OK);
106         
107         session->vuid = setup.out.vuid;
108
109         printf("create a third security context on the same transport, with vuid set\n");
110         session2 = smbcli_session_init(cli->transport, tctx, false, options);
111
112         session2->vuid = session->vuid;
113         setup.in.sesskey = cli->transport->negotiate.sesskey;
114         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
115         setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
116
117         setup.in.credentials = cmdline_credentials;
118
119         status = smb_composite_sesssetup(session2, &setup);
120         CHECK_STATUS(status, NT_STATUS_OK);
121
122         session2->vuid = setup.out.vuid;
123         printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
124         
125         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
126                 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
127                 if (session2->vuid == session->vuid) {
128                         printf("server allows the user to re-use an existing vuid in session setup \n");
129                 }
130         } else {
131                 CHECK_NOT_VALUE(session2->vuid, session->vuid);
132         }
133         talloc_free(session2);
134
135         if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
136                 printf("create a fourth security context on the same transport, without extended security\n");
137                 session3 = smbcli_session_init(cli->transport, tctx, false, options);
138
139                 session3->vuid = session->vuid;
140                 setup.in.sesskey = cli->transport->negotiate.sesskey;
141                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
142                 setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
143         
144                 setup.in.credentials = cmdline_credentials;
145         
146
147                 status = smb_composite_sesssetup(session3, &setup);
148                 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
149
150                 printf("create a fouth anonymous security context on the same transport, without extended security\n");
151                 session4 = smbcli_session_init(cli->transport, tctx, false, options);
152
153                 session4->vuid = session->vuid;
154                 setup.in.sesskey = cli->transport->negotiate.sesskey;
155                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
156                 setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
157                 
158                 anon_creds = cli_credentials_init(tctx);
159                 cli_credentials_set_conf(anon_creds, tctx->lp_ctx);
160                 cli_credentials_set_anonymous(anon_creds);
161
162                 setup.in.credentials = anon_creds;
163         
164                 status = smb_composite_sesssetup(session3, &setup);
165                 CHECK_STATUS(status, NT_STATUS_OK);
166
167                 talloc_free(session4);
168         }
169                 
170         printf("use the same tree as the existing connection\n");
171         tree = smbcli_tree_init(session, tctx, false);
172         tree->tid = cli->tree->tid;
173
174         printf("create a file using the new vuid\n");
175         io.generic.level = RAW_OPEN_NTCREATEX;
176         io.ntcreatex.in.root_fid = 0;
177         io.ntcreatex.in.flags = 0;
178         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
179         io.ntcreatex.in.create_options = 0;
180         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
181         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
182         io.ntcreatex.in.alloc_size = 0;
183         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
184         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
185         io.ntcreatex.in.security_flags = 0;
186         io.ntcreatex.in.fname = fname;
187         status = smb_raw_open(tree, tctx, &io);
188         CHECK_STATUS(status, NT_STATUS_OK);
189         fnum = io.ntcreatex.out.file.fnum;
190
191         printf("write using the old vuid\n");
192         wr.generic.level = RAW_WRITE_WRITEX;
193         wr.writex.in.file.fnum = fnum;
194         wr.writex.in.offset = 0;
195         wr.writex.in.wmode = 0;
196         wr.writex.in.remaining = 0;
197         wr.writex.in.count = 1;
198         wr.writex.in.data = &c;
199
200         status = smb_raw_write(cli->tree, &wr);
201         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
202
203         printf("write with the new vuid\n");
204         status = smb_raw_write(tree, &wr);
205         CHECK_STATUS(status, NT_STATUS_OK);
206         CHECK_VALUE(wr.writex.out.nwritten, 1);
207
208         printf("logoff the new vuid\n");
209         status = smb_raw_ulogoff(session);
210         CHECK_STATUS(status, NT_STATUS_OK);
211
212         printf("the new vuid should not now be accessible\n");
213         status = smb_raw_write(tree, &wr);
214         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
215
216         printf("second logoff for the new vuid should fail\n");
217         status = smb_raw_ulogoff(session);
218         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
219         talloc_free(session);
220
221         printf("the fnum should have been auto-closed\n");
222         cl.close.level = RAW_CLOSE_CLOSE;
223         cl.close.in.file.fnum = fnum;
224         cl.close.in.write_time = 0;
225         status = smb_raw_close(cli->tree, &cl);
226         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
227
228         printf("create %d secondary security contexts on the same transport\n", 
229                (int)ARRAY_SIZE(sessions));
230         for (i=0; i <ARRAY_SIZE(sessions); i++) {
231                 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
232                 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
233                 setups[i].in.workgroup = lp_workgroup(tctx->lp_ctx);
234                 
235                 setups[i].in.credentials = cmdline_credentials;
236
237                 sessions[i] = smbcli_session_init(cli->transport, tctx, false, options);
238                 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
239
240         }
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, struct torture_context *tctx)
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 = torture_setting_string(tctx, "share", NULL);
286         host  = torture_setting_string(tctx, "host", NULL);
287         
288         printf("create a second tree context on the same session\n");
289         tree = smbcli_tree_init(cli->session, tctx, 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(tctx, "\\\\%s\\%s", host, share);
295         tcon.tconx.in.device = "A:";    
296         status = smb_raw_tcon(tree, tctx, &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, tctx, &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, tctx, &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, struct torture_context *tctx)
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         struct smbcli_session_options options;
387
388         printf("TESTING TREE with ulogoff\n");
389
390         if (!torture_setup_dir(cli, BASEDIR)) {
391                 return false;
392         }
393
394         share = torture_setting_string(tctx, "share", NULL);
395         host  = torture_setting_string(tctx, "host", NULL);
396
397         lp_smbcli_session_options(tctx->lp_ctx, &options);
398
399         printf("create the first new sessions\n");
400         session1 = smbcli_session_init(cli->transport, tctx, false, options);
401         setup.in.sesskey = cli->transport->negotiate.sesskey;
402         setup.in.capabilities = cli->transport->negotiate.capabilities;
403         setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
404         setup.in.credentials = cmdline_credentials;
405         status = smb_composite_sesssetup(session1, &setup);
406         CHECK_STATUS(status, NT_STATUS_OK);
407         session1->vuid = setup.out.vuid;
408         printf("vuid1=%d\n", session1->vuid);
409
410         printf("create a tree context on the with vuid1\n");
411         tree = smbcli_tree_init(session1, tctx, false);
412         tcon.generic.level = RAW_TCON_TCONX;
413         tcon.tconx.in.flags = 0;
414         tcon.tconx.in.password = data_blob(NULL, 0);
415         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
416         tcon.tconx.in.device = "A:";
417         status = smb_raw_tcon(tree, tctx, &tcon);
418         CHECK_STATUS(status, NT_STATUS_OK);
419         tree->tid = tcon.tconx.out.tid;
420         printf("tid=%d\n", tree->tid);
421
422         printf("create a file using vuid1\n");
423         io.generic.level = RAW_OPEN_NTCREATEX;
424         io.ntcreatex.in.root_fid = 0;
425         io.ntcreatex.in.flags = 0;
426         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
427         io.ntcreatex.in.create_options = 0;
428         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
429         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
430         io.ntcreatex.in.alloc_size = 0;
431         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
432         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
433         io.ntcreatex.in.security_flags = 0;
434         io.ntcreatex.in.fname = fname1;
435         status = smb_raw_open(tree, tctx, &io);
436         CHECK_STATUS(status, NT_STATUS_OK);
437         fnum1 = io.ntcreatex.out.file.fnum;
438
439         printf("write using vuid1\n");
440         wr.generic.level = RAW_WRITE_WRITEX;
441         wr.writex.in.file.fnum = fnum1;
442         wr.writex.in.offset = 0;
443         wr.writex.in.wmode = 0;
444         wr.writex.in.remaining = 0;
445         wr.writex.in.count = 1;
446         wr.writex.in.data = &c;
447         status = smb_raw_write(tree, &wr);
448         CHECK_STATUS(status, NT_STATUS_OK);
449         CHECK_VALUE(wr.writex.out.nwritten, 1);
450
451         printf("ulogoff the vuid1\n");
452         status = smb_raw_ulogoff(session1);
453         CHECK_STATUS(status, NT_STATUS_OK);
454
455         printf("create the second new sessions\n");
456         session2 = smbcli_session_init(cli->transport, tctx, false, options);
457         setup.in.sesskey = cli->transport->negotiate.sesskey;
458         setup.in.capabilities = cli->transport->negotiate.capabilities;
459         setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
460         setup.in.credentials = cmdline_credentials;
461         status = smb_composite_sesssetup(session2, &setup);
462         CHECK_STATUS(status, NT_STATUS_OK);
463         session2->vuid = setup.out.vuid;
464         printf("vuid2=%d\n", session2->vuid);
465
466         printf("use the existing tree with vuid2\n");
467         tree->session = session2;
468
469         printf("create a file using vuid2\n");
470         io.generic.level = RAW_OPEN_NTCREATEX;
471         io.ntcreatex.in.root_fid = 0;
472         io.ntcreatex.in.flags = 0;
473         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
474         io.ntcreatex.in.create_options = 0;
475         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
476         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
477         io.ntcreatex.in.alloc_size = 0;
478         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
479         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
480         io.ntcreatex.in.security_flags = 0;
481         io.ntcreatex.in.fname = fname2;
482         status = smb_raw_open(tree, tctx, &io);
483         CHECK_STATUS(status, NT_STATUS_OK);
484         fnum2 = io.ntcreatex.out.file.fnum;
485
486         printf("write using vuid2\n");
487         wr.generic.level = RAW_WRITE_WRITEX;
488         wr.writex.in.file.fnum = fnum2;
489         wr.writex.in.offset = 0;
490         wr.writex.in.wmode = 0;
491         wr.writex.in.remaining = 0;
492         wr.writex.in.count = 1;
493         wr.writex.in.data = &c;
494         status = smb_raw_write(tree, &wr);
495         CHECK_STATUS(status, NT_STATUS_OK);
496         CHECK_VALUE(wr.writex.out.nwritten, 1);
497
498         printf("ulogoff the vuid2\n");
499         status = smb_raw_ulogoff(session2);
500         CHECK_STATUS(status, NT_STATUS_OK);
501
502         /* this also demonstrates that SMBtdis doesn't need a valid vuid */
503         printf("disconnect the existing tree connection\n");
504         status = smb_tree_disconnect(tree);
505         CHECK_STATUS(status, NT_STATUS_OK);
506
507         printf("disconnect the existing tree connection\n");
508         status = smb_tree_disconnect(tree);
509         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
510
511         /* close down the new tree */
512         talloc_free(tree);
513         
514 done:
515         return ret;
516 }
517
518 /*
519   test pid ops
520   this test demonstrates that exit() only sees the PID
521   used for the open() calls
522 */
523 static bool test_pid_exit_only_sees_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
524 {
525         NTSTATUS status;
526         bool ret = true;
527         union smb_open io;
528         union smb_write wr;
529         union smb_close cl;
530         int fnum;
531         const char *fname = BASEDIR "\\test.txt";
532         uint8_t c = 1;
533         uint16_t pid1, pid2;
534
535         printf("TESTING PID HANDLING exit() only cares about open() PID\n");
536
537         if (!torture_setup_dir(cli, BASEDIR)) {
538                 return false;
539         }
540
541         pid1 = cli->session->pid;
542         pid2 = pid1 + 1;
543
544         printf("pid1=%d pid2=%d\n", pid1, pid2);
545
546         printf("create a file using pid1\n");
547         cli->session->pid = pid1;
548         io.generic.level = RAW_OPEN_NTCREATEX;
549         io.ntcreatex.in.root_fid = 0;
550         io.ntcreatex.in.flags = 0;
551         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
552         io.ntcreatex.in.create_options = 0;
553         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
554         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
555         io.ntcreatex.in.alloc_size = 0;
556         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
557         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
558         io.ntcreatex.in.security_flags = 0;
559         io.ntcreatex.in.fname = fname;
560         status = smb_raw_open(cli->tree, mem_ctx, &io);
561         CHECK_STATUS(status, NT_STATUS_OK);
562         fnum = io.ntcreatex.out.file.fnum;
563
564         printf("write using pid2\n");
565         cli->session->pid = pid2;
566         wr.generic.level = RAW_WRITE_WRITEX;
567         wr.writex.in.file.fnum = fnum;
568         wr.writex.in.offset = 0;
569         wr.writex.in.wmode = 0;
570         wr.writex.in.remaining = 0;
571         wr.writex.in.count = 1;
572         wr.writex.in.data = &c;
573         status = smb_raw_write(cli->tree, &wr);
574         CHECK_STATUS(status, NT_STATUS_OK);
575         CHECK_VALUE(wr.writex.out.nwritten, 1);
576
577         printf("exit pid2\n");
578         cli->session->pid = pid2;
579         status = smb_raw_exit(cli->session);
580         CHECK_STATUS(status, NT_STATUS_OK);
581
582         printf("the fnum should still be accessible via pid2\n");
583         cli->session->pid = pid2;
584         status = smb_raw_write(cli->tree, &wr);
585         CHECK_STATUS(status, NT_STATUS_OK);
586         CHECK_VALUE(wr.writex.out.nwritten, 1);
587
588         printf("exit pid2\n");
589         cli->session->pid = pid2;
590         status = smb_raw_exit(cli->session);
591         CHECK_STATUS(status, NT_STATUS_OK);
592
593         printf("the fnum should still be accessible via pid1 and pid2\n");
594         cli->session->pid = pid1;
595         status = smb_raw_write(cli->tree, &wr);
596         CHECK_STATUS(status, NT_STATUS_OK);
597         CHECK_VALUE(wr.writex.out.nwritten, 1);
598         cli->session->pid = pid2;
599         status = smb_raw_write(cli->tree, &wr);
600         CHECK_STATUS(status, NT_STATUS_OK);
601         CHECK_VALUE(wr.writex.out.nwritten, 1);
602
603         printf("exit pid1\n");
604         cli->session->pid = pid1;
605         status = smb_raw_exit(cli->session);
606         CHECK_STATUS(status, NT_STATUS_OK);
607
608         printf("the fnum should not now be accessible via pid1 or pid2\n");
609         cli->session->pid = pid1;
610         status = smb_raw_write(cli->tree, &wr);
611         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
612         cli->session->pid = pid2;
613         status = smb_raw_write(cli->tree, &wr);
614         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
615
616         printf("the fnum should have been auto-closed\n");
617         cli->session->pid = pid1;
618         cl.close.level = RAW_CLOSE_CLOSE;
619         cl.close.in.file.fnum = fnum;
620         cl.close.in.write_time = 0;
621         status = smb_raw_close(cli->tree, &cl);
622         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
623
624 done:
625         return ret;
626 }
627
628 /*
629   test pid ops with 2 sessions
630 */
631 static bool test_pid_2sess(struct smbcli_state *cli, struct torture_context *tctx)
632 {
633         NTSTATUS status;
634         bool ret = true;
635         struct smbcli_session *session;
636         struct smb_composite_sesssetup setup;
637         union smb_open io;
638         union smb_write wr;
639         union smb_close cl;
640         int fnum;
641         const char *fname = BASEDIR "\\test.txt";
642         uint8_t c = 1;
643         uint16_t vuid1, vuid2;
644         struct smbcli_session_options options;
645
646         printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
647
648         if (!torture_setup_dir(cli, BASEDIR)) {
649                 return false;
650         }
651
652         lp_smbcli_session_options(tctx->lp_ctx, &options);
653
654         printf("create a second security context on the same transport\n");
655         session = smbcli_session_init(cli->transport, tctx, false, options);
656
657         setup.in.sesskey = cli->transport->negotiate.sesskey;
658         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
659         setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
660
661         setup.in.credentials = cmdline_credentials;
662
663         status = smb_composite_sesssetup(session, &setup);
664         CHECK_STATUS(status, NT_STATUS_OK);     
665         session->vuid = setup.out.vuid;
666
667         vuid1 = cli->session->vuid;
668         vuid2 = session->vuid;
669
670         printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
671
672         printf("create a file using the vuid1\n");
673         cli->session->vuid = vuid1;
674         io.generic.level = RAW_OPEN_NTCREATEX;
675         io.ntcreatex.in.root_fid = 0;
676         io.ntcreatex.in.flags = 0;
677         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
678         io.ntcreatex.in.create_options = 0;
679         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
680         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
681         io.ntcreatex.in.alloc_size = 0;
682         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
683         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
684         io.ntcreatex.in.security_flags = 0;
685         io.ntcreatex.in.fname = fname;
686         status = smb_raw_open(cli->tree, tctx, &io);
687         CHECK_STATUS(status, NT_STATUS_OK);
688         fnum = io.ntcreatex.out.file.fnum;
689
690         printf("write using the vuid1 (fnum=%d)\n", fnum);
691         cli->session->vuid = vuid1;
692         wr.generic.level = RAW_WRITE_WRITEX;
693         wr.writex.in.file.fnum = fnum;
694         wr.writex.in.offset = 0;
695         wr.writex.in.wmode = 0;
696         wr.writex.in.remaining = 0;
697         wr.writex.in.count = 1;
698         wr.writex.in.data = &c;
699
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 vuid2\n");
705         cli->session->vuid = vuid2;
706         status = smb_raw_exit(cli->session);
707         CHECK_STATUS(status, NT_STATUS_OK);
708
709         printf("the fnum should still be accessible\n");
710         cli->session->vuid = vuid1;
711         status = smb_raw_write(cli->tree, &wr);
712         CHECK_STATUS(status, NT_STATUS_OK);
713         CHECK_VALUE(wr.writex.out.nwritten, 1);
714
715         printf("exit the pid with vuid1\n");
716         cli->session->vuid = vuid1;
717         status = smb_raw_exit(cli->session);
718         CHECK_STATUS(status, NT_STATUS_OK);
719
720         printf("the fnum should not now be accessible\n");
721         status = smb_raw_write(cli->tree, &wr);
722         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
723
724         printf("the fnum should have been auto-closed\n");
725         cl.close.level = RAW_CLOSE_CLOSE;
726         cl.close.in.file.fnum = fnum;
727         cl.close.in.write_time = 0;
728         status = smb_raw_close(cli->tree, &cl);
729         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
730
731 done:
732         return ret;
733 }
734
735 /*
736   test pid ops with 2 tcons
737 */
738 static bool test_pid_2tcon(struct smbcli_state *cli, struct torture_context *tctx)
739 {
740         NTSTATUS status;
741         bool ret = true;
742         const char *share, *host;
743         struct smbcli_tree *tree;
744         union smb_tcon tcon;
745         union smb_open io;
746         union smb_write wr;
747         union smb_close cl;
748         int fnum1, fnum2;
749         const char *fname1 = BASEDIR "\\test1.txt";
750         const char *fname2 = BASEDIR "\\test2.txt";
751         uint8_t c = 1;
752         uint16_t tid1, tid2;
753
754         printf("TESTING PID HANDLING WITH 2 TCONS\n");
755
756         if (!torture_setup_dir(cli, BASEDIR)) {
757                 return false;
758         }
759
760         share = torture_setting_string(tctx, "share", NULL);
761         host  = torture_setting_string(tctx, "host", NULL);
762         
763         printf("create a second tree context on the same session\n");
764         tree = smbcli_tree_init(cli->session, tctx, false);
765
766         tcon.generic.level = RAW_TCON_TCONX;
767         tcon.tconx.in.flags = 0;
768         tcon.tconx.in.password = data_blob(NULL, 0);
769         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
770         tcon.tconx.in.device = "A:";    
771         status = smb_raw_tcon(tree, tctx, &tcon);
772         CHECK_STATUS(status, NT_STATUS_OK);     
773
774         tree->tid = tcon.tconx.out.tid;
775
776         tid1 = cli->tree->tid;
777         tid2 = tree->tid;
778         printf("tid1=%d tid2=%d\n", tid1, tid2);
779
780         printf("create a file using the tid1\n");
781         cli->tree->tid = tid1;
782         io.generic.level = RAW_OPEN_NTCREATEX;
783         io.ntcreatex.in.root_fid = 0;
784         io.ntcreatex.in.flags = 0;
785         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
786         io.ntcreatex.in.create_options = 0;
787         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
788         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
789         io.ntcreatex.in.alloc_size = 0;
790         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
791         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
792         io.ntcreatex.in.security_flags = 0;
793         io.ntcreatex.in.fname = fname1;
794         status = smb_raw_open(cli->tree, tctx, &io);
795         CHECK_STATUS(status, NT_STATUS_OK);
796         fnum1 = io.ntcreatex.out.file.fnum;
797
798         printf("write using the tid1\n");
799         wr.generic.level = RAW_WRITE_WRITEX;
800         wr.writex.in.file.fnum = fnum1;
801         wr.writex.in.offset = 0;
802         wr.writex.in.wmode = 0;
803         wr.writex.in.remaining = 0;
804         wr.writex.in.count = 1;
805         wr.writex.in.data = &c;
806
807         status = smb_raw_write(cli->tree, &wr);
808         CHECK_STATUS(status, NT_STATUS_OK);
809         CHECK_VALUE(wr.writex.out.nwritten, 1);
810
811         printf("create a file using the tid2\n");
812         cli->tree->tid = tid2;
813         io.generic.level = RAW_OPEN_NTCREATEX;
814         io.ntcreatex.in.root_fid = 0;
815         io.ntcreatex.in.flags = 0;
816         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
817         io.ntcreatex.in.create_options = 0;
818         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
819         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
820         io.ntcreatex.in.alloc_size = 0;
821         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
822         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
823         io.ntcreatex.in.security_flags = 0;
824         io.ntcreatex.in.fname = fname2;
825         status = smb_raw_open(cli->tree, tctx, &io);
826         CHECK_STATUS(status, NT_STATUS_OK);
827         fnum2 = io.ntcreatex.out.file.fnum;
828
829         printf("write using the tid2\n");
830         wr.generic.level = RAW_WRITE_WRITEX;
831         wr.writex.in.file.fnum = fnum2;
832         wr.writex.in.offset = 0;
833         wr.writex.in.wmode = 0;
834         wr.writex.in.remaining = 0;
835         wr.writex.in.count = 1;
836         wr.writex.in.data = &c;
837
838         status = smb_raw_write(cli->tree, &wr);
839         CHECK_STATUS(status, NT_STATUS_OK);
840         CHECK_VALUE(wr.writex.out.nwritten, 1);
841
842         printf("exit the pid\n");
843         status = smb_raw_exit(cli->session);
844         CHECK_STATUS(status, NT_STATUS_OK);
845
846         printf("the fnum1 on tid1 should not be accessible\n");
847         cli->tree->tid = tid1;
848         wr.writex.in.file.fnum = fnum1;
849         status = smb_raw_write(cli->tree, &wr);
850         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
851
852         printf("the fnum1 on tid1 should have been auto-closed\n");
853         cl.close.level = RAW_CLOSE_CLOSE;
854         cl.close.in.file.fnum = fnum1;
855         cl.close.in.write_time = 0;
856         status = smb_raw_close(cli->tree, &cl);
857         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
858
859         printf("the fnum2 on tid2 should not be accessible\n");
860         cli->tree->tid = tid2;
861         wr.writex.in.file.fnum = fnum2;
862         status = smb_raw_write(cli->tree, &wr);
863         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
864
865         printf("the fnum2 on tid2 should have been auto-closed\n");
866         cl.close.level = RAW_CLOSE_CLOSE;
867         cl.close.in.file.fnum = fnum2;
868         cl.close.in.write_time = 0;
869         status = smb_raw_close(cli->tree, &cl);
870         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
871
872 done:
873         return ret;
874 }
875
876
877 /* 
878    basic testing of session/tree context calls
879 */
880 static bool torture_raw_context_int(struct torture_context *tctx, 
881                                                                         struct smbcli_state *cli)
882 {
883         bool ret = true;
884
885         ret &= test_session(cli, tctx);
886         ret &= test_tree(cli, tctx);
887         ret &= test_tree_ulogoff(cli, tctx);
888         ret &= test_pid_exit_only_sees_open(cli, tctx);
889         ret &= test_pid_2sess(cli, tctx);
890         ret &= test_pid_2tcon(cli, tctx);
891
892         smb_raw_exit(cli->session);
893         smbcli_deltree(cli->tree, BASEDIR);
894
895         return ret;
896 }
897 /* 
898    basic testing of session/tree context calls
899 */
900 bool torture_raw_context(struct torture_context *torture, 
901                          struct smbcli_state *cli)
902 {
903         bool ret = true;
904         if (lp_use_spnego(torture->lp_ctx)) {
905                 ret &= torture_raw_context_int(torture, cli);
906                 lp_set_cmdline(torture->lp_ctx, "use spnego", "False");
907         }
908
909         ret &= torture_raw_context_int(torture, cli);
910
911         return ret;
912 }