s3: Fix bug #9085.
[Samba.git] / source4 / torture / raw / context.c
bloba9d36b7788c9f9a19963c063c0a63baf3d6ea930
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for session setup operations
4 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
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"
33 #define BASEDIR "\\rawcontext"
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)
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)
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)
61 test session ops
63 static bool test_session(struct smbcli_state *cli, struct torture_context *tctx)
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;
87 printf("TESTING SESSION HANDLING\n");
89 if (!torture_setup_dir(cli, BASEDIR)) {
90 return false;
93 printf("create a second security context on the same transport\n");
95 lp_smbcli_session_options(tctx->lp_ctx, &options);
96 gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
98 session = smbcli_session_init(cli->transport, tctx, false, options);
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);
104 setup.in.credentials = cmdline_credentials;
105 setup.in.gensec_settings = gensec_settings;
107 status = smb_composite_sesssetup(session, &setup);
108 CHECK_STATUS(status, NT_STATUS_OK);
110 session->vuid = setup.out.vuid;
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);
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);
120 setup.in.credentials = cmdline_credentials;
122 status = smb_composite_sesssetup(session2, &setup);
123 CHECK_STATUS(status, NT_STATUS_OK);
125 session2->vuid = setup.out.vuid;
126 printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
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");
133 } else {
134 CHECK_NOT_VALUE(session2->vuid, session->vuid);
136 talloc_free(session2);
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);
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);
147 setup.in.credentials = cmdline_credentials;
149 status = smb_composite_sesssetup(session3, &setup);
150 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
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);
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);
160 anon_creds = cli_credentials_init(tctx);
161 cli_credentials_set_conf(anon_creds, tctx->lp_ctx);
162 cli_credentials_set_anonymous(anon_creds);
164 setup.in.credentials = anon_creds;
166 status = smb_composite_sesssetup(session3, &setup);
167 CHECK_STATUS(status, NT_STATUS_OK);
169 talloc_free(session4);
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;
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;
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;
202 status = smb_raw_write(cli->tree, &wr);
203 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
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);
210 printf("logoff the new vuid\n");
211 status = smb_raw_ulogoff(session);
212 CHECK_STATUS(status, NT_STATUS_OK);
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);
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);
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);
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);
237 setups[i].in.credentials = cmdline_credentials;
238 setups[i].in.gensec_settings = gensec_settings;
240 sessions[i] = smbcli_session_init(cli->transport, tctx, false, options);
241 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
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);
258 talloc_free(tree);
260 done:
261 return ret;
266 test tree ops
268 static bool test_tree(struct smbcli_state *cli, struct torture_context *tctx)
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;
282 printf("TESTING TREE HANDLING\n");
284 if (!torture_setup_dir(cli, BASEDIR)) {
285 return false;
288 share = torture_setting_string(tctx, "share", NULL);
289 host = torture_setting_string(tctx, "host", NULL);
291 printf("create a second tree context on the same session\n");
292 tree = smbcli_tree_init(cli->session, tctx, false);
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);
303 tree->tid = tcon.tconx.out.tid;
304 printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
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);
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;
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;
338 status = smb_raw_write(cli->tree, &wr);
339 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
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);
346 printf("disconnect the new tid\n");
347 status = smb_tree_disconnect(tree);
348 CHECK_STATUS(status, NT_STATUS_OK);
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);
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);
361 /* close down the new tree */
362 talloc_free(tree);
364 done:
365 return ret;
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
373 static bool test_tree_ulogoff(struct smbcli_state *cli, struct torture_context *tctx)
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;
391 printf("TESTING TREE with ulogoff\n");
393 if (!torture_setup_dir(cli, BASEDIR)) {
394 return false;
397 share = torture_setting_string(tctx, "share", NULL);
398 host = torture_setting_string(tctx, "host", NULL);
400 lp_smbcli_session_options(tctx->lp_ctx, &options);
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);
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);
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;
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);
455 printf("ulogoff the vuid1\n");
456 status = smb_raw_ulogoff(session1);
457 CHECK_STATUS(status, NT_STATUS_OK);
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);
471 printf("use the existing tree with vuid2\n");
472 tree->session = session2;
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;
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);
503 printf("ulogoff the vuid2\n");
504 status = smb_raw_ulogoff(session2);
505 CHECK_STATUS(status, NT_STATUS_OK);
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);
512 printf("disconnect the existing tree connection\n");
513 status = smb_tree_disconnect(tree);
514 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
516 /* close down the new tree */
517 talloc_free(tree);
519 done:
520 return ret;
524 test pid ops
525 this test demonstrates that exit() only sees the PID
526 used for the open() calls
528 static bool test_pid_exit_only_sees_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
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;
540 printf("TESTING PID HANDLING exit() only cares about open() PID\n");
542 if (!torture_setup_dir(cli, BASEDIR)) {
543 return false;
546 pid1 = cli->session->pid;
547 pid2 = pid1 + 1;
549 printf("pid1=%d pid2=%d\n", pid1, pid2);
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;
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);
582 printf("exit pid2\n");
583 cli->session->pid = pid2;
584 status = smb_raw_exit(cli->session);
585 CHECK_STATUS(status, NT_STATUS_OK);
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);
593 printf("exit pid2\n");
594 cli->session->pid = pid2;
595 status = smb_raw_exit(cli->session);
596 CHECK_STATUS(status, NT_STATUS_OK);
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);
608 printf("exit pid1\n");
609 cli->session->pid = pid1;
610 status = smb_raw_exit(cli->session);
611 CHECK_STATUS(status, NT_STATUS_OK);
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);
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);
629 done:
630 return ret;
634 test pid ops with 2 sessions
636 static bool test_pid_2sess(struct smbcli_state *cli, struct torture_context *tctx)
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;
651 printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
653 if (!torture_setup_dir(cli, BASEDIR)) {
654 return false;
657 lp_smbcli_session_options(tctx->lp_ctx, &options);
659 printf("create a second security context on the same transport\n");
660 session = smbcli_session_init(cli->transport, tctx, false, options);
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);
668 status = smb_composite_sesssetup(session, &setup);
669 CHECK_STATUS(status, NT_STATUS_OK);
670 session->vuid = setup.out.vuid;
672 vuid1 = cli->session->vuid;
673 vuid2 = session->vuid;
675 printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
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;
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;
705 status = smb_raw_write(cli->tree, &wr);
706 CHECK_STATUS(status, NT_STATUS_OK);
707 CHECK_VALUE(wr.writex.out.nwritten, 1);
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);
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);
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);
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);
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);
736 done:
737 return ret;
741 test pid ops with 2 tcons
743 static bool test_pid_2tcon(struct smbcli_state *cli, struct torture_context *tctx)
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;
759 printf("TESTING PID HANDLING WITH 2 TCONS\n");
761 if (!torture_setup_dir(cli, BASEDIR)) {
762 return false;
765 share = torture_setting_string(tctx, "share", NULL);
766 host = torture_setting_string(tctx, "host", NULL);
768 printf("create a second tree context on the same session\n");
769 tree = smbcli_tree_init(cli->session, tctx, false);
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);
779 tree->tid = tcon.tconx.out.tid;
781 tid1 = cli->tree->tid;
782 tid2 = tree->tid;
783 printf("tid1=%d tid2=%d\n", tid1, tid2);
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;
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;
812 status = smb_raw_write(cli->tree, &wr);
813 CHECK_STATUS(status, NT_STATUS_OK);
814 CHECK_VALUE(wr.writex.out.nwritten, 1);
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;
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;
843 status = smb_raw_write(cli->tree, &wr);
844 CHECK_STATUS(status, NT_STATUS_OK);
845 CHECK_VALUE(wr.writex.out.nwritten, 1);
847 printf("exit the pid\n");
848 status = smb_raw_exit(cli->session);
849 CHECK_STATUS(status, NT_STATUS_OK);
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);
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);
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);
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);
877 done:
878 return ret;
883 basic testing of session/tree context calls
885 static bool torture_raw_context_int(struct torture_context *tctx,
886 struct smbcli_state *cli)
888 bool ret = true;
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);
897 smb_raw_exit(cli->session);
898 smbcli_deltree(cli->tree, BASEDIR);
900 return ret;
903 basic testing of session/tree context calls
905 bool torture_raw_context(struct torture_context *torture,
906 struct smbcli_state *cli)
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");
914 ret &= torture_raw_context_int(torture, cli);
916 return ret;