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/>.
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 #include "torture/raw/proto.h"
31 #define BASEDIR "\\rawcontext"
33 #define CHECK_STATUS(status, correct) \
34 torture_assert_ntstatus_equal_goto(tctx, status, correct, ret, done, __location__)
36 #define CHECK_VALUE(v, correct) \
37 torture_assert_int_equal_goto(tctx, v, correct, ret, done, __location__)
39 #define CHECK_NOT_VALUE(v, correct) \
40 torture_assert_goto(tctx, ((v) != (correct)), ret, done, \
41 talloc_asprintf(tctx, "(%s) Incorrect value %s=%d - should not be %d\n", \
42 __location__, #v, v, correct));
48 static bool test_session(struct torture_context *tctx,
49 struct smbcli_state *cli)
53 struct smbcli_session *session;
54 struct smbcli_session *session2;
55 struct smbcli_session *session3;
56 struct smbcli_session *session4;
57 struct cli_credentials *anon_creds;
58 struct smbcli_session *sessions[15];
59 struct composite_context *composite_contexts[15];
60 struct smbcli_tree *tree;
61 struct smb_composite_sesssetup setup;
62 struct smb_composite_sesssetup setups[15];
63 struct gensec_settings *gensec_settings;
68 const char *fname = BASEDIR "\\test.txt";
71 struct smbcli_session_options options;
73 torture_comment(tctx, "TESTING SESSION HANDLING\n");
75 if (!torture_setup_dir(cli, BASEDIR)) {
79 torture_comment(tctx, "create a second security context on the same transport\n");
81 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
82 gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
84 session = smbcli_session_init(cli->transport, tctx, false, options);
86 setup.in.sesskey = cli->transport->negotiate.sesskey;
87 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
88 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
90 setup.in.credentials = cmdline_credentials;
91 setup.in.gensec_settings = gensec_settings;
93 status = smb_composite_sesssetup(session, &setup);
94 CHECK_STATUS(status, NT_STATUS_OK);
96 session->vuid = setup.out.vuid;
98 torture_comment(tctx, "create a third security context on the same transport, with vuid set\n");
99 session2 = smbcli_session_init(cli->transport, tctx, false, options);
101 session2->vuid = session->vuid;
102 setup.in.sesskey = cli->transport->negotiate.sesskey;
103 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
104 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
106 setup.in.credentials = cmdline_credentials;
108 status = smb_composite_sesssetup(session2, &setup);
109 CHECK_STATUS(status, NT_STATUS_OK);
111 session2->vuid = setup.out.vuid;
112 torture_comment(tctx, "vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
114 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
115 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
116 if (session2->vuid == session->vuid) {
117 torture_comment(tctx, "server allows the user to re-use an existing vuid in session setup \n");
120 CHECK_NOT_VALUE(session2->vuid, session->vuid);
122 talloc_free(session2);
124 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
125 torture_comment(tctx, "create a fourth security context on the same transport, without extended security\n");
126 session3 = smbcli_session_init(cli->transport, tctx, false, options);
128 session3->vuid = session->vuid;
129 setup.in.sesskey = cli->transport->negotiate.sesskey;
130 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
131 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
133 setup.in.credentials = cmdline_credentials;
135 status = smb_composite_sesssetup(session3, &setup);
136 if (!NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)) {
138 * Windows 2008 R2 returns INVALID_PARAMETER
139 * while Windows 2000 sp4 returns LOGON_FAILURE...
141 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
144 torture_comment(tctx, "create a fouth anonymous security context on the same transport, without extended security\n");
145 session4 = smbcli_session_init(cli->transport, tctx, false, options);
147 session4->vuid = session->vuid;
148 setup.in.sesskey = cli->transport->negotiate.sesskey;
149 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
150 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
152 anon_creds = cli_credentials_init(tctx);
153 cli_credentials_set_conf(anon_creds, tctx->lp_ctx);
154 cli_credentials_set_anonymous(anon_creds);
156 setup.in.credentials = anon_creds;
158 status = smb_composite_sesssetup(session3, &setup);
159 CHECK_STATUS(status, NT_STATUS_OK);
161 talloc_free(session4);
164 torture_comment(tctx, "use the same tree as the existing connection\n");
165 tree = smbcli_tree_init(session, tctx, false);
166 tree->tid = cli->tree->tid;
168 torture_comment(tctx, "create a file using the new vuid\n");
169 io.generic.level = RAW_OPEN_NTCREATEX;
170 io.ntcreatex.in.root_fid.fnum = 0;
171 io.ntcreatex.in.flags = 0;
172 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
173 io.ntcreatex.in.create_options = 0;
174 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
175 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
176 io.ntcreatex.in.alloc_size = 0;
177 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
178 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
179 io.ntcreatex.in.security_flags = 0;
180 io.ntcreatex.in.fname = fname;
181 status = smb_raw_open(tree, tctx, &io);
182 CHECK_STATUS(status, NT_STATUS_OK);
183 fnum = io.ntcreatex.out.file.fnum;
185 torture_comment(tctx, "write using the old vuid\n");
186 wr.generic.level = RAW_WRITE_WRITEX;
187 wr.writex.in.file.fnum = fnum;
188 wr.writex.in.offset = 0;
189 wr.writex.in.wmode = 0;
190 wr.writex.in.remaining = 0;
191 wr.writex.in.count = 1;
192 wr.writex.in.data = &c;
194 status = smb_raw_write(cli->tree, &wr);
195 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
197 torture_comment(tctx, "write with the new vuid\n");
198 status = smb_raw_write(tree, &wr);
199 CHECK_STATUS(status, NT_STATUS_OK);
200 CHECK_VALUE(wr.writex.out.nwritten, 1);
202 torture_comment(tctx, "logoff the new vuid\n");
203 status = smb_raw_ulogoff(session);
204 CHECK_STATUS(status, NT_STATUS_OK);
206 torture_comment(tctx, "the new vuid should not now be accessible\n");
207 status = smb_raw_write(tree, &wr);
208 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
210 torture_comment(tctx, "second logoff for the new vuid should fail\n");
211 status = smb_raw_ulogoff(session);
212 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
213 talloc_free(session);
215 torture_comment(tctx, "the fnum should have been auto-closed\n");
216 cl.close.level = RAW_CLOSE_CLOSE;
217 cl.close.in.file.fnum = fnum;
218 cl.close.in.write_time = 0;
219 status = smb_raw_close(cli->tree, &cl);
220 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
222 torture_comment(tctx, "create %d secondary security contexts on the same transport\n",
223 (int)ARRAY_SIZE(sessions));
224 for (i=0; i <ARRAY_SIZE(sessions); i++) {
225 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
226 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
227 setups[i].in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
229 setups[i].in.credentials = cmdline_credentials;
230 setups[i].in.gensec_settings = gensec_settings;
232 sessions[i] = smbcli_session_init(cli->transport, tctx, false, options);
233 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
238 torture_comment(tctx, "finishing %d secondary security contexts on the same transport\n",
239 (int)ARRAY_SIZE(sessions));
240 for (i=0; i< ARRAY_SIZE(sessions); i++) {
241 status = smb_composite_sesssetup_recv(composite_contexts[i]);
242 CHECK_STATUS(status, NT_STATUS_OK);
243 sessions[i]->vuid = setups[i].out.vuid;
244 torture_comment(tctx, "VUID: %d\n", sessions[i]->vuid);
245 status = smb_raw_ulogoff(sessions[i]);
246 CHECK_STATUS(status, NT_STATUS_OK);
260 static bool test_tree(struct torture_context *tctx, struct smbcli_state *cli)
264 const char *share, *host;
265 struct smbcli_tree *tree;
271 const char *fname = BASEDIR "\\test.txt";
274 torture_comment(tctx, "TESTING TREE HANDLING\n");
276 if (!torture_setup_dir(cli, BASEDIR)) {
280 share = torture_setting_string(tctx, "share", NULL);
281 host = torture_setting_string(tctx, "host", NULL);
283 torture_comment(tctx, "create a second tree context on the same session\n");
284 tree = smbcli_tree_init(cli->session, tctx, false);
286 tcon.generic.level = RAW_TCON_TCONX;
287 tcon.tconx.in.flags = 0;
288 tcon.tconx.in.password = data_blob(NULL, 0);
289 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
290 tcon.tconx.in.device = "A:";
291 status = smb_raw_tcon(tree, tctx, &tcon);
292 CHECK_STATUS(status, NT_STATUS_OK);
295 tree->tid = tcon.tconx.out.tid;
296 torture_comment(tctx, "tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
298 torture_comment(tctx, "try a tconx with a bad device type\n");
299 tcon.tconx.in.device = "FOO";
300 status = smb_raw_tcon(tree, tctx, &tcon);
301 CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
304 torture_comment(tctx, "create a file using the new tid\n");
305 io.generic.level = RAW_OPEN_NTCREATEX;
306 io.ntcreatex.in.root_fid.fnum = 0;
307 io.ntcreatex.in.flags = 0;
308 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
309 io.ntcreatex.in.create_options = 0;
310 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
311 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
312 io.ntcreatex.in.alloc_size = 0;
313 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
314 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
315 io.ntcreatex.in.security_flags = 0;
316 io.ntcreatex.in.fname = fname;
317 status = smb_raw_open(tree, tctx, &io);
318 CHECK_STATUS(status, NT_STATUS_OK);
319 fnum = io.ntcreatex.out.file.fnum;
321 torture_comment(tctx, "write using the old tid\n");
322 wr.generic.level = RAW_WRITE_WRITEX;
323 wr.writex.in.file.fnum = fnum;
324 wr.writex.in.offset = 0;
325 wr.writex.in.wmode = 0;
326 wr.writex.in.remaining = 0;
327 wr.writex.in.count = 1;
328 wr.writex.in.data = &c;
330 status = smb_raw_write(cli->tree, &wr);
331 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
333 torture_comment(tctx, "write with the new tid\n");
334 status = smb_raw_write(tree, &wr);
335 CHECK_STATUS(status, NT_STATUS_OK);
336 CHECK_VALUE(wr.writex.out.nwritten, 1);
338 torture_comment(tctx, "disconnect the new tid\n");
339 status = smb_tree_disconnect(tree);
340 CHECK_STATUS(status, NT_STATUS_OK);
342 torture_comment(tctx, "the new tid should not now be accessible\n");
343 status = smb_raw_write(tree, &wr);
344 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
346 torture_comment(tctx, "the fnum should have been auto-closed\n");
347 cl.close.level = RAW_CLOSE_CLOSE;
348 cl.close.in.file.fnum = fnum;
349 cl.close.in.write_time = 0;
350 status = smb_raw_close(cli->tree, &cl);
351 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
353 /* close down the new tree */
361 test tree with ulogoff
362 this demonstrates that a tcon isn't autoclosed by a ulogoff
363 the tcon can be reused using any other valid session later
365 static bool test_tree_ulogoff(struct torture_context *tctx, struct smbcli_state *cli)
369 const char *share, *host;
370 struct smbcli_session *session1;
371 struct smbcli_session *session2;
372 struct smb_composite_sesssetup setup;
373 struct smbcli_tree *tree;
378 const char *fname1 = BASEDIR "\\test1.txt";
379 const char *fname2 = BASEDIR "\\test2.txt";
381 struct smbcli_session_options options;
383 torture_comment(tctx, "TESTING TREE with ulogoff\n");
385 if (!torture_setup_dir(cli, BASEDIR)) {
389 share = torture_setting_string(tctx, "share", NULL);
390 host = torture_setting_string(tctx, "host", NULL);
392 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
394 torture_comment(tctx, "create the first new sessions\n");
395 session1 = smbcli_session_init(cli->transport, tctx, false, options);
396 setup.in.sesskey = cli->transport->negotiate.sesskey;
397 setup.in.capabilities = cli->transport->negotiate.capabilities;
398 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
399 setup.in.credentials = cmdline_credentials;
400 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
401 status = smb_composite_sesssetup(session1, &setup);
402 CHECK_STATUS(status, NT_STATUS_OK);
403 session1->vuid = setup.out.vuid;
404 torture_comment(tctx, "vuid1=%d\n", session1->vuid);
406 torture_comment(tctx, "create a tree context on the with vuid1\n");
407 tree = smbcli_tree_init(session1, tctx, false);
408 tcon.generic.level = RAW_TCON_TCONX;
409 tcon.tconx.in.flags = 0;
410 tcon.tconx.in.password = data_blob(NULL, 0);
411 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
412 tcon.tconx.in.device = "A:";
413 status = smb_raw_tcon(tree, tctx, &tcon);
414 CHECK_STATUS(status, NT_STATUS_OK);
415 tree->tid = tcon.tconx.out.tid;
416 torture_comment(tctx, "tid=%d\n", tree->tid);
418 torture_comment(tctx, "create a file using vuid1\n");
419 io.generic.level = RAW_OPEN_NTCREATEX;
420 io.ntcreatex.in.root_fid.fnum = 0;
421 io.ntcreatex.in.flags = 0;
422 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
423 io.ntcreatex.in.create_options = 0;
424 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
425 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
426 io.ntcreatex.in.alloc_size = 0;
427 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
428 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
429 io.ntcreatex.in.security_flags = 0;
430 io.ntcreatex.in.fname = fname1;
431 status = smb_raw_open(tree, tctx, &io);
432 CHECK_STATUS(status, NT_STATUS_OK);
433 fnum1 = io.ntcreatex.out.file.fnum;
435 torture_comment(tctx, "write using vuid1\n");
436 wr.generic.level = RAW_WRITE_WRITEX;
437 wr.writex.in.file.fnum = fnum1;
438 wr.writex.in.offset = 0;
439 wr.writex.in.wmode = 0;
440 wr.writex.in.remaining = 0;
441 wr.writex.in.count = 1;
442 wr.writex.in.data = &c;
443 status = smb_raw_write(tree, &wr);
444 CHECK_STATUS(status, NT_STATUS_OK);
445 CHECK_VALUE(wr.writex.out.nwritten, 1);
447 torture_comment(tctx, "ulogoff the vuid1\n");
448 status = smb_raw_ulogoff(session1);
449 CHECK_STATUS(status, NT_STATUS_OK);
451 torture_comment(tctx, "create the second new sessions\n");
452 session2 = smbcli_session_init(cli->transport, tctx, false, options);
453 setup.in.sesskey = cli->transport->negotiate.sesskey;
454 setup.in.capabilities = cli->transport->negotiate.capabilities;
455 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
456 setup.in.credentials = cmdline_credentials;
457 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
458 status = smb_composite_sesssetup(session2, &setup);
459 CHECK_STATUS(status, NT_STATUS_OK);
460 session2->vuid = setup.out.vuid;
461 torture_comment(tctx, "vuid2=%d\n", session2->vuid);
463 torture_comment(tctx, "use the existing tree with vuid2\n");
464 tree->session = session2;
466 torture_comment(tctx, "create a file using vuid2\n");
467 io.generic.level = RAW_OPEN_NTCREATEX;
468 io.ntcreatex.in.root_fid.fnum = 0;
469 io.ntcreatex.in.flags = 0;
470 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
471 io.ntcreatex.in.create_options = 0;
472 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
473 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
474 io.ntcreatex.in.alloc_size = 0;
475 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
476 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
477 io.ntcreatex.in.security_flags = 0;
478 io.ntcreatex.in.fname = fname2;
479 status = smb_raw_open(tree, tctx, &io);
480 CHECK_STATUS(status, NT_STATUS_OK);
481 fnum2 = io.ntcreatex.out.file.fnum;
483 torture_comment(tctx, "write using vuid2\n");
484 wr.generic.level = RAW_WRITE_WRITEX;
485 wr.writex.in.file.fnum = fnum2;
486 wr.writex.in.offset = 0;
487 wr.writex.in.wmode = 0;
488 wr.writex.in.remaining = 0;
489 wr.writex.in.count = 1;
490 wr.writex.in.data = &c;
491 status = smb_raw_write(tree, &wr);
492 CHECK_STATUS(status, NT_STATUS_OK);
493 CHECK_VALUE(wr.writex.out.nwritten, 1);
495 torture_comment(tctx, "ulogoff the vuid2\n");
496 status = smb_raw_ulogoff(session2);
497 CHECK_STATUS(status, NT_STATUS_OK);
499 /* this also demonstrates that SMBtdis doesn't need a valid vuid */
500 torture_comment(tctx, "disconnect the existing tree connection\n");
501 status = smb_tree_disconnect(tree);
502 CHECK_STATUS(status, NT_STATUS_OK);
504 torture_comment(tctx, "disconnect the existing tree connection\n");
505 status = smb_tree_disconnect(tree);
506 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
508 /* close down the new tree */
517 this test demonstrates that exit() only sees the PID
518 used for the open() calls
520 static bool test_pid_exit_only_sees_open(struct torture_context *tctx,
521 struct smbcli_state *cli)
524 TALLOC_CTX *mem_ctx = tctx;
530 const char *fname = BASEDIR "\\test.txt";
534 torture_comment(tctx, "TESTING PID HANDLING exit() only cares about open() PID\n");
536 if (!torture_setup_dir(cli, BASEDIR)) {
540 pid1 = cli->session->pid;
543 torture_comment(tctx, "pid1=%d pid2=%d\n", pid1, pid2);
545 torture_comment(tctx, "create a file using pid1\n");
546 cli->session->pid = pid1;
547 io.generic.level = RAW_OPEN_NTCREATEX;
548 io.ntcreatex.in.root_fid.fnum = 0;
549 io.ntcreatex.in.flags = 0;
550 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
551 io.ntcreatex.in.create_options = 0;
552 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
553 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
554 io.ntcreatex.in.alloc_size = 0;
555 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
556 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
557 io.ntcreatex.in.security_flags = 0;
558 io.ntcreatex.in.fname = fname;
559 status = smb_raw_open(cli->tree, mem_ctx, &io);
560 CHECK_STATUS(status, NT_STATUS_OK);
561 fnum = io.ntcreatex.out.file.fnum;
563 torture_comment(tctx, "write using pid2\n");
564 cli->session->pid = pid2;
565 wr.generic.level = RAW_WRITE_WRITEX;
566 wr.writex.in.file.fnum = fnum;
567 wr.writex.in.offset = 0;
568 wr.writex.in.wmode = 0;
569 wr.writex.in.remaining = 0;
570 wr.writex.in.count = 1;
571 wr.writex.in.data = &c;
572 status = smb_raw_write(cli->tree, &wr);
573 CHECK_STATUS(status, NT_STATUS_OK);
574 CHECK_VALUE(wr.writex.out.nwritten, 1);
576 torture_comment(tctx, "exit pid2\n");
577 cli->session->pid = pid2;
578 status = smb_raw_exit(cli->session);
579 CHECK_STATUS(status, NT_STATUS_OK);
581 torture_comment(tctx, "the fnum should still be accessible via pid2\n");
582 cli->session->pid = pid2;
583 status = smb_raw_write(cli->tree, &wr);
584 CHECK_STATUS(status, NT_STATUS_OK);
585 CHECK_VALUE(wr.writex.out.nwritten, 1);
587 torture_comment(tctx, "exit pid2\n");
588 cli->session->pid = pid2;
589 status = smb_raw_exit(cli->session);
590 CHECK_STATUS(status, NT_STATUS_OK);
592 torture_comment(tctx, "the fnum should still be accessible via pid1 and pid2\n");
593 cli->session->pid = pid1;
594 status = smb_raw_write(cli->tree, &wr);
595 CHECK_STATUS(status, NT_STATUS_OK);
596 CHECK_VALUE(wr.writex.out.nwritten, 1);
597 cli->session->pid = pid2;
598 status = smb_raw_write(cli->tree, &wr);
599 CHECK_STATUS(status, NT_STATUS_OK);
600 CHECK_VALUE(wr.writex.out.nwritten, 1);
602 torture_comment(tctx, "exit pid1\n");
603 cli->session->pid = pid1;
604 status = smb_raw_exit(cli->session);
605 CHECK_STATUS(status, NT_STATUS_OK);
607 torture_comment(tctx, "the fnum should not now be accessible via pid1 or pid2\n");
608 cli->session->pid = pid1;
609 status = smb_raw_write(cli->tree, &wr);
610 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
611 cli->session->pid = pid2;
612 status = smb_raw_write(cli->tree, &wr);
613 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
615 torture_comment(tctx, "the fnum should have been auto-closed\n");
616 cli->session->pid = pid1;
617 cl.close.level = RAW_CLOSE_CLOSE;
618 cl.close.in.file.fnum = fnum;
619 cl.close.in.write_time = 0;
620 status = smb_raw_close(cli->tree, &cl);
621 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
628 test pid ops with 2 sessions
630 static bool test_pid_2sess(struct torture_context *tctx,
631 struct smbcli_state *cli)
635 struct smbcli_session *session;
636 struct smb_composite_sesssetup setup;
641 const char *fname = BASEDIR "\\test.txt";
643 uint16_t vuid1, vuid2;
644 struct smbcli_session_options options;
646 torture_comment(tctx, "TESTING PID HANDLING WITH 2 SESSIONS\n");
648 if (!torture_setup_dir(cli, BASEDIR)) {
652 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
654 torture_comment(tctx, "create a second security context on the same transport\n");
655 session = smbcli_session_init(cli->transport, tctx, false, options);
657 setup.in.sesskey = cli->transport->negotiate.sesskey;
658 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
659 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
660 setup.in.credentials = cmdline_credentials;
661 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
663 status = smb_composite_sesssetup(session, &setup);
664 CHECK_STATUS(status, NT_STATUS_OK);
665 session->vuid = setup.out.vuid;
667 vuid1 = cli->session->vuid;
668 vuid2 = session->vuid;
670 torture_comment(tctx, "vuid1=%d vuid2=%d\n", vuid1, vuid2);
672 torture_comment(tctx, "create a file using the vuid1\n");
673 cli->session->vuid = vuid1;
674 io.generic.level = RAW_OPEN_NTCREATEX;
675 io.ntcreatex.in.root_fid.fnum = 0;
676 io.ntcreatex.in.flags = 0;
677 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
678 io.ntcreatex.in.create_options = 0;
679 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
680 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
681 io.ntcreatex.in.alloc_size = 0;
682 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
683 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
684 io.ntcreatex.in.security_flags = 0;
685 io.ntcreatex.in.fname = fname;
686 status = smb_raw_open(cli->tree, tctx, &io);
687 CHECK_STATUS(status, NT_STATUS_OK);
688 fnum = io.ntcreatex.out.file.fnum;
690 torture_comment(tctx, "write using the vuid1 (fnum=%d)\n", fnum);
691 cli->session->vuid = vuid1;
692 wr.generic.level = RAW_WRITE_WRITEX;
693 wr.writex.in.file.fnum = fnum;
694 wr.writex.in.offset = 0;
695 wr.writex.in.wmode = 0;
696 wr.writex.in.remaining = 0;
697 wr.writex.in.count = 1;
698 wr.writex.in.data = &c;
700 status = smb_raw_write(cli->tree, &wr);
701 CHECK_STATUS(status, NT_STATUS_OK);
702 CHECK_VALUE(wr.writex.out.nwritten, 1);
704 torture_comment(tctx, "exit the pid with vuid2\n");
705 cli->session->vuid = vuid2;
706 status = smb_raw_exit(cli->session);
707 CHECK_STATUS(status, NT_STATUS_OK);
709 torture_comment(tctx, "the fnum should still be accessible\n");
710 cli->session->vuid = vuid1;
711 status = smb_raw_write(cli->tree, &wr);
712 CHECK_STATUS(status, NT_STATUS_OK);
713 CHECK_VALUE(wr.writex.out.nwritten, 1);
715 torture_comment(tctx, "exit the pid with vuid1\n");
716 cli->session->vuid = vuid1;
717 status = smb_raw_exit(cli->session);
718 CHECK_STATUS(status, NT_STATUS_OK);
720 torture_comment(tctx, "the fnum should not now be accessible\n");
721 status = smb_raw_write(cli->tree, &wr);
722 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
724 torture_comment(tctx, "the fnum should have been auto-closed\n");
725 cl.close.level = RAW_CLOSE_CLOSE;
726 cl.close.in.file.fnum = fnum;
727 cl.close.in.write_time = 0;
728 status = smb_raw_close(cli->tree, &cl);
729 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
736 test pid ops with 2 tcons
738 static bool test_pid_2tcon(struct torture_context *tctx,
739 struct smbcli_state *cli)
743 const char *share, *host;
744 struct smbcli_tree *tree;
750 const char *fname1 = BASEDIR "\\test1.txt";
751 const char *fname2 = BASEDIR "\\test2.txt";
755 torture_comment(tctx, "TESTING PID HANDLING WITH 2 TCONS\n");
757 if (!torture_setup_dir(cli, BASEDIR)) {
761 share = torture_setting_string(tctx, "share", NULL);
762 host = torture_setting_string(tctx, "host", NULL);
764 torture_comment(tctx, "create a second tree context on the same session\n");
765 tree = smbcli_tree_init(cli->session, tctx, false);
767 tcon.generic.level = RAW_TCON_TCONX;
768 tcon.tconx.in.flags = 0;
769 tcon.tconx.in.password = data_blob(NULL, 0);
770 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
771 tcon.tconx.in.device = "A:";
772 status = smb_raw_tcon(tree, tctx, &tcon);
773 CHECK_STATUS(status, NT_STATUS_OK);
775 tree->tid = tcon.tconx.out.tid;
777 tid1 = cli->tree->tid;
779 torture_comment(tctx, "tid1=%d tid2=%d\n", tid1, tid2);
781 torture_comment(tctx, "create a file using the tid1\n");
782 cli->tree->tid = tid1;
783 io.generic.level = RAW_OPEN_NTCREATEX;
784 io.ntcreatex.in.root_fid.fnum = 0;
785 io.ntcreatex.in.flags = 0;
786 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
787 io.ntcreatex.in.create_options = 0;
788 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
789 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
790 io.ntcreatex.in.alloc_size = 0;
791 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
792 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
793 io.ntcreatex.in.security_flags = 0;
794 io.ntcreatex.in.fname = fname1;
795 status = smb_raw_open(cli->tree, tctx, &io);
796 CHECK_STATUS(status, NT_STATUS_OK);
797 fnum1 = io.ntcreatex.out.file.fnum;
799 torture_comment(tctx, "write using the tid1\n");
800 wr.generic.level = RAW_WRITE_WRITEX;
801 wr.writex.in.file.fnum = fnum1;
802 wr.writex.in.offset = 0;
803 wr.writex.in.wmode = 0;
804 wr.writex.in.remaining = 0;
805 wr.writex.in.count = 1;
806 wr.writex.in.data = &c;
808 status = smb_raw_write(cli->tree, &wr);
809 CHECK_STATUS(status, NT_STATUS_OK);
810 CHECK_VALUE(wr.writex.out.nwritten, 1);
812 torture_comment(tctx, "create a file using the tid2\n");
813 cli->tree->tid = tid2;
814 io.generic.level = RAW_OPEN_NTCREATEX;
815 io.ntcreatex.in.root_fid.fnum = 0;
816 io.ntcreatex.in.flags = 0;
817 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
818 io.ntcreatex.in.create_options = 0;
819 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
820 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
821 io.ntcreatex.in.alloc_size = 0;
822 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
823 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
824 io.ntcreatex.in.security_flags = 0;
825 io.ntcreatex.in.fname = fname2;
826 status = smb_raw_open(cli->tree, tctx, &io);
827 CHECK_STATUS(status, NT_STATUS_OK);
828 fnum2 = io.ntcreatex.out.file.fnum;
830 torture_comment(tctx, "write using the tid2\n");
831 wr.generic.level = RAW_WRITE_WRITEX;
832 wr.writex.in.file.fnum = fnum2;
833 wr.writex.in.offset = 0;
834 wr.writex.in.wmode = 0;
835 wr.writex.in.remaining = 0;
836 wr.writex.in.count = 1;
837 wr.writex.in.data = &c;
839 status = smb_raw_write(cli->tree, &wr);
840 CHECK_STATUS(status, NT_STATUS_OK);
841 CHECK_VALUE(wr.writex.out.nwritten, 1);
843 torture_comment(tctx, "exit the pid\n");
844 status = smb_raw_exit(cli->session);
845 CHECK_STATUS(status, NT_STATUS_OK);
847 torture_comment(tctx, "the fnum1 on tid1 should not be accessible\n");
848 cli->tree->tid = tid1;
849 wr.writex.in.file.fnum = fnum1;
850 status = smb_raw_write(cli->tree, &wr);
851 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
853 torture_comment(tctx, "the fnum1 on tid1 should have been auto-closed\n");
854 cl.close.level = RAW_CLOSE_CLOSE;
855 cl.close.in.file.fnum = fnum1;
856 cl.close.in.write_time = 0;
857 status = smb_raw_close(cli->tree, &cl);
858 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
860 torture_comment(tctx, "the fnum2 on tid2 should not be accessible\n");
861 cli->tree->tid = tid2;
862 wr.writex.in.file.fnum = fnum2;
863 status = smb_raw_write(cli->tree, &wr);
864 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
866 torture_comment(tctx, "the fnum2 on tid2 should have been auto-closed\n");
867 cl.close.level = RAW_CLOSE_CLOSE;
868 cl.close.in.file.fnum = fnum2;
869 cl.close.in.write_time = 0;
870 status = smb_raw_close(cli->tree, &cl);
871 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
877 struct torture_suite *torture_raw_context(TALLOC_CTX *mem_ctx)
879 struct torture_suite *suite = torture_suite_create(mem_ctx, "context");
881 torture_suite_add_1smb_test(suite, "session1", test_session);
883 * TODO: add test_session with 'use spnego = false'
884 * torture_suite_add_1smb_test(suite, "session1", test_session);
886 torture_suite_add_1smb_test(suite, "tree", test_tree);
887 torture_suite_add_1smb_test(suite, "tree_ulogoff", test_tree_ulogoff);
888 torture_suite_add_1smb_test(suite, "pid_only_sess", test_pid_exit_only_sees_open);
889 torture_suite_add_1smb_test(suite, "pid_2sess", test_pid_2sess);
890 torture_suite_add_1smb_test(suite, "pid_2tcon", test_pid_2tcon);