s3-selftest: Remove some unnecessary comma
[Samba/gebeck_regimport.git] / source4 / torture / raw / context.c
blob45e7482057cd5d3d4656cb70f5a9f784fb1cea48
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 "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) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 printf("(%s) Incorrect status %s - should be %s\n", \
36 __location__, nt_errstr(status), nt_errstr(correct)); \
37 ret = false; \
38 goto done; \
39 }} while (0)
41 #define CHECK_VALUE(v, correct) do { \
42 if ((v) != (correct)) { \
43 printf("(%s) Incorrect value %s=%d - should be %d\n", \
44 __location__, #v, v, correct); \
45 ret = false; \
46 goto done; \
47 }} while (0)
49 #define CHECK_NOT_VALUE(v, correct) do { \
50 if ((v) == (correct)) { \
51 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
52 __location__, #v, v, correct); \
53 ret = false; \
54 goto done; \
55 }} while (0)
59 test session ops
61 static bool test_session(struct smbcli_state *cli, struct torture_context *tctx)
63 NTSTATUS status;
64 bool ret = true;
65 struct smbcli_session *session;
66 struct smbcli_session *session2;
67 struct smbcli_session *session3;
68 struct smbcli_session *session4;
69 struct cli_credentials *anon_creds;
70 struct smbcli_session *sessions[15];
71 struct composite_context *composite_contexts[15];
72 struct smbcli_tree *tree;
73 struct smb_composite_sesssetup setup;
74 struct smb_composite_sesssetup setups[15];
75 struct gensec_settings *gensec_settings;
76 union smb_open io;
77 union smb_write wr;
78 union smb_close cl;
79 int fnum;
80 const char *fname = BASEDIR "\\test.txt";
81 uint8_t c = 1;
82 int i;
83 struct smbcli_session_options options;
85 printf("TESTING SESSION HANDLING\n");
87 if (!torture_setup_dir(cli, BASEDIR)) {
88 return false;
91 printf("create a second security context on the same transport\n");
93 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
94 gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
96 session = smbcli_session_init(cli->transport, tctx, false, options);
98 setup.in.sesskey = cli->transport->negotiate.sesskey;
99 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
100 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
102 setup.in.credentials = cmdline_credentials;
103 setup.in.gensec_settings = gensec_settings;
105 status = smb_composite_sesssetup(session, &setup);
106 CHECK_STATUS(status, NT_STATUS_OK);
108 session->vuid = setup.out.vuid;
110 printf("create a third security context on the same transport, with vuid set\n");
111 session2 = smbcli_session_init(cli->transport, tctx, false, options);
113 session2->vuid = session->vuid;
114 setup.in.sesskey = cli->transport->negotiate.sesskey;
115 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
116 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
118 setup.in.credentials = cmdline_credentials;
120 status = smb_composite_sesssetup(session2, &setup);
121 CHECK_STATUS(status, NT_STATUS_OK);
123 session2->vuid = setup.out.vuid;
124 printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
126 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
127 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
128 if (session2->vuid == session->vuid) {
129 printf("server allows the user to re-use an existing vuid in session setup \n");
131 } else {
132 CHECK_NOT_VALUE(session2->vuid, session->vuid);
134 talloc_free(session2);
136 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
137 printf("create a fourth security context on the same transport, without extended security\n");
138 session3 = smbcli_session_init(cli->transport, tctx, false, options);
140 session3->vuid = session->vuid;
141 setup.in.sesskey = cli->transport->negotiate.sesskey;
142 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
143 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
145 setup.in.credentials = cmdline_credentials;
147 status = smb_composite_sesssetup(session3, &setup);
148 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
150 printf("create a fouth anonymous security context on the same transport, without extended security\n");
151 session4 = smbcli_session_init(cli->transport, tctx, false, options);
153 session4->vuid = session->vuid;
154 setup.in.sesskey = cli->transport->negotiate.sesskey;
155 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
156 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
158 anon_creds = cli_credentials_init(tctx);
159 cli_credentials_set_conf(anon_creds, tctx->lp_ctx);
160 cli_credentials_set_anonymous(anon_creds);
162 setup.in.credentials = anon_creds;
164 status = smb_composite_sesssetup(session3, &setup);
165 CHECK_STATUS(status, NT_STATUS_OK);
167 talloc_free(session4);
170 printf("use the same tree as the existing connection\n");
171 tree = smbcli_tree_init(session, tctx, false);
172 tree->tid = cli->tree->tid;
174 printf("create a file using the new vuid\n");
175 io.generic.level = RAW_OPEN_NTCREATEX;
176 io.ntcreatex.in.root_fid.fnum = 0;
177 io.ntcreatex.in.flags = 0;
178 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
179 io.ntcreatex.in.create_options = 0;
180 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
181 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
182 io.ntcreatex.in.alloc_size = 0;
183 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
184 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
185 io.ntcreatex.in.security_flags = 0;
186 io.ntcreatex.in.fname = fname;
187 status = smb_raw_open(tree, tctx, &io);
188 CHECK_STATUS(status, NT_STATUS_OK);
189 fnum = io.ntcreatex.out.file.fnum;
191 printf("write using the old vuid\n");
192 wr.generic.level = RAW_WRITE_WRITEX;
193 wr.writex.in.file.fnum = fnum;
194 wr.writex.in.offset = 0;
195 wr.writex.in.wmode = 0;
196 wr.writex.in.remaining = 0;
197 wr.writex.in.count = 1;
198 wr.writex.in.data = &c;
200 status = smb_raw_write(cli->tree, &wr);
201 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
203 printf("write with the new vuid\n");
204 status = smb_raw_write(tree, &wr);
205 CHECK_STATUS(status, NT_STATUS_OK);
206 CHECK_VALUE(wr.writex.out.nwritten, 1);
208 printf("logoff the new vuid\n");
209 status = smb_raw_ulogoff(session);
210 CHECK_STATUS(status, NT_STATUS_OK);
212 printf("the new vuid should not now be accessible\n");
213 status = smb_raw_write(tree, &wr);
214 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
216 printf("second logoff for the new vuid should fail\n");
217 status = smb_raw_ulogoff(session);
218 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
219 talloc_free(session);
221 printf("the fnum should have been auto-closed\n");
222 cl.close.level = RAW_CLOSE_CLOSE;
223 cl.close.in.file.fnum = fnum;
224 cl.close.in.write_time = 0;
225 status = smb_raw_close(cli->tree, &cl);
226 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
228 printf("create %d secondary security contexts on the same transport\n",
229 (int)ARRAY_SIZE(sessions));
230 for (i=0; i <ARRAY_SIZE(sessions); i++) {
231 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
232 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
233 setups[i].in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
235 setups[i].in.credentials = cmdline_credentials;
236 setups[i].in.gensec_settings = gensec_settings;
238 sessions[i] = smbcli_session_init(cli->transport, tctx, false, options);
239 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
244 printf("finishing %d secondary security contexts on the same transport\n",
245 (int)ARRAY_SIZE(sessions));
246 for (i=0; i< ARRAY_SIZE(sessions); i++) {
247 status = smb_composite_sesssetup_recv(composite_contexts[i]);
248 CHECK_STATUS(status, NT_STATUS_OK);
249 sessions[i]->vuid = setups[i].out.vuid;
250 printf("VUID: %d\n", sessions[i]->vuid);
251 status = smb_raw_ulogoff(sessions[i]);
252 CHECK_STATUS(status, NT_STATUS_OK);
256 talloc_free(tree);
258 done:
259 return ret;
264 test tree ops
266 static bool test_tree(struct smbcli_state *cli, struct torture_context *tctx)
268 NTSTATUS status;
269 bool ret = true;
270 const char *share, *host;
271 struct smbcli_tree *tree;
272 union smb_tcon tcon;
273 union smb_open io;
274 union smb_write wr;
275 union smb_close cl;
276 int fnum;
277 const char *fname = BASEDIR "\\test.txt";
278 uint8_t c = 1;
280 printf("TESTING TREE HANDLING\n");
282 if (!torture_setup_dir(cli, BASEDIR)) {
283 return false;
286 share = torture_setting_string(tctx, "share", NULL);
287 host = torture_setting_string(tctx, "host", NULL);
289 printf("create a second tree context on the same session\n");
290 tree = smbcli_tree_init(cli->session, tctx, false);
292 tcon.generic.level = RAW_TCON_TCONX;
293 tcon.tconx.in.flags = 0;
294 tcon.tconx.in.password = data_blob(NULL, 0);
295 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
296 tcon.tconx.in.device = "A:";
297 status = smb_raw_tcon(tree, tctx, &tcon);
298 CHECK_STATUS(status, NT_STATUS_OK);
301 tree->tid = tcon.tconx.out.tid;
302 printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
304 printf("try a tconx with a bad device type\n");
305 tcon.tconx.in.device = "FOO";
306 status = smb_raw_tcon(tree, tctx, &tcon);
307 CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
310 printf("create a file using the new tid\n");
311 io.generic.level = RAW_OPEN_NTCREATEX;
312 io.ntcreatex.in.root_fid.fnum = 0;
313 io.ntcreatex.in.flags = 0;
314 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
315 io.ntcreatex.in.create_options = 0;
316 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
317 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
318 io.ntcreatex.in.alloc_size = 0;
319 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
320 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
321 io.ntcreatex.in.security_flags = 0;
322 io.ntcreatex.in.fname = fname;
323 status = smb_raw_open(tree, tctx, &io);
324 CHECK_STATUS(status, NT_STATUS_OK);
325 fnum = io.ntcreatex.out.file.fnum;
327 printf("write using the old tid\n");
328 wr.generic.level = RAW_WRITE_WRITEX;
329 wr.writex.in.file.fnum = fnum;
330 wr.writex.in.offset = 0;
331 wr.writex.in.wmode = 0;
332 wr.writex.in.remaining = 0;
333 wr.writex.in.count = 1;
334 wr.writex.in.data = &c;
336 status = smb_raw_write(cli->tree, &wr);
337 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
339 printf("write with the new tid\n");
340 status = smb_raw_write(tree, &wr);
341 CHECK_STATUS(status, NT_STATUS_OK);
342 CHECK_VALUE(wr.writex.out.nwritten, 1);
344 printf("disconnect the new tid\n");
345 status = smb_tree_disconnect(tree);
346 CHECK_STATUS(status, NT_STATUS_OK);
348 printf("the new tid should not now be accessible\n");
349 status = smb_raw_write(tree, &wr);
350 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
352 printf("the fnum should have been auto-closed\n");
353 cl.close.level = RAW_CLOSE_CLOSE;
354 cl.close.in.file.fnum = fnum;
355 cl.close.in.write_time = 0;
356 status = smb_raw_close(cli->tree, &cl);
357 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
359 /* close down the new tree */
360 talloc_free(tree);
362 done:
363 return ret;
367 test tree with ulogoff
368 this demonstrates that a tcon isn't autoclosed by a ulogoff
369 the tcon can be reused using any other valid session later
371 static bool test_tree_ulogoff(struct smbcli_state *cli, struct torture_context *tctx)
373 NTSTATUS status;
374 bool ret = true;
375 const char *share, *host;
376 struct smbcli_session *session1;
377 struct smbcli_session *session2;
378 struct smb_composite_sesssetup setup;
379 struct smbcli_tree *tree;
380 union smb_tcon tcon;
381 union smb_open io;
382 union smb_write wr;
383 int fnum1, fnum2;
384 const char *fname1 = BASEDIR "\\test1.txt";
385 const char *fname2 = BASEDIR "\\test2.txt";
386 uint8_t c = 1;
387 struct smbcli_session_options options;
389 printf("TESTING TREE with ulogoff\n");
391 if (!torture_setup_dir(cli, BASEDIR)) {
392 return false;
395 share = torture_setting_string(tctx, "share", NULL);
396 host = torture_setting_string(tctx, "host", NULL);
398 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
400 printf("create the first new sessions\n");
401 session1 = smbcli_session_init(cli->transport, tctx, false, options);
402 setup.in.sesskey = cli->transport->negotiate.sesskey;
403 setup.in.capabilities = cli->transport->negotiate.capabilities;
404 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
405 setup.in.credentials = cmdline_credentials;
406 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
407 status = smb_composite_sesssetup(session1, &setup);
408 CHECK_STATUS(status, NT_STATUS_OK);
409 session1->vuid = setup.out.vuid;
410 printf("vuid1=%d\n", session1->vuid);
412 printf("create a tree context on the with vuid1\n");
413 tree = smbcli_tree_init(session1, tctx, false);
414 tcon.generic.level = RAW_TCON_TCONX;
415 tcon.tconx.in.flags = 0;
416 tcon.tconx.in.password = data_blob(NULL, 0);
417 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
418 tcon.tconx.in.device = "A:";
419 status = smb_raw_tcon(tree, tctx, &tcon);
420 CHECK_STATUS(status, NT_STATUS_OK);
421 tree->tid = tcon.tconx.out.tid;
422 printf("tid=%d\n", tree->tid);
424 printf("create a file using vuid1\n");
425 io.generic.level = RAW_OPEN_NTCREATEX;
426 io.ntcreatex.in.root_fid.fnum = 0;
427 io.ntcreatex.in.flags = 0;
428 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
429 io.ntcreatex.in.create_options = 0;
430 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
431 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
432 io.ntcreatex.in.alloc_size = 0;
433 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
434 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
435 io.ntcreatex.in.security_flags = 0;
436 io.ntcreatex.in.fname = fname1;
437 status = smb_raw_open(tree, tctx, &io);
438 CHECK_STATUS(status, NT_STATUS_OK);
439 fnum1 = io.ntcreatex.out.file.fnum;
441 printf("write using vuid1\n");
442 wr.generic.level = RAW_WRITE_WRITEX;
443 wr.writex.in.file.fnum = fnum1;
444 wr.writex.in.offset = 0;
445 wr.writex.in.wmode = 0;
446 wr.writex.in.remaining = 0;
447 wr.writex.in.count = 1;
448 wr.writex.in.data = &c;
449 status = smb_raw_write(tree, &wr);
450 CHECK_STATUS(status, NT_STATUS_OK);
451 CHECK_VALUE(wr.writex.out.nwritten, 1);
453 printf("ulogoff the vuid1\n");
454 status = smb_raw_ulogoff(session1);
455 CHECK_STATUS(status, NT_STATUS_OK);
457 printf("create the second new sessions\n");
458 session2 = smbcli_session_init(cli->transport, tctx, false, options);
459 setup.in.sesskey = cli->transport->negotiate.sesskey;
460 setup.in.capabilities = cli->transport->negotiate.capabilities;
461 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
462 setup.in.credentials = cmdline_credentials;
463 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
464 status = smb_composite_sesssetup(session2, &setup);
465 CHECK_STATUS(status, NT_STATUS_OK);
466 session2->vuid = setup.out.vuid;
467 printf("vuid2=%d\n", session2->vuid);
469 printf("use the existing tree with vuid2\n");
470 tree->session = session2;
472 printf("create a file using vuid2\n");
473 io.generic.level = RAW_OPEN_NTCREATEX;
474 io.ntcreatex.in.root_fid.fnum = 0;
475 io.ntcreatex.in.flags = 0;
476 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
477 io.ntcreatex.in.create_options = 0;
478 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
479 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
480 io.ntcreatex.in.alloc_size = 0;
481 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
482 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
483 io.ntcreatex.in.security_flags = 0;
484 io.ntcreatex.in.fname = fname2;
485 status = smb_raw_open(tree, tctx, &io);
486 CHECK_STATUS(status, NT_STATUS_OK);
487 fnum2 = io.ntcreatex.out.file.fnum;
489 printf("write using vuid2\n");
490 wr.generic.level = RAW_WRITE_WRITEX;
491 wr.writex.in.file.fnum = fnum2;
492 wr.writex.in.offset = 0;
493 wr.writex.in.wmode = 0;
494 wr.writex.in.remaining = 0;
495 wr.writex.in.count = 1;
496 wr.writex.in.data = &c;
497 status = smb_raw_write(tree, &wr);
498 CHECK_STATUS(status, NT_STATUS_OK);
499 CHECK_VALUE(wr.writex.out.nwritten, 1);
501 printf("ulogoff the vuid2\n");
502 status = smb_raw_ulogoff(session2);
503 CHECK_STATUS(status, NT_STATUS_OK);
505 /* this also demonstrates that SMBtdis doesn't need a valid vuid */
506 printf("disconnect the existing tree connection\n");
507 status = smb_tree_disconnect(tree);
508 CHECK_STATUS(status, NT_STATUS_OK);
510 printf("disconnect the existing tree connection\n");
511 status = smb_tree_disconnect(tree);
512 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
514 /* close down the new tree */
515 talloc_free(tree);
517 done:
518 return ret;
522 test pid ops
523 this test demonstrates that exit() only sees the PID
524 used for the open() calls
526 static bool test_pid_exit_only_sees_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
528 NTSTATUS status;
529 bool ret = true;
530 union smb_open io;
531 union smb_write wr;
532 union smb_close cl;
533 int fnum;
534 const char *fname = BASEDIR "\\test.txt";
535 uint8_t c = 1;
536 uint16_t pid1, pid2;
538 printf("TESTING PID HANDLING exit() only cares about open() PID\n");
540 if (!torture_setup_dir(cli, BASEDIR)) {
541 return false;
544 pid1 = cli->session->pid;
545 pid2 = pid1 + 1;
547 printf("pid1=%d pid2=%d\n", pid1, pid2);
549 printf("create a file using pid1\n");
550 cli->session->pid = pid1;
551 io.generic.level = RAW_OPEN_NTCREATEX;
552 io.ntcreatex.in.root_fid.fnum = 0;
553 io.ntcreatex.in.flags = 0;
554 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
555 io.ntcreatex.in.create_options = 0;
556 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
557 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
558 io.ntcreatex.in.alloc_size = 0;
559 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
560 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
561 io.ntcreatex.in.security_flags = 0;
562 io.ntcreatex.in.fname = fname;
563 status = smb_raw_open(cli->tree, mem_ctx, &io);
564 CHECK_STATUS(status, NT_STATUS_OK);
565 fnum = io.ntcreatex.out.file.fnum;
567 printf("write using pid2\n");
568 cli->session->pid = pid2;
569 wr.generic.level = RAW_WRITE_WRITEX;
570 wr.writex.in.file.fnum = fnum;
571 wr.writex.in.offset = 0;
572 wr.writex.in.wmode = 0;
573 wr.writex.in.remaining = 0;
574 wr.writex.in.count = 1;
575 wr.writex.in.data = &c;
576 status = smb_raw_write(cli->tree, &wr);
577 CHECK_STATUS(status, NT_STATUS_OK);
578 CHECK_VALUE(wr.writex.out.nwritten, 1);
580 printf("exit pid2\n");
581 cli->session->pid = pid2;
582 status = smb_raw_exit(cli->session);
583 CHECK_STATUS(status, NT_STATUS_OK);
585 printf("the fnum should still be accessible via pid2\n");
586 cli->session->pid = pid2;
587 status = smb_raw_write(cli->tree, &wr);
588 CHECK_STATUS(status, NT_STATUS_OK);
589 CHECK_VALUE(wr.writex.out.nwritten, 1);
591 printf("exit pid2\n");
592 cli->session->pid = pid2;
593 status = smb_raw_exit(cli->session);
594 CHECK_STATUS(status, NT_STATUS_OK);
596 printf("the fnum should still be accessible via pid1 and pid2\n");
597 cli->session->pid = pid1;
598 status = smb_raw_write(cli->tree, &wr);
599 CHECK_STATUS(status, NT_STATUS_OK);
600 CHECK_VALUE(wr.writex.out.nwritten, 1);
601 cli->session->pid = pid2;
602 status = smb_raw_write(cli->tree, &wr);
603 CHECK_STATUS(status, NT_STATUS_OK);
604 CHECK_VALUE(wr.writex.out.nwritten, 1);
606 printf("exit pid1\n");
607 cli->session->pid = pid1;
608 status = smb_raw_exit(cli->session);
609 CHECK_STATUS(status, NT_STATUS_OK);
611 printf("the fnum should not now be accessible via pid1 or pid2\n");
612 cli->session->pid = pid1;
613 status = smb_raw_write(cli->tree, &wr);
614 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
615 cli->session->pid = pid2;
616 status = smb_raw_write(cli->tree, &wr);
617 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
619 printf("the fnum should have been auto-closed\n");
620 cli->session->pid = pid1;
621 cl.close.level = RAW_CLOSE_CLOSE;
622 cl.close.in.file.fnum = fnum;
623 cl.close.in.write_time = 0;
624 status = smb_raw_close(cli->tree, &cl);
625 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
627 done:
628 return ret;
632 test pid ops with 2 sessions
634 static bool test_pid_2sess(struct smbcli_state *cli, struct torture_context *tctx)
636 NTSTATUS status;
637 bool ret = true;
638 struct smbcli_session *session;
639 struct smb_composite_sesssetup setup;
640 union smb_open io;
641 union smb_write wr;
642 union smb_close cl;
643 int fnum;
644 const char *fname = BASEDIR "\\test.txt";
645 uint8_t c = 1;
646 uint16_t vuid1, vuid2;
647 struct smbcli_session_options options;
649 printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
651 if (!torture_setup_dir(cli, BASEDIR)) {
652 return false;
655 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
657 printf("create a second security context on the same transport\n");
658 session = smbcli_session_init(cli->transport, tctx, false, options);
660 setup.in.sesskey = cli->transport->negotiate.sesskey;
661 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
662 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
663 setup.in.credentials = cmdline_credentials;
664 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
666 status = smb_composite_sesssetup(session, &setup);
667 CHECK_STATUS(status, NT_STATUS_OK);
668 session->vuid = setup.out.vuid;
670 vuid1 = cli->session->vuid;
671 vuid2 = session->vuid;
673 printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
675 printf("create a file using the vuid1\n");
676 cli->session->vuid = vuid1;
677 io.generic.level = RAW_OPEN_NTCREATEX;
678 io.ntcreatex.in.root_fid.fnum = 0;
679 io.ntcreatex.in.flags = 0;
680 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
681 io.ntcreatex.in.create_options = 0;
682 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
683 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
684 io.ntcreatex.in.alloc_size = 0;
685 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
686 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
687 io.ntcreatex.in.security_flags = 0;
688 io.ntcreatex.in.fname = fname;
689 status = smb_raw_open(cli->tree, tctx, &io);
690 CHECK_STATUS(status, NT_STATUS_OK);
691 fnum = io.ntcreatex.out.file.fnum;
693 printf("write using the vuid1 (fnum=%d)\n", fnum);
694 cli->session->vuid = vuid1;
695 wr.generic.level = RAW_WRITE_WRITEX;
696 wr.writex.in.file.fnum = fnum;
697 wr.writex.in.offset = 0;
698 wr.writex.in.wmode = 0;
699 wr.writex.in.remaining = 0;
700 wr.writex.in.count = 1;
701 wr.writex.in.data = &c;
703 status = smb_raw_write(cli->tree, &wr);
704 CHECK_STATUS(status, NT_STATUS_OK);
705 CHECK_VALUE(wr.writex.out.nwritten, 1);
707 printf("exit the pid with vuid2\n");
708 cli->session->vuid = vuid2;
709 status = smb_raw_exit(cli->session);
710 CHECK_STATUS(status, NT_STATUS_OK);
712 printf("the fnum should still be accessible\n");
713 cli->session->vuid = vuid1;
714 status = smb_raw_write(cli->tree, &wr);
715 CHECK_STATUS(status, NT_STATUS_OK);
716 CHECK_VALUE(wr.writex.out.nwritten, 1);
718 printf("exit the pid with vuid1\n");
719 cli->session->vuid = vuid1;
720 status = smb_raw_exit(cli->session);
721 CHECK_STATUS(status, NT_STATUS_OK);
723 printf("the fnum should not now be accessible\n");
724 status = smb_raw_write(cli->tree, &wr);
725 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
727 printf("the fnum should have been auto-closed\n");
728 cl.close.level = RAW_CLOSE_CLOSE;
729 cl.close.in.file.fnum = fnum;
730 cl.close.in.write_time = 0;
731 status = smb_raw_close(cli->tree, &cl);
732 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
734 done:
735 return ret;
739 test pid ops with 2 tcons
741 static bool test_pid_2tcon(struct smbcli_state *cli, struct torture_context *tctx)
743 NTSTATUS status;
744 bool ret = true;
745 const char *share, *host;
746 struct smbcli_tree *tree;
747 union smb_tcon tcon;
748 union smb_open io;
749 union smb_write wr;
750 union smb_close cl;
751 int fnum1, fnum2;
752 const char *fname1 = BASEDIR "\\test1.txt";
753 const char *fname2 = BASEDIR "\\test2.txt";
754 uint8_t c = 1;
755 uint16_t tid1, tid2;
757 printf("TESTING PID HANDLING WITH 2 TCONS\n");
759 if (!torture_setup_dir(cli, BASEDIR)) {
760 return false;
763 share = torture_setting_string(tctx, "share", NULL);
764 host = torture_setting_string(tctx, "host", NULL);
766 printf("create a second tree context on the same session\n");
767 tree = smbcli_tree_init(cli->session, tctx, false);
769 tcon.generic.level = RAW_TCON_TCONX;
770 tcon.tconx.in.flags = 0;
771 tcon.tconx.in.password = data_blob(NULL, 0);
772 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
773 tcon.tconx.in.device = "A:";
774 status = smb_raw_tcon(tree, tctx, &tcon);
775 CHECK_STATUS(status, NT_STATUS_OK);
777 tree->tid = tcon.tconx.out.tid;
779 tid1 = cli->tree->tid;
780 tid2 = tree->tid;
781 printf("tid1=%d tid2=%d\n", tid1, tid2);
783 printf("create a file using the tid1\n");
784 cli->tree->tid = tid1;
785 io.generic.level = RAW_OPEN_NTCREATEX;
786 io.ntcreatex.in.root_fid.fnum = 0;
787 io.ntcreatex.in.flags = 0;
788 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
789 io.ntcreatex.in.create_options = 0;
790 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
791 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
792 io.ntcreatex.in.alloc_size = 0;
793 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
794 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
795 io.ntcreatex.in.security_flags = 0;
796 io.ntcreatex.in.fname = fname1;
797 status = smb_raw_open(cli->tree, tctx, &io);
798 CHECK_STATUS(status, NT_STATUS_OK);
799 fnum1 = io.ntcreatex.out.file.fnum;
801 printf("write using the tid1\n");
802 wr.generic.level = RAW_WRITE_WRITEX;
803 wr.writex.in.file.fnum = fnum1;
804 wr.writex.in.offset = 0;
805 wr.writex.in.wmode = 0;
806 wr.writex.in.remaining = 0;
807 wr.writex.in.count = 1;
808 wr.writex.in.data = &c;
810 status = smb_raw_write(cli->tree, &wr);
811 CHECK_STATUS(status, NT_STATUS_OK);
812 CHECK_VALUE(wr.writex.out.nwritten, 1);
814 printf("create a file using the tid2\n");
815 cli->tree->tid = tid2;
816 io.generic.level = RAW_OPEN_NTCREATEX;
817 io.ntcreatex.in.root_fid.fnum = 0;
818 io.ntcreatex.in.flags = 0;
819 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
820 io.ntcreatex.in.create_options = 0;
821 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
822 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
823 io.ntcreatex.in.alloc_size = 0;
824 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
825 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
826 io.ntcreatex.in.security_flags = 0;
827 io.ntcreatex.in.fname = fname2;
828 status = smb_raw_open(cli->tree, tctx, &io);
829 CHECK_STATUS(status, NT_STATUS_OK);
830 fnum2 = io.ntcreatex.out.file.fnum;
832 printf("write using the tid2\n");
833 wr.generic.level = RAW_WRITE_WRITEX;
834 wr.writex.in.file.fnum = fnum2;
835 wr.writex.in.offset = 0;
836 wr.writex.in.wmode = 0;
837 wr.writex.in.remaining = 0;
838 wr.writex.in.count = 1;
839 wr.writex.in.data = &c;
841 status = smb_raw_write(cli->tree, &wr);
842 CHECK_STATUS(status, NT_STATUS_OK);
843 CHECK_VALUE(wr.writex.out.nwritten, 1);
845 printf("exit the pid\n");
846 status = smb_raw_exit(cli->session);
847 CHECK_STATUS(status, NT_STATUS_OK);
849 printf("the fnum1 on tid1 should not be accessible\n");
850 cli->tree->tid = tid1;
851 wr.writex.in.file.fnum = fnum1;
852 status = smb_raw_write(cli->tree, &wr);
853 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
855 printf("the fnum1 on tid1 should have been auto-closed\n");
856 cl.close.level = RAW_CLOSE_CLOSE;
857 cl.close.in.file.fnum = fnum1;
858 cl.close.in.write_time = 0;
859 status = smb_raw_close(cli->tree, &cl);
860 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
862 printf("the fnum2 on tid2 should not be accessible\n");
863 cli->tree->tid = tid2;
864 wr.writex.in.file.fnum = fnum2;
865 status = smb_raw_write(cli->tree, &wr);
866 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
868 printf("the fnum2 on tid2 should have been auto-closed\n");
869 cl.close.level = RAW_CLOSE_CLOSE;
870 cl.close.in.file.fnum = fnum2;
871 cl.close.in.write_time = 0;
872 status = smb_raw_close(cli->tree, &cl);
873 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
875 done:
876 return ret;
881 basic testing of session/tree context calls
883 static bool torture_raw_context_int(struct torture_context *tctx,
884 struct smbcli_state *cli)
886 bool ret = true;
888 ret &= test_session(cli, tctx);
889 ret &= test_tree(cli, tctx);
890 ret &= test_tree_ulogoff(cli, tctx);
891 ret &= test_pid_exit_only_sees_open(cli, tctx);
892 ret &= test_pid_2sess(cli, tctx);
893 ret &= test_pid_2tcon(cli, tctx);
895 smb_raw_exit(cli->session);
896 smbcli_deltree(cli->tree, BASEDIR);
898 return ret;
901 basic testing of session/tree context calls
903 bool torture_raw_context(struct torture_context *torture,
904 struct smbcli_state *cli)
906 bool ret = true;
907 if (lpcfg_use_spnego(torture->lp_ctx)) {
908 ret &= torture_raw_context_int(torture, cli);
909 lpcfg_set_cmdline(torture->lp_ctx, "use spnego", "False");
912 ret &= torture_raw_context_int(torture, cli);
914 return ret;