s3:pylibsmb: Add ipc=True support for CLI_FULL_CONNECTION_IPC
[Samba.git] / source4 / torture / raw / context.c
blob8c3a7675047dcd1cde0e00f41fdcc4d20308650a
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) \
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));
46 test session ops
48 static bool test_session(struct torture_context *tctx,
49 struct smbcli_state *cli)
51 NTSTATUS status;
52 bool ret = true;
53 struct smbcli_session *session;
54 struct smbcli_session *session2;
55 uint16_t vuid3;
56 struct smbcli_session *session3;
57 struct smbcli_session *session4;
58 struct cli_credentials *anon_creds;
59 struct smbcli_session *sessions[15];
60 struct composite_context *composite_contexts[15];
61 struct smbcli_tree *tree;
62 struct smb_composite_sesssetup setup;
63 struct smb_composite_sesssetup setups[15];
64 struct gensec_settings *gensec_settings;
65 union smb_open io;
66 union smb_write wr;
67 union smb_close cl;
68 int fnum;
69 const char *fname = BASEDIR "\\test.txt";
70 uint8_t c = 1;
71 int i;
72 struct smbcli_session_options options;
74 torture_comment(tctx, "TESTING SESSION HANDLING\n");
76 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
78 torture_comment(tctx, "create a second security context on the same transport\n");
80 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
81 gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
83 session = smbcli_session_init(cli->transport, tctx, false, options);
85 setup.in.sesskey = cli->transport->negotiate.sesskey;
86 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
87 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
89 setup.in.credentials = popt_get_cmdline_credentials();
90 setup.in.gensec_settings = gensec_settings;
92 status = smb_composite_sesssetup(session, &setup);
93 CHECK_STATUS(status, NT_STATUS_OK);
95 session->vuid = setup.out.vuid;
97 torture_comment(tctx, "create a third security context on the same transport, with given vuid\n");
98 session2 = smbcli_session_init(cli->transport, tctx, false, options);
100 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
101 vuid3 = session->vuid+1;
102 if (vuid3 == cli->session->vuid) {
103 vuid3 += 1;
105 if (vuid3 == UINT16_MAX) {
106 vuid3 += 2;
108 } else {
109 vuid3 = session->vuid;
111 session2->vuid = vuid3;
113 setup.in.sesskey = cli->transport->negotiate.sesskey;
114 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
115 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
117 setup.in.credentials = popt_get_cmdline_credentials();
119 torture_comment(tctx, "vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, vuid3);
121 status = smb_composite_sesssetup(session2, &setup);
122 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
123 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
124 } else {
125 CHECK_STATUS(status, NT_STATUS_OK);
126 session2->vuid = setup.out.vuid;
127 CHECK_NOT_VALUE(session2->vuid, vuid3);
130 torture_comment(tctx, "vuid1=%d vuid2=%d vuid3=%d=>%d (%s)\n",
131 cli->session->vuid, session->vuid,
132 vuid3, session2->vuid, nt_errstr(status));
134 talloc_free(session2);
136 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
137 torture_comment(tctx, "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 = vuid3;
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 = popt_get_cmdline_credentials();
147 status = smb_composite_sesssetup(session3, &setup);
148 if (!NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)) {
150 * Windows 2008 R2 returns INVALID_PARAMETER
151 * while Windows 2000 sp4 returns LOGON_FAILURE...
153 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
156 torture_comment(tctx, "create a fouth anonymous security context on the same transport, without extended security\n");
157 session4 = smbcli_session_init(cli->transport, tctx, false, options);
159 session4->vuid = vuid3;
160 setup.in.sesskey = cli->transport->negotiate.sesskey;
161 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
162 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
164 anon_creds = cli_credentials_init(tctx);
165 cli_credentials_set_conf(anon_creds, tctx->lp_ctx);
166 cli_credentials_set_anonymous(anon_creds);
168 setup.in.credentials = anon_creds;
170 status = smb_composite_sesssetup(session3, &setup);
171 CHECK_STATUS(status, NT_STATUS_OK);
173 talloc_free(session4);
176 torture_comment(tctx, "use the same tree as the existing connection\n");
177 tree = smbcli_tree_init(session, tctx, false);
178 tree->tid = cli->tree->tid;
180 torture_comment(tctx, "create a file using the new vuid\n");
181 io.generic.level = RAW_OPEN_NTCREATEX;
182 io.ntcreatex.in.root_fid.fnum = 0;
183 io.ntcreatex.in.flags = 0;
184 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
185 io.ntcreatex.in.create_options = 0;
186 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
187 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
188 io.ntcreatex.in.alloc_size = 0;
189 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
190 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
191 io.ntcreatex.in.security_flags = 0;
192 io.ntcreatex.in.fname = fname;
193 status = smb_raw_open(tree, tctx, &io);
194 CHECK_STATUS(status, NT_STATUS_OK);
195 fnum = io.ntcreatex.out.file.fnum;
197 torture_comment(tctx, "write using the old vuid\n");
198 wr.generic.level = RAW_WRITE_WRITEX;
199 wr.writex.in.file.fnum = fnum;
200 wr.writex.in.offset = 0;
201 wr.writex.in.wmode = 0;
202 wr.writex.in.remaining = 0;
203 wr.writex.in.count = 1;
204 wr.writex.in.data = &c;
206 status = smb_raw_write(cli->tree, &wr);
207 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
209 torture_comment(tctx, "write with the new vuid\n");
210 status = smb_raw_write(tree, &wr);
211 CHECK_STATUS(status, NT_STATUS_OK);
212 CHECK_VALUE(wr.writex.out.nwritten, 1);
214 torture_comment(tctx, "logoff the new vuid\n");
215 status = smb_raw_ulogoff(session);
216 CHECK_STATUS(status, NT_STATUS_OK);
218 torture_comment(tctx, "the new vuid should not now be accessible\n");
219 status = smb_raw_write(tree, &wr);
220 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
222 torture_comment(tctx, "second logoff for the new vuid should fail\n");
223 status = smb_raw_ulogoff(session);
224 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
225 talloc_free(tree);
226 talloc_free(session);
228 torture_comment(tctx, "the fnum should have been auto-closed\n");
229 cl.close.level = RAW_CLOSE_CLOSE;
230 cl.close.in.file.fnum = fnum;
231 cl.close.in.write_time = 0;
232 status = smb_raw_close(cli->tree, &cl);
233 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
235 torture_comment(tctx, "create %d secondary security contexts on the same transport\n",
236 (int)ARRAY_SIZE(sessions));
237 for (i=0; i <ARRAY_SIZE(sessions); i++) {
238 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
239 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
240 setups[i].in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
242 setups[i].in.credentials = popt_get_cmdline_credentials();
243 setups[i].in.gensec_settings = gensec_settings;
245 sessions[i] = smbcli_session_init(cli->transport, tctx, false, options);
246 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
251 torture_comment(tctx, "finishing %d secondary security contexts on the same transport\n",
252 (int)ARRAY_SIZE(sessions));
253 for (i=0; i< ARRAY_SIZE(sessions); i++) {
254 status = smb_composite_sesssetup_recv(composite_contexts[i]);
255 CHECK_STATUS(status, NT_STATUS_OK);
256 sessions[i]->vuid = setups[i].out.vuid;
257 torture_comment(tctx, "VUID: %d\n", sessions[i]->vuid);
258 status = smb_raw_ulogoff(sessions[i]);
259 CHECK_STATUS(status, NT_STATUS_OK);
262 done:
263 return ret;
268 test tree ops
270 static bool test_tree(struct torture_context *tctx, struct smbcli_state *cli)
272 NTSTATUS status;
273 bool ret = true;
274 const char *share, *host;
275 struct smbcli_tree *tree;
276 union smb_tcon tcon;
277 union smb_open io;
278 union smb_write wr;
279 union smb_close cl;
280 int fnum;
281 const char *fname = BASEDIR "\\test.txt";
282 uint8_t c = 1;
284 torture_comment(tctx, "TESTING TREE HANDLING\n");
286 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
288 share = torture_setting_string(tctx, "share", NULL);
289 host = torture_setting_string(tctx, "host", NULL);
291 torture_comment(tctx, "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 = TCONX_FLAG_EXTENDED_RESPONSE;
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 torture_comment(tctx, "tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
306 torture_comment(tctx, "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 torture_comment(tctx, "create a file using the new tid\n");
313 io.generic.level = RAW_OPEN_NTCREATEX;
314 io.ntcreatex.in.root_fid.fnum = 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 torture_comment(tctx, "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 torture_comment(tctx, "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 torture_comment(tctx, "disconnect the new tid\n");
347 status = smb_tree_disconnect(tree);
348 CHECK_STATUS(status, NT_STATUS_OK);
350 torture_comment(tctx, "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 torture_comment(tctx, "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 torture_context *tctx, struct smbcli_state *cli)
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 torture_comment(tctx, "TESTING TREE with ulogoff\n");
393 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
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 torture_comment(tctx, "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 = popt_get_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 torture_comment(tctx, "vuid1=%d\n", session1->vuid);
412 torture_comment(tctx, "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 = TCONX_FLAG_EXTENDED_RESPONSE;
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 torture_comment(tctx, "tid=%d\n", tree->tid);
424 torture_comment(tctx, "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 torture_comment(tctx, "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 torture_comment(tctx, "ulogoff the vuid1\n");
454 status = smb_raw_ulogoff(session1);
455 CHECK_STATUS(status, NT_STATUS_OK);
457 torture_comment(tctx, "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 = popt_get_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 torture_comment(tctx, "vuid2=%d\n", session2->vuid);
469 torture_comment(tctx, "use the existing tree with vuid2\n");
470 tree->session = session2;
472 torture_comment(tctx, "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 torture_comment(tctx, "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 torture_comment(tctx, "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 torture_comment(tctx, "disconnect the existing tree connection\n");
507 status = smb_tree_disconnect(tree);
508 CHECK_STATUS(status, NT_STATUS_OK);
510 torture_comment(tctx, "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 torture_context *tctx,
527 struct smbcli_state *cli)
529 NTSTATUS status;
530 TALLOC_CTX *mem_ctx = tctx;
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 torture_comment(tctx, "TESTING PID HANDLING exit() only cares about open() PID\n");
542 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
544 pid1 = cli->session->pid;
545 pid2 = pid1 + 1;
547 torture_comment(tctx, "pid1=%d pid2=%d\n", pid1, pid2);
549 torture_comment(tctx, "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 torture_comment(tctx, "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 torture_comment(tctx, "exit pid2\n");
581 cli->session->pid = pid2;
582 status = smb_raw_exit(cli->session);
583 CHECK_STATUS(status, NT_STATUS_OK);
585 torture_comment(tctx, "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 torture_comment(tctx, "exit pid2\n");
592 cli->session->pid = pid2;
593 status = smb_raw_exit(cli->session);
594 CHECK_STATUS(status, NT_STATUS_OK);
596 torture_comment(tctx, "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 torture_comment(tctx, "exit pid1\n");
607 cli->session->pid = pid1;
608 status = smb_raw_exit(cli->session);
609 CHECK_STATUS(status, NT_STATUS_OK);
611 torture_comment(tctx, "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 torture_comment(tctx, "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 torture_context *tctx,
635 struct smbcli_state *cli)
637 NTSTATUS status;
638 bool ret = true;
639 struct smbcli_session *session;
640 struct smb_composite_sesssetup setup;
641 union smb_open io;
642 union smb_write wr;
643 union smb_close cl;
644 int fnum;
645 const char *fname = BASEDIR "\\test.txt";
646 uint8_t c = 1;
647 uint16_t vuid1, vuid2;
648 struct smbcli_session_options options;
650 torture_comment(tctx, "TESTING PID HANDLING WITH 2 SESSIONS\n");
652 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
654 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
656 torture_comment(tctx, "create a second security context on the same transport\n");
657 session = smbcli_session_init(cli->transport, tctx, false, options);
659 setup.in.sesskey = cli->transport->negotiate.sesskey;
660 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
661 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
662 setup.in.credentials = popt_get_cmdline_credentials();
663 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
665 status = smb_composite_sesssetup(session, &setup);
666 CHECK_STATUS(status, NT_STATUS_OK);
667 session->vuid = setup.out.vuid;
669 vuid1 = cli->session->vuid;
670 vuid2 = session->vuid;
672 torture_comment(tctx, "vuid1=%d vuid2=%d\n", vuid1, vuid2);
674 torture_comment(tctx, "create a file using the vuid1\n");
675 cli->session->vuid = vuid1;
676 io.generic.level = RAW_OPEN_NTCREATEX;
677 io.ntcreatex.in.root_fid.fnum = 0;
678 io.ntcreatex.in.flags = 0;
679 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
680 io.ntcreatex.in.create_options = 0;
681 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
682 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
683 io.ntcreatex.in.alloc_size = 0;
684 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
685 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
686 io.ntcreatex.in.security_flags = 0;
687 io.ntcreatex.in.fname = fname;
688 status = smb_raw_open(cli->tree, tctx, &io);
689 CHECK_STATUS(status, NT_STATUS_OK);
690 fnum = io.ntcreatex.out.file.fnum;
692 torture_comment(tctx, "write using the vuid1 (fnum=%d)\n", fnum);
693 cli->session->vuid = vuid1;
694 wr.generic.level = RAW_WRITE_WRITEX;
695 wr.writex.in.file.fnum = fnum;
696 wr.writex.in.offset = 0;
697 wr.writex.in.wmode = 0;
698 wr.writex.in.remaining = 0;
699 wr.writex.in.count = 1;
700 wr.writex.in.data = &c;
702 status = smb_raw_write(cli->tree, &wr);
703 CHECK_STATUS(status, NT_STATUS_OK);
704 CHECK_VALUE(wr.writex.out.nwritten, 1);
706 torture_comment(tctx, "exit the pid with vuid2\n");
707 cli->session->vuid = vuid2;
708 status = smb_raw_exit(cli->session);
709 CHECK_STATUS(status, NT_STATUS_OK);
711 torture_comment(tctx, "the fnum should still be accessible\n");
712 cli->session->vuid = vuid1;
713 status = smb_raw_write(cli->tree, &wr);
714 CHECK_STATUS(status, NT_STATUS_OK);
715 CHECK_VALUE(wr.writex.out.nwritten, 1);
717 torture_comment(tctx, "exit the pid with vuid1\n");
718 cli->session->vuid = vuid1;
719 status = smb_raw_exit(cli->session);
720 CHECK_STATUS(status, NT_STATUS_OK);
722 torture_comment(tctx, "the fnum should not now be accessible\n");
723 status = smb_raw_write(cli->tree, &wr);
724 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
726 torture_comment(tctx, "the fnum should have been auto-closed\n");
727 cl.close.level = RAW_CLOSE_CLOSE;
728 cl.close.in.file.fnum = fnum;
729 cl.close.in.write_time = 0;
730 status = smb_raw_close(cli->tree, &cl);
731 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
733 done:
734 return ret;
738 test pid ops with 2 tcons
740 static bool test_pid_2tcon(struct torture_context *tctx,
741 struct smbcli_state *cli)
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 torture_comment(tctx, "TESTING PID HANDLING WITH 2 TCONS\n");
759 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " 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 = TCONX_FLAG_EXTENDED_RESPONSE;
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;
778 tid2 = 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);
873 done:
874 return ret;
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);
892 return suite;