s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[nivanova/samba-autobuild/.git] / source4 / torture / raw / context.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for session setup operations
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 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 "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/smb_composite/smb_composite.h"
24 #include "lib/cmdline/popt_common.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
27 #include "auth/credentials/credentials.h"
28 #include "param/param.h"
29
30 #define BASEDIR "\\rawcontext"
31
32 #define CHECK_STATUS(status, correct) do { \
33         if (!NT_STATUS_EQUAL(status, correct)) { \
34                 printf("(%s) Incorrect status %s - should be %s\n", \
35                        __location__, nt_errstr(status), nt_errstr(correct)); \
36                 ret = false; \
37                 goto done; \
38         }} while (0)
39
40 #define CHECK_VALUE(v, correct) do { \
41         if ((v) != (correct)) { \
42                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
43                        __location__, #v, v, correct); \
44                 ret = false; \
45                 goto done; \
46         }} while (0)
47
48 #define CHECK_NOT_VALUE(v, correct) do { \
49         if ((v) == (correct)) { \
50                 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
51                        __location__, #v, v, correct); \
52                 ret = false; \
53                 goto done; \
54         }} while (0)
55
56
57 /*
58   test session ops
59 */
60 static bool test_session(struct smbcli_state *cli, struct torture_context *tctx)
61 {
62         NTSTATUS status;
63         bool ret = true;
64         struct smbcli_session *session;
65         struct smbcli_session *session2;
66         struct smbcli_session *session3;
67         struct smbcli_session *session4;
68         struct cli_credentials *anon_creds;
69         struct smbcli_session *sessions[15];
70         struct composite_context *composite_contexts[15];
71         struct smbcli_tree *tree;
72         struct smb_composite_sesssetup setup;
73         struct smb_composite_sesssetup setups[15];
74         struct gensec_settings *gensec_settings;
75         union smb_open io;
76         union smb_write wr;
77         union smb_close cl;
78         int fnum;
79         const char *fname = BASEDIR "\\test.txt";
80         uint8_t c = 1;
81         int i;
82         struct smbcli_session_options options;
83
84         printf("TESTING SESSION HANDLING\n");
85
86         if (!torture_setup_dir(cli, BASEDIR)) {
87                 return false;
88         }
89
90         printf("create a second security context on the same transport\n");
91
92         lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
93         gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
94
95         session = smbcli_session_init(cli->transport, tctx, false, options);
96
97         setup.in.sesskey = cli->transport->negotiate.sesskey;
98         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
99         setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
100
101         setup.in.credentials = cmdline_credentials;
102         setup.in.gensec_settings = gensec_settings;
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 = lpcfg_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 = lpcfg_workgroup(tctx->lp_ctx);
143         
144                 setup.in.credentials = cmdline_credentials;
145
146                 status = smb_composite_sesssetup(session3, &setup);
147                 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
148
149                 printf("create a fouth anonymous security context on the same transport, without extended security\n");
150                 session4 = smbcli_session_init(cli->transport, tctx, false, options);
151
152                 session4->vuid = session->vuid;
153                 setup.in.sesskey = cli->transport->negotiate.sesskey;
154                 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
155                 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
156                 
157                 anon_creds = cli_credentials_init(tctx);
158                 cli_credentials_set_conf(anon_creds, tctx->lp_ctx);
159                 cli_credentials_set_anonymous(anon_creds);
160
161                 setup.in.credentials = anon_creds;
162         
163                 status = smb_composite_sesssetup(session3, &setup);
164                 CHECK_STATUS(status, NT_STATUS_OK);
165
166                 talloc_free(session4);
167         }
168                 
169         printf("use the same tree as the existing connection\n");
170         tree = smbcli_tree_init(session, tctx, false);
171         tree->tid = cli->tree->tid;
172
173         printf("create a file using the new vuid\n");
174         io.generic.level = RAW_OPEN_NTCREATEX;
175         io.ntcreatex.in.root_fid.fnum = 0;
176         io.ntcreatex.in.flags = 0;
177         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
178         io.ntcreatex.in.create_options = 0;
179         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
180         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
181         io.ntcreatex.in.alloc_size = 0;
182         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
183         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
184         io.ntcreatex.in.security_flags = 0;
185         io.ntcreatex.in.fname = fname;
186         status = smb_raw_open(tree, tctx, &io);
187         CHECK_STATUS(status, NT_STATUS_OK);
188         fnum = io.ntcreatex.out.file.fnum;
189
190         printf("write using the old vuid\n");
191         wr.generic.level = RAW_WRITE_WRITEX;
192         wr.writex.in.file.fnum = fnum;
193         wr.writex.in.offset = 0;
194         wr.writex.in.wmode = 0;
195         wr.writex.in.remaining = 0;
196         wr.writex.in.count = 1;
197         wr.writex.in.data = &c;
198
199         status = smb_raw_write(cli->tree, &wr);
200         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
201
202         printf("write with the new vuid\n");
203         status = smb_raw_write(tree, &wr);
204         CHECK_STATUS(status, NT_STATUS_OK);
205         CHECK_VALUE(wr.writex.out.nwritten, 1);
206
207         printf("logoff the new vuid\n");
208         status = smb_raw_ulogoff(session);
209         CHECK_STATUS(status, NT_STATUS_OK);
210
211         printf("the new vuid should not now be accessible\n");
212         status = smb_raw_write(tree, &wr);
213         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
214
215         printf("second logoff for the new vuid should fail\n");
216         status = smb_raw_ulogoff(session);
217         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
218         talloc_free(session);
219
220         printf("the fnum should have been auto-closed\n");
221         cl.close.level = RAW_CLOSE_CLOSE;
222         cl.close.in.file.fnum = fnum;
223         cl.close.in.write_time = 0;
224         status = smb_raw_close(cli->tree, &cl);
225         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
226
227         printf("create %d secondary security contexts on the same transport\n", 
228                (int)ARRAY_SIZE(sessions));
229         for (i=0; i <ARRAY_SIZE(sessions); i++) {
230                 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
231                 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
232                 setups[i].in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
233                 
234                 setups[i].in.credentials = cmdline_credentials;
235                 setups[i].in.gensec_settings = gensec_settings;
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.fnum = 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         lpcfg_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 = lpcfg_workgroup(tctx->lp_ctx);
404         setup.in.credentials = cmdline_credentials;
405         setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
406         status = smb_composite_sesssetup(session1, &setup);
407         CHECK_STATUS(status, NT_STATUS_OK);
408         session1->vuid = setup.out.vuid;
409         printf("vuid1=%d\n", session1->vuid);
410
411         printf("create a tree context on the with vuid1\n");
412         tree = smbcli_tree_init(session1, tctx, false);
413         tcon.generic.level = RAW_TCON_TCONX;
414         tcon.tconx.in.flags = 0;
415         tcon.tconx.in.password = data_blob(NULL, 0);
416         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
417         tcon.tconx.in.device = "A:";
418         status = smb_raw_tcon(tree, tctx, &tcon);
419         CHECK_STATUS(status, NT_STATUS_OK);
420         tree->tid = tcon.tconx.out.tid;
421         printf("tid=%d\n", tree->tid);
422
423         printf("create a file using vuid1\n");
424         io.generic.level = RAW_OPEN_NTCREATEX;
425         io.ntcreatex.in.root_fid.fnum = 0;
426         io.ntcreatex.in.flags = 0;
427         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
428         io.ntcreatex.in.create_options = 0;
429         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
430         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
431         io.ntcreatex.in.alloc_size = 0;
432         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
433         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
434         io.ntcreatex.in.security_flags = 0;
435         io.ntcreatex.in.fname = fname1;
436         status = smb_raw_open(tree, tctx, &io);
437         CHECK_STATUS(status, NT_STATUS_OK);
438         fnum1 = io.ntcreatex.out.file.fnum;
439
440         printf("write using vuid1\n");
441         wr.generic.level = RAW_WRITE_WRITEX;
442         wr.writex.in.file.fnum = fnum1;
443         wr.writex.in.offset = 0;
444         wr.writex.in.wmode = 0;
445         wr.writex.in.remaining = 0;
446         wr.writex.in.count = 1;
447         wr.writex.in.data = &c;
448         status = smb_raw_write(tree, &wr);
449         CHECK_STATUS(status, NT_STATUS_OK);
450         CHECK_VALUE(wr.writex.out.nwritten, 1);
451
452         printf("ulogoff the vuid1\n");
453         status = smb_raw_ulogoff(session1);
454         CHECK_STATUS(status, NT_STATUS_OK);
455
456         printf("create the second new sessions\n");
457         session2 = smbcli_session_init(cli->transport, tctx, false, options);
458         setup.in.sesskey = cli->transport->negotiate.sesskey;
459         setup.in.capabilities = cli->transport->negotiate.capabilities;
460         setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
461         setup.in.credentials = cmdline_credentials;
462         setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
463         status = smb_composite_sesssetup(session2, &setup);
464         CHECK_STATUS(status, NT_STATUS_OK);
465         session2->vuid = setup.out.vuid;
466         printf("vuid2=%d\n", session2->vuid);
467
468         printf("use the existing tree with vuid2\n");
469         tree->session = session2;
470
471         printf("create a file using vuid2\n");
472         io.generic.level = RAW_OPEN_NTCREATEX;
473         io.ntcreatex.in.root_fid.fnum = 0;
474         io.ntcreatex.in.flags = 0;
475         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
476         io.ntcreatex.in.create_options = 0;
477         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
478         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
479         io.ntcreatex.in.alloc_size = 0;
480         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
481         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
482         io.ntcreatex.in.security_flags = 0;
483         io.ntcreatex.in.fname = fname2;
484         status = smb_raw_open(tree, tctx, &io);
485         CHECK_STATUS(status, NT_STATUS_OK);
486         fnum2 = io.ntcreatex.out.file.fnum;
487
488         printf("write using vuid2\n");
489         wr.generic.level = RAW_WRITE_WRITEX;
490         wr.writex.in.file.fnum = fnum2;
491         wr.writex.in.offset = 0;
492         wr.writex.in.wmode = 0;
493         wr.writex.in.remaining = 0;
494         wr.writex.in.count = 1;
495         wr.writex.in.data = &c;
496         status = smb_raw_write(tree, &wr);
497         CHECK_STATUS(status, NT_STATUS_OK);
498         CHECK_VALUE(wr.writex.out.nwritten, 1);
499
500         printf("ulogoff the vuid2\n");
501         status = smb_raw_ulogoff(session2);
502         CHECK_STATUS(status, NT_STATUS_OK);
503
504         /* this also demonstrates that SMBtdis doesn't need a valid vuid */
505         printf("disconnect the existing tree connection\n");
506         status = smb_tree_disconnect(tree);
507         CHECK_STATUS(status, NT_STATUS_OK);
508
509         printf("disconnect the existing tree connection\n");
510         status = smb_tree_disconnect(tree);
511         CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
512
513         /* close down the new tree */
514         talloc_free(tree);
515         
516 done:
517         return ret;
518 }
519
520 /*
521   test pid ops
522   this test demonstrates that exit() only sees the PID
523   used for the open() calls
524 */
525 static bool test_pid_exit_only_sees_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
526 {
527         NTSTATUS status;
528         bool ret = true;
529         union smb_open io;
530         union smb_write wr;
531         union smb_close cl;
532         int fnum;
533         const char *fname = BASEDIR "\\test.txt";
534         uint8_t c = 1;
535         uint16_t pid1, pid2;
536
537         printf("TESTING PID HANDLING exit() only cares about open() PID\n");
538
539         if (!torture_setup_dir(cli, BASEDIR)) {
540                 return false;
541         }
542
543         pid1 = cli->session->pid;
544         pid2 = pid1 + 1;
545
546         printf("pid1=%d pid2=%d\n", pid1, pid2);
547
548         printf("create a file using pid1\n");
549         cli->session->pid = pid1;
550         io.generic.level = RAW_OPEN_NTCREATEX;
551         io.ntcreatex.in.root_fid.fnum = 0;
552         io.ntcreatex.in.flags = 0;
553         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
554         io.ntcreatex.in.create_options = 0;
555         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
556         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
557         io.ntcreatex.in.alloc_size = 0;
558         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
559         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
560         io.ntcreatex.in.security_flags = 0;
561         io.ntcreatex.in.fname = fname;
562         status = smb_raw_open(cli->tree, mem_ctx, &io);
563         CHECK_STATUS(status, NT_STATUS_OK);
564         fnum = io.ntcreatex.out.file.fnum;
565
566         printf("write using pid2\n");
567         cli->session->pid = pid2;
568         wr.generic.level = RAW_WRITE_WRITEX;
569         wr.writex.in.file.fnum = fnum;
570         wr.writex.in.offset = 0;
571         wr.writex.in.wmode = 0;
572         wr.writex.in.remaining = 0;
573         wr.writex.in.count = 1;
574         wr.writex.in.data = &c;
575         status = smb_raw_write(cli->tree, &wr);
576         CHECK_STATUS(status, NT_STATUS_OK);
577         CHECK_VALUE(wr.writex.out.nwritten, 1);
578
579         printf("exit pid2\n");
580         cli->session->pid = pid2;
581         status = smb_raw_exit(cli->session);
582         CHECK_STATUS(status, NT_STATUS_OK);
583
584         printf("the fnum should still be accessible via pid2\n");
585         cli->session->pid = pid2;
586         status = smb_raw_write(cli->tree, &wr);
587         CHECK_STATUS(status, NT_STATUS_OK);
588         CHECK_VALUE(wr.writex.out.nwritten, 1);
589
590         printf("exit pid2\n");
591         cli->session->pid = pid2;
592         status = smb_raw_exit(cli->session);
593         CHECK_STATUS(status, NT_STATUS_OK);
594
595         printf("the fnum should still be accessible via pid1 and pid2\n");
596         cli->session->pid = pid1;
597         status = smb_raw_write(cli->tree, &wr);
598         CHECK_STATUS(status, NT_STATUS_OK);
599         CHECK_VALUE(wr.writex.out.nwritten, 1);
600         cli->session->pid = pid2;
601         status = smb_raw_write(cli->tree, &wr);
602         CHECK_STATUS(status, NT_STATUS_OK);
603         CHECK_VALUE(wr.writex.out.nwritten, 1);
604
605         printf("exit pid1\n");
606         cli->session->pid = pid1;
607         status = smb_raw_exit(cli->session);
608         CHECK_STATUS(status, NT_STATUS_OK);
609
610         printf("the fnum should not now be accessible via pid1 or pid2\n");
611         cli->session->pid = pid1;
612         status = smb_raw_write(cli->tree, &wr);
613         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
614         cli->session->pid = pid2;
615         status = smb_raw_write(cli->tree, &wr);
616         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
617
618         printf("the fnum should have been auto-closed\n");
619         cli->session->pid = pid1;
620         cl.close.level = RAW_CLOSE_CLOSE;
621         cl.close.in.file.fnum = fnum;
622         cl.close.in.write_time = 0;
623         status = smb_raw_close(cli->tree, &cl);
624         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
625
626 done:
627         return ret;
628 }
629
630 /*
631   test pid ops with 2 sessions
632 */
633 static bool test_pid_2sess(struct smbcli_state *cli, struct torture_context *tctx)
634 {
635         NTSTATUS status;
636         bool ret = true;
637         struct smbcli_session *session;
638         struct smb_composite_sesssetup setup;
639         union smb_open io;
640         union smb_write wr;
641         union smb_close cl;
642         int fnum;
643         const char *fname = BASEDIR "\\test.txt";
644         uint8_t c = 1;
645         uint16_t vuid1, vuid2;
646         struct smbcli_session_options options;
647
648         printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
649
650         if (!torture_setup_dir(cli, BASEDIR)) {
651                 return false;
652         }
653
654         lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
655
656         printf("create a second security context on the same transport\n");
657         session = smbcli_session_init(cli->transport, tctx, false, options);
658
659         setup.in.sesskey = cli->transport->negotiate.sesskey;
660         setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
661         setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
662         setup.in.credentials = cmdline_credentials;
663         setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
664
665         status = smb_composite_sesssetup(session, &setup);
666         CHECK_STATUS(status, NT_STATUS_OK);     
667         session->vuid = setup.out.vuid;
668
669         vuid1 = cli->session->vuid;
670         vuid2 = session->vuid;
671
672         printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
673
674         printf("create a file using the vuid1\n");
675         cli->session->vuid = vuid1;
676         io.generic.level = RAW_OPEN_NTCREATEX;
677         io.ntcreatex.in.root_fid.fnum = 0;
678         io.ntcreatex.in.flags = 0;
679         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
680         io.ntcreatex.in.create_options = 0;
681         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
682         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
683         io.ntcreatex.in.alloc_size = 0;
684         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
685         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
686         io.ntcreatex.in.security_flags = 0;
687         io.ntcreatex.in.fname = fname;
688         status = smb_raw_open(cli->tree, tctx, &io);
689         CHECK_STATUS(status, NT_STATUS_OK);
690         fnum = io.ntcreatex.out.file.fnum;
691
692         printf("write using the vuid1 (fnum=%d)\n", fnum);
693         cli->session->vuid = vuid1;
694         wr.generic.level = RAW_WRITE_WRITEX;
695         wr.writex.in.file.fnum = fnum;
696         wr.writex.in.offset = 0;
697         wr.writex.in.wmode = 0;
698         wr.writex.in.remaining = 0;
699         wr.writex.in.count = 1;
700         wr.writex.in.data = &c;
701
702         status = smb_raw_write(cli->tree, &wr);
703         CHECK_STATUS(status, NT_STATUS_OK);
704         CHECK_VALUE(wr.writex.out.nwritten, 1);
705
706         printf("exit the pid with vuid2\n");
707         cli->session->vuid = vuid2;
708         status = smb_raw_exit(cli->session);
709         CHECK_STATUS(status, NT_STATUS_OK);
710
711         printf("the fnum should still be accessible\n");
712         cli->session->vuid = vuid1;
713         status = smb_raw_write(cli->tree, &wr);
714         CHECK_STATUS(status, NT_STATUS_OK);
715         CHECK_VALUE(wr.writex.out.nwritten, 1);
716
717         printf("exit the pid with vuid1\n");
718         cli->session->vuid = vuid1;
719         status = smb_raw_exit(cli->session);
720         CHECK_STATUS(status, NT_STATUS_OK);
721
722         printf("the fnum should not now be accessible\n");
723         status = smb_raw_write(cli->tree, &wr);
724         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
725
726         printf("the fnum should have been auto-closed\n");
727         cl.close.level = RAW_CLOSE_CLOSE;
728         cl.close.in.file.fnum = fnum;
729         cl.close.in.write_time = 0;
730         status = smb_raw_close(cli->tree, &cl);
731         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
732
733 done:
734         return ret;
735 }
736
737 /*
738   test pid ops with 2 tcons
739 */
740 static bool test_pid_2tcon(struct smbcli_state *cli, struct torture_context *tctx)
741 {
742         NTSTATUS status;
743         bool ret = true;
744         const char *share, *host;
745         struct smbcli_tree *tree;
746         union smb_tcon tcon;
747         union smb_open io;
748         union smb_write wr;
749         union smb_close cl;
750         int fnum1, fnum2;
751         const char *fname1 = BASEDIR "\\test1.txt";
752         const char *fname2 = BASEDIR "\\test2.txt";
753         uint8_t c = 1;
754         uint16_t tid1, tid2;
755
756         printf("TESTING PID HANDLING WITH 2 TCONS\n");
757
758         if (!torture_setup_dir(cli, BASEDIR)) {
759                 return false;
760         }
761
762         share = torture_setting_string(tctx, "share", NULL);
763         host  = torture_setting_string(tctx, "host", NULL);
764         
765         printf("create a second tree context on the same session\n");
766         tree = smbcli_tree_init(cli->session, tctx, false);
767
768         tcon.generic.level = RAW_TCON_TCONX;
769         tcon.tconx.in.flags = 0;
770         tcon.tconx.in.password = data_blob(NULL, 0);
771         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
772         tcon.tconx.in.device = "A:";    
773         status = smb_raw_tcon(tree, tctx, &tcon);
774         CHECK_STATUS(status, NT_STATUS_OK);     
775
776         tree->tid = tcon.tconx.out.tid;
777
778         tid1 = cli->tree->tid;
779         tid2 = tree->tid;
780         printf("tid1=%d tid2=%d\n", tid1, tid2);
781
782         printf("create a file using the tid1\n");
783         cli->tree->tid = tid1;
784         io.generic.level = RAW_OPEN_NTCREATEX;
785         io.ntcreatex.in.root_fid.fnum = 0;
786         io.ntcreatex.in.flags = 0;
787         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
788         io.ntcreatex.in.create_options = 0;
789         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
790         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
791         io.ntcreatex.in.alloc_size = 0;
792         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
793         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
794         io.ntcreatex.in.security_flags = 0;
795         io.ntcreatex.in.fname = fname1;
796         status = smb_raw_open(cli->tree, tctx, &io);
797         CHECK_STATUS(status, NT_STATUS_OK);
798         fnum1 = io.ntcreatex.out.file.fnum;
799
800         printf("write using the tid1\n");
801         wr.generic.level = RAW_WRITE_WRITEX;
802         wr.writex.in.file.fnum = fnum1;
803         wr.writex.in.offset = 0;
804         wr.writex.in.wmode = 0;
805         wr.writex.in.remaining = 0;
806         wr.writex.in.count = 1;
807         wr.writex.in.data = &c;
808
809         status = smb_raw_write(cli->tree, &wr);
810         CHECK_STATUS(status, NT_STATUS_OK);
811         CHECK_VALUE(wr.writex.out.nwritten, 1);
812
813         printf("create a file using the tid2\n");
814         cli->tree->tid = tid2;
815         io.generic.level = RAW_OPEN_NTCREATEX;
816         io.ntcreatex.in.root_fid.fnum = 0;
817         io.ntcreatex.in.flags = 0;
818         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
819         io.ntcreatex.in.create_options = 0;
820         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
821         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
822         io.ntcreatex.in.alloc_size = 0;
823         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
824         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
825         io.ntcreatex.in.security_flags = 0;
826         io.ntcreatex.in.fname = fname2;
827         status = smb_raw_open(cli->tree, tctx, &io);
828         CHECK_STATUS(status, NT_STATUS_OK);
829         fnum2 = io.ntcreatex.out.file.fnum;
830
831         printf("write using the tid2\n");
832         wr.generic.level = RAW_WRITE_WRITEX;
833         wr.writex.in.file.fnum = fnum2;
834         wr.writex.in.offset = 0;
835         wr.writex.in.wmode = 0;
836         wr.writex.in.remaining = 0;
837         wr.writex.in.count = 1;
838         wr.writex.in.data = &c;
839
840         status = smb_raw_write(cli->tree, &wr);
841         CHECK_STATUS(status, NT_STATUS_OK);
842         CHECK_VALUE(wr.writex.out.nwritten, 1);
843
844         printf("exit the pid\n");
845         status = smb_raw_exit(cli->session);
846         CHECK_STATUS(status, NT_STATUS_OK);
847
848         printf("the fnum1 on tid1 should not be accessible\n");
849         cli->tree->tid = tid1;
850         wr.writex.in.file.fnum = fnum1;
851         status = smb_raw_write(cli->tree, &wr);
852         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
853
854         printf("the fnum1 on tid1 should have been auto-closed\n");
855         cl.close.level = RAW_CLOSE_CLOSE;
856         cl.close.in.file.fnum = fnum1;
857         cl.close.in.write_time = 0;
858         status = smb_raw_close(cli->tree, &cl);
859         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
860
861         printf("the fnum2 on tid2 should not be accessible\n");
862         cli->tree->tid = tid2;
863         wr.writex.in.file.fnum = fnum2;
864         status = smb_raw_write(cli->tree, &wr);
865         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
866
867         printf("the fnum2 on tid2 should have been auto-closed\n");
868         cl.close.level = RAW_CLOSE_CLOSE;
869         cl.close.in.file.fnum = fnum2;
870         cl.close.in.write_time = 0;
871         status = smb_raw_close(cli->tree, &cl);
872         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
873
874 done:
875         return ret;
876 }
877
878
879 /* 
880    basic testing of session/tree context calls
881 */
882 static bool torture_raw_context_int(struct torture_context *tctx, 
883                                                                         struct smbcli_state *cli)
884 {
885         bool ret = true;
886
887         ret &= test_session(cli, tctx);
888         ret &= test_tree(cli, tctx);
889         ret &= test_tree_ulogoff(cli, tctx);
890         ret &= test_pid_exit_only_sees_open(cli, tctx);
891         ret &= test_pid_2sess(cli, tctx);
892         ret &= test_pid_2tcon(cli, tctx);
893
894         smb_raw_exit(cli->session);
895         smbcli_deltree(cli->tree, BASEDIR);
896
897         return ret;
898 }
899 /* 
900    basic testing of session/tree context calls
901 */
902 bool torture_raw_context(struct torture_context *torture, 
903                          struct smbcli_state *cli)
904 {
905         bool ret = true;
906         if (lpcfg_use_spnego(torture->lp_ctx)) {
907                 ret &= torture_raw_context_int(torture, cli);
908                 lpcfg_set_cmdline(torture->lp_ctx, "use spnego", "False");
909         }
910
911         ret &= torture_raw_context_int(torture, cli);
912
913         return ret;
914 }