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