s4:torture/raw: make torture_raw_context a test suite
[Samba/gebeck_regimport.git] / source4 / torture / raw / context.c
blob45300cf249bc0ecdd36066d289ff09db3ba22a41
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 smbcli_state *cli, struct torture_context *tctx)
50 NTSTATUS status;
51 bool ret = true;
52 struct smbcli_session *session;
53 struct smbcli_session *session2;
54 struct smbcli_session *session3;
55 struct smbcli_session *session4;
56 struct cli_credentials *anon_creds;
57 struct smbcli_session *sessions[15];
58 struct composite_context *composite_contexts[15];
59 struct smbcli_tree *tree;
60 struct smb_composite_sesssetup setup;
61 struct smb_composite_sesssetup setups[15];
62 struct gensec_settings *gensec_settings;
63 union smb_open io;
64 union smb_write wr;
65 union smb_close cl;
66 int fnum;
67 const char *fname = BASEDIR "\\test.txt";
68 uint8_t c = 1;
69 int i;
70 struct smbcli_session_options options;
72 torture_comment(tctx, "TESTING SESSION HANDLING\n");
74 if (!torture_setup_dir(cli, BASEDIR)) {
75 return false;
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 = 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 vuid set\n");
98 session2 = smbcli_session_init(cli->transport, tctx, false, options);
100 session2->vuid = session->vuid;
101 setup.in.sesskey = cli->transport->negotiate.sesskey;
102 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
103 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
105 setup.in.credentials = cmdline_credentials;
107 status = smb_composite_sesssetup(session2, &setup);
108 CHECK_STATUS(status, NT_STATUS_OK);
110 session2->vuid = setup.out.vuid;
111 torture_comment(tctx, "vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
113 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
114 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
115 if (session2->vuid == session->vuid) {
116 torture_comment(tctx, "server allows the user to re-use an existing vuid in session setup \n");
118 } else {
119 CHECK_NOT_VALUE(session2->vuid, session->vuid);
121 talloc_free(session2);
123 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
124 torture_comment(tctx, "create a fourth security context on the same transport, without extended security\n");
125 session3 = smbcli_session_init(cli->transport, tctx, false, options);
127 session3->vuid = session->vuid;
128 setup.in.sesskey = cli->transport->negotiate.sesskey;
129 setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
130 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
132 setup.in.credentials = cmdline_credentials;
134 status = smb_composite_sesssetup(session3, &setup);
135 CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
137 torture_comment(tctx, "create a fouth anonymous security context on the same transport, without extended security\n");
138 session4 = smbcli_session_init(cli->transport, tctx, false, options);
140 session4->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 anon_creds = cli_credentials_init(tctx);
146 cli_credentials_set_conf(anon_creds, tctx->lp_ctx);
147 cli_credentials_set_anonymous(anon_creds);
149 setup.in.credentials = anon_creds;
151 status = smb_composite_sesssetup(session3, &setup);
152 CHECK_STATUS(status, NT_STATUS_OK);
154 talloc_free(session4);
157 torture_comment(tctx, "use the same tree as the existing connection\n");
158 tree = smbcli_tree_init(session, tctx, false);
159 tree->tid = cli->tree->tid;
161 torture_comment(tctx, "create a file using the new vuid\n");
162 io.generic.level = RAW_OPEN_NTCREATEX;
163 io.ntcreatex.in.root_fid.fnum = 0;
164 io.ntcreatex.in.flags = 0;
165 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
166 io.ntcreatex.in.create_options = 0;
167 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
168 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
169 io.ntcreatex.in.alloc_size = 0;
170 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
171 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
172 io.ntcreatex.in.security_flags = 0;
173 io.ntcreatex.in.fname = fname;
174 status = smb_raw_open(tree, tctx, &io);
175 CHECK_STATUS(status, NT_STATUS_OK);
176 fnum = io.ntcreatex.out.file.fnum;
178 torture_comment(tctx, "write using the old vuid\n");
179 wr.generic.level = RAW_WRITE_WRITEX;
180 wr.writex.in.file.fnum = fnum;
181 wr.writex.in.offset = 0;
182 wr.writex.in.wmode = 0;
183 wr.writex.in.remaining = 0;
184 wr.writex.in.count = 1;
185 wr.writex.in.data = &c;
187 status = smb_raw_write(cli->tree, &wr);
188 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
190 torture_comment(tctx, "write with the new vuid\n");
191 status = smb_raw_write(tree, &wr);
192 CHECK_STATUS(status, NT_STATUS_OK);
193 CHECK_VALUE(wr.writex.out.nwritten, 1);
195 torture_comment(tctx, "logoff the new vuid\n");
196 status = smb_raw_ulogoff(session);
197 CHECK_STATUS(status, NT_STATUS_OK);
199 torture_comment(tctx, "the new vuid should not now be accessible\n");
200 status = smb_raw_write(tree, &wr);
201 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
203 torture_comment(tctx, "second logoff for the new vuid should fail\n");
204 status = smb_raw_ulogoff(session);
205 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
206 talloc_free(session);
208 torture_comment(tctx, "the fnum should have been auto-closed\n");
209 cl.close.level = RAW_CLOSE_CLOSE;
210 cl.close.in.file.fnum = fnum;
211 cl.close.in.write_time = 0;
212 status = smb_raw_close(cli->tree, &cl);
213 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
215 torture_comment(tctx, "create %d secondary security contexts on the same transport\n",
216 (int)ARRAY_SIZE(sessions));
217 for (i=0; i <ARRAY_SIZE(sessions); i++) {
218 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
219 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
220 setups[i].in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
222 setups[i].in.credentials = cmdline_credentials;
223 setups[i].in.gensec_settings = gensec_settings;
225 sessions[i] = smbcli_session_init(cli->transport, tctx, false, options);
226 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
231 torture_comment(tctx, "finishing %d secondary security contexts on the same transport\n",
232 (int)ARRAY_SIZE(sessions));
233 for (i=0; i< ARRAY_SIZE(sessions); i++) {
234 status = smb_composite_sesssetup_recv(composite_contexts[i]);
235 CHECK_STATUS(status, NT_STATUS_OK);
236 sessions[i]->vuid = setups[i].out.vuid;
237 torture_comment(tctx, "VUID: %d\n", sessions[i]->vuid);
238 status = smb_raw_ulogoff(sessions[i]);
239 CHECK_STATUS(status, NT_STATUS_OK);
243 talloc_free(tree);
245 done:
246 return ret;
251 test tree ops
253 static bool test_tree(struct smbcli_state *cli, struct torture_context *tctx)
255 NTSTATUS status;
256 bool ret = true;
257 const char *share, *host;
258 struct smbcli_tree *tree;
259 union smb_tcon tcon;
260 union smb_open io;
261 union smb_write wr;
262 union smb_close cl;
263 int fnum;
264 const char *fname = BASEDIR "\\test.txt";
265 uint8_t c = 1;
267 torture_comment(tctx, "TESTING TREE HANDLING\n");
269 if (!torture_setup_dir(cli, BASEDIR)) {
270 return false;
273 share = torture_setting_string(tctx, "share", NULL);
274 host = torture_setting_string(tctx, "host", NULL);
276 torture_comment(tctx, "create a second tree context on the same session\n");
277 tree = smbcli_tree_init(cli->session, tctx, false);
279 tcon.generic.level = RAW_TCON_TCONX;
280 tcon.tconx.in.flags = 0;
281 tcon.tconx.in.password = data_blob(NULL, 0);
282 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
283 tcon.tconx.in.device = "A:";
284 status = smb_raw_tcon(tree, tctx, &tcon);
285 CHECK_STATUS(status, NT_STATUS_OK);
288 tree->tid = tcon.tconx.out.tid;
289 torture_comment(tctx, "tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
291 torture_comment(tctx, "try a tconx with a bad device type\n");
292 tcon.tconx.in.device = "FOO";
293 status = smb_raw_tcon(tree, tctx, &tcon);
294 CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
297 torture_comment(tctx, "create a file using the new tid\n");
298 io.generic.level = RAW_OPEN_NTCREATEX;
299 io.ntcreatex.in.root_fid.fnum = 0;
300 io.ntcreatex.in.flags = 0;
301 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
302 io.ntcreatex.in.create_options = 0;
303 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
304 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
305 io.ntcreatex.in.alloc_size = 0;
306 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
307 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
308 io.ntcreatex.in.security_flags = 0;
309 io.ntcreatex.in.fname = fname;
310 status = smb_raw_open(tree, tctx, &io);
311 CHECK_STATUS(status, NT_STATUS_OK);
312 fnum = io.ntcreatex.out.file.fnum;
314 torture_comment(tctx, "write using the old tid\n");
315 wr.generic.level = RAW_WRITE_WRITEX;
316 wr.writex.in.file.fnum = fnum;
317 wr.writex.in.offset = 0;
318 wr.writex.in.wmode = 0;
319 wr.writex.in.remaining = 0;
320 wr.writex.in.count = 1;
321 wr.writex.in.data = &c;
323 status = smb_raw_write(cli->tree, &wr);
324 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
326 torture_comment(tctx, "write with the new tid\n");
327 status = smb_raw_write(tree, &wr);
328 CHECK_STATUS(status, NT_STATUS_OK);
329 CHECK_VALUE(wr.writex.out.nwritten, 1);
331 torture_comment(tctx, "disconnect the new tid\n");
332 status = smb_tree_disconnect(tree);
333 CHECK_STATUS(status, NT_STATUS_OK);
335 torture_comment(tctx, "the new tid should not now be accessible\n");
336 status = smb_raw_write(tree, &wr);
337 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
339 torture_comment(tctx, "the fnum should have been auto-closed\n");
340 cl.close.level = RAW_CLOSE_CLOSE;
341 cl.close.in.file.fnum = fnum;
342 cl.close.in.write_time = 0;
343 status = smb_raw_close(cli->tree, &cl);
344 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
346 /* close down the new tree */
347 talloc_free(tree);
349 done:
350 return ret;
354 test tree with ulogoff
355 this demonstrates that a tcon isn't autoclosed by a ulogoff
356 the tcon can be reused using any other valid session later
358 static bool test_tree_ulogoff(struct smbcli_state *cli, struct torture_context *tctx)
360 NTSTATUS status;
361 bool ret = true;
362 const char *share, *host;
363 struct smbcli_session *session1;
364 struct smbcli_session *session2;
365 struct smb_composite_sesssetup setup;
366 struct smbcli_tree *tree;
367 union smb_tcon tcon;
368 union smb_open io;
369 union smb_write wr;
370 int fnum1, fnum2;
371 const char *fname1 = BASEDIR "\\test1.txt";
372 const char *fname2 = BASEDIR "\\test2.txt";
373 uint8_t c = 1;
374 struct smbcli_session_options options;
376 torture_comment(tctx, "TESTING TREE with ulogoff\n");
378 if (!torture_setup_dir(cli, BASEDIR)) {
379 return false;
382 share = torture_setting_string(tctx, "share", NULL);
383 host = torture_setting_string(tctx, "host", NULL);
385 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
387 torture_comment(tctx, "create the first new sessions\n");
388 session1 = smbcli_session_init(cli->transport, tctx, false, options);
389 setup.in.sesskey = cli->transport->negotiate.sesskey;
390 setup.in.capabilities = cli->transport->negotiate.capabilities;
391 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
392 setup.in.credentials = cmdline_credentials;
393 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
394 status = smb_composite_sesssetup(session1, &setup);
395 CHECK_STATUS(status, NT_STATUS_OK);
396 session1->vuid = setup.out.vuid;
397 torture_comment(tctx, "vuid1=%d\n", session1->vuid);
399 torture_comment(tctx, "create a tree context on the with vuid1\n");
400 tree = smbcli_tree_init(session1, tctx, false);
401 tcon.generic.level = RAW_TCON_TCONX;
402 tcon.tconx.in.flags = 0;
403 tcon.tconx.in.password = data_blob(NULL, 0);
404 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
405 tcon.tconx.in.device = "A:";
406 status = smb_raw_tcon(tree, tctx, &tcon);
407 CHECK_STATUS(status, NT_STATUS_OK);
408 tree->tid = tcon.tconx.out.tid;
409 torture_comment(tctx, "tid=%d\n", tree->tid);
411 torture_comment(tctx, "create a file using vuid1\n");
412 io.generic.level = RAW_OPEN_NTCREATEX;
413 io.ntcreatex.in.root_fid.fnum = 0;
414 io.ntcreatex.in.flags = 0;
415 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
416 io.ntcreatex.in.create_options = 0;
417 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
418 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
419 io.ntcreatex.in.alloc_size = 0;
420 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
421 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
422 io.ntcreatex.in.security_flags = 0;
423 io.ntcreatex.in.fname = fname1;
424 status = smb_raw_open(tree, tctx, &io);
425 CHECK_STATUS(status, NT_STATUS_OK);
426 fnum1 = io.ntcreatex.out.file.fnum;
428 torture_comment(tctx, "write using vuid1\n");
429 wr.generic.level = RAW_WRITE_WRITEX;
430 wr.writex.in.file.fnum = fnum1;
431 wr.writex.in.offset = 0;
432 wr.writex.in.wmode = 0;
433 wr.writex.in.remaining = 0;
434 wr.writex.in.count = 1;
435 wr.writex.in.data = &c;
436 status = smb_raw_write(tree, &wr);
437 CHECK_STATUS(status, NT_STATUS_OK);
438 CHECK_VALUE(wr.writex.out.nwritten, 1);
440 torture_comment(tctx, "ulogoff the vuid1\n");
441 status = smb_raw_ulogoff(session1);
442 CHECK_STATUS(status, NT_STATUS_OK);
444 torture_comment(tctx, "create the second new sessions\n");
445 session2 = smbcli_session_init(cli->transport, tctx, false, options);
446 setup.in.sesskey = cli->transport->negotiate.sesskey;
447 setup.in.capabilities = cli->transport->negotiate.capabilities;
448 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
449 setup.in.credentials = cmdline_credentials;
450 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
451 status = smb_composite_sesssetup(session2, &setup);
452 CHECK_STATUS(status, NT_STATUS_OK);
453 session2->vuid = setup.out.vuid;
454 torture_comment(tctx, "vuid2=%d\n", session2->vuid);
456 torture_comment(tctx, "use the existing tree with vuid2\n");
457 tree->session = session2;
459 torture_comment(tctx, "create a file using vuid2\n");
460 io.generic.level = RAW_OPEN_NTCREATEX;
461 io.ntcreatex.in.root_fid.fnum = 0;
462 io.ntcreatex.in.flags = 0;
463 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
464 io.ntcreatex.in.create_options = 0;
465 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
466 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
467 io.ntcreatex.in.alloc_size = 0;
468 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
469 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
470 io.ntcreatex.in.security_flags = 0;
471 io.ntcreatex.in.fname = fname2;
472 status = smb_raw_open(tree, tctx, &io);
473 CHECK_STATUS(status, NT_STATUS_OK);
474 fnum2 = io.ntcreatex.out.file.fnum;
476 torture_comment(tctx, "write using vuid2\n");
477 wr.generic.level = RAW_WRITE_WRITEX;
478 wr.writex.in.file.fnum = fnum2;
479 wr.writex.in.offset = 0;
480 wr.writex.in.wmode = 0;
481 wr.writex.in.remaining = 0;
482 wr.writex.in.count = 1;
483 wr.writex.in.data = &c;
484 status = smb_raw_write(tree, &wr);
485 CHECK_STATUS(status, NT_STATUS_OK);
486 CHECK_VALUE(wr.writex.out.nwritten, 1);
488 torture_comment(tctx, "ulogoff the vuid2\n");
489 status = smb_raw_ulogoff(session2);
490 CHECK_STATUS(status, NT_STATUS_OK);
492 /* this also demonstrates that SMBtdis doesn't need a valid vuid */
493 torture_comment(tctx, "disconnect the existing tree connection\n");
494 status = smb_tree_disconnect(tree);
495 CHECK_STATUS(status, NT_STATUS_OK);
497 torture_comment(tctx, "disconnect the existing tree connection\n");
498 status = smb_tree_disconnect(tree);
499 CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
501 /* close down the new tree */
502 talloc_free(tree);
504 done:
505 return ret;
509 test pid ops
510 this test demonstrates that exit() only sees the PID
511 used for the open() calls
513 static bool test_pid_exit_only_sees_open(struct smbcli_state *cli,
514 struct torture_context *tctx)
516 NTSTATUS status;
517 TALLOC_CTX *mem_ctx = tctx;
518 bool ret = true;
519 union smb_open io;
520 union smb_write wr;
521 union smb_close cl;
522 int fnum;
523 const char *fname = BASEDIR "\\test.txt";
524 uint8_t c = 1;
525 uint16_t pid1, pid2;
527 torture_comment(tctx, "TESTING PID HANDLING exit() only cares about open() PID\n");
529 if (!torture_setup_dir(cli, BASEDIR)) {
530 return false;
533 pid1 = cli->session->pid;
534 pid2 = pid1 + 1;
536 torture_comment(tctx, "pid1=%d pid2=%d\n", pid1, pid2);
538 torture_comment(tctx, "create a file using pid1\n");
539 cli->session->pid = pid1;
540 io.generic.level = RAW_OPEN_NTCREATEX;
541 io.ntcreatex.in.root_fid.fnum = 0;
542 io.ntcreatex.in.flags = 0;
543 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
544 io.ntcreatex.in.create_options = 0;
545 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
546 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
547 io.ntcreatex.in.alloc_size = 0;
548 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
549 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
550 io.ntcreatex.in.security_flags = 0;
551 io.ntcreatex.in.fname = fname;
552 status = smb_raw_open(cli->tree, mem_ctx, &io);
553 CHECK_STATUS(status, NT_STATUS_OK);
554 fnum = io.ntcreatex.out.file.fnum;
556 torture_comment(tctx, "write using pid2\n");
557 cli->session->pid = pid2;
558 wr.generic.level = RAW_WRITE_WRITEX;
559 wr.writex.in.file.fnum = fnum;
560 wr.writex.in.offset = 0;
561 wr.writex.in.wmode = 0;
562 wr.writex.in.remaining = 0;
563 wr.writex.in.count = 1;
564 wr.writex.in.data = &c;
565 status = smb_raw_write(cli->tree, &wr);
566 CHECK_STATUS(status, NT_STATUS_OK);
567 CHECK_VALUE(wr.writex.out.nwritten, 1);
569 torture_comment(tctx, "exit pid2\n");
570 cli->session->pid = pid2;
571 status = smb_raw_exit(cli->session);
572 CHECK_STATUS(status, NT_STATUS_OK);
574 torture_comment(tctx, "the fnum should still be accessible via pid2\n");
575 cli->session->pid = pid2;
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 pid1 and pid2\n");
586 cli->session->pid = pid1;
587 status = smb_raw_write(cli->tree, &wr);
588 CHECK_STATUS(status, NT_STATUS_OK);
589 CHECK_VALUE(wr.writex.out.nwritten, 1);
590 cli->session->pid = pid2;
591 status = smb_raw_write(cli->tree, &wr);
592 CHECK_STATUS(status, NT_STATUS_OK);
593 CHECK_VALUE(wr.writex.out.nwritten, 1);
595 torture_comment(tctx, "exit pid1\n");
596 cli->session->pid = pid1;
597 status = smb_raw_exit(cli->session);
598 CHECK_STATUS(status, NT_STATUS_OK);
600 torture_comment(tctx, "the fnum should not now be accessible via pid1 or pid2\n");
601 cli->session->pid = pid1;
602 status = smb_raw_write(cli->tree, &wr);
603 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
604 cli->session->pid = pid2;
605 status = smb_raw_write(cli->tree, &wr);
606 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
608 torture_comment(tctx, "the fnum should have been auto-closed\n");
609 cli->session->pid = pid1;
610 cl.close.level = RAW_CLOSE_CLOSE;
611 cl.close.in.file.fnum = fnum;
612 cl.close.in.write_time = 0;
613 status = smb_raw_close(cli->tree, &cl);
614 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
616 done:
617 return ret;
621 test pid ops with 2 sessions
623 static bool test_pid_2sess(struct smbcli_state *cli, struct torture_context *tctx)
625 NTSTATUS status;
626 bool ret = true;
627 struct smbcli_session *session;
628 struct smb_composite_sesssetup setup;
629 union smb_open io;
630 union smb_write wr;
631 union smb_close cl;
632 int fnum;
633 const char *fname = BASEDIR "\\test.txt";
634 uint8_t c = 1;
635 uint16_t vuid1, vuid2;
636 struct smbcli_session_options options;
638 torture_comment(tctx, "TESTING PID HANDLING WITH 2 SESSIONS\n");
640 if (!torture_setup_dir(cli, BASEDIR)) {
641 return false;
644 lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
646 torture_comment(tctx, "create a second security context on the same transport\n");
647 session = smbcli_session_init(cli->transport, tctx, false, options);
649 setup.in.sesskey = cli->transport->negotiate.sesskey;
650 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
651 setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
652 setup.in.credentials = cmdline_credentials;
653 setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
655 status = smb_composite_sesssetup(session, &setup);
656 CHECK_STATUS(status, NT_STATUS_OK);
657 session->vuid = setup.out.vuid;
659 vuid1 = cli->session->vuid;
660 vuid2 = session->vuid;
662 torture_comment(tctx, "vuid1=%d vuid2=%d\n", vuid1, vuid2);
664 torture_comment(tctx, "create a file using the vuid1\n");
665 cli->session->vuid = vuid1;
666 io.generic.level = RAW_OPEN_NTCREATEX;
667 io.ntcreatex.in.root_fid.fnum = 0;
668 io.ntcreatex.in.flags = 0;
669 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
670 io.ntcreatex.in.create_options = 0;
671 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
672 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
673 io.ntcreatex.in.alloc_size = 0;
674 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
675 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
676 io.ntcreatex.in.security_flags = 0;
677 io.ntcreatex.in.fname = fname;
678 status = smb_raw_open(cli->tree, tctx, &io);
679 CHECK_STATUS(status, NT_STATUS_OK);
680 fnum = io.ntcreatex.out.file.fnum;
682 torture_comment(tctx, "write using the vuid1 (fnum=%d)\n", fnum);
683 cli->session->vuid = vuid1;
684 wr.generic.level = RAW_WRITE_WRITEX;
685 wr.writex.in.file.fnum = fnum;
686 wr.writex.in.offset = 0;
687 wr.writex.in.wmode = 0;
688 wr.writex.in.remaining = 0;
689 wr.writex.in.count = 1;
690 wr.writex.in.data = &c;
692 status = smb_raw_write(cli->tree, &wr);
693 CHECK_STATUS(status, NT_STATUS_OK);
694 CHECK_VALUE(wr.writex.out.nwritten, 1);
696 torture_comment(tctx, "exit the pid with vuid2\n");
697 cli->session->vuid = vuid2;
698 status = smb_raw_exit(cli->session);
699 CHECK_STATUS(status, NT_STATUS_OK);
701 torture_comment(tctx, "the fnum should still be accessible\n");
702 cli->session->vuid = vuid1;
703 status = smb_raw_write(cli->tree, &wr);
704 CHECK_STATUS(status, NT_STATUS_OK);
705 CHECK_VALUE(wr.writex.out.nwritten, 1);
707 torture_comment(tctx, "exit the pid with vuid1\n");
708 cli->session->vuid = vuid1;
709 status = smb_raw_exit(cli->session);
710 CHECK_STATUS(status, NT_STATUS_OK);
712 torture_comment(tctx, "the fnum should not now be accessible\n");
713 status = smb_raw_write(cli->tree, &wr);
714 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
716 torture_comment(tctx, "the fnum should have been auto-closed\n");
717 cl.close.level = RAW_CLOSE_CLOSE;
718 cl.close.in.file.fnum = fnum;
719 cl.close.in.write_time = 0;
720 status = smb_raw_close(cli->tree, &cl);
721 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
723 done:
724 return ret;
728 test pid ops with 2 tcons
730 static bool test_pid_2tcon(struct smbcli_state *cli, struct torture_context *tctx)
732 NTSTATUS status;
733 bool ret = true;
734 const char *share, *host;
735 struct smbcli_tree *tree;
736 union smb_tcon tcon;
737 union smb_open io;
738 union smb_write wr;
739 union smb_close cl;
740 int fnum1, fnum2;
741 const char *fname1 = BASEDIR "\\test1.txt";
742 const char *fname2 = BASEDIR "\\test2.txt";
743 uint8_t c = 1;
744 uint16_t tid1, tid2;
746 torture_comment(tctx, "TESTING PID HANDLING WITH 2 TCONS\n");
748 if (!torture_setup_dir(cli, BASEDIR)) {
749 return false;
752 share = torture_setting_string(tctx, "share", NULL);
753 host = torture_setting_string(tctx, "host", NULL);
755 torture_comment(tctx, "create a second tree context on the same session\n");
756 tree = smbcli_tree_init(cli->session, tctx, false);
758 tcon.generic.level = RAW_TCON_TCONX;
759 tcon.tconx.in.flags = 0;
760 tcon.tconx.in.password = data_blob(NULL, 0);
761 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
762 tcon.tconx.in.device = "A:";
763 status = smb_raw_tcon(tree, tctx, &tcon);
764 CHECK_STATUS(status, NT_STATUS_OK);
766 tree->tid = tcon.tconx.out.tid;
768 tid1 = cli->tree->tid;
769 tid2 = tree->tid;
770 torture_comment(tctx, "tid1=%d tid2=%d\n", tid1, tid2);
772 torture_comment(tctx, "create a file using the tid1\n");
773 cli->tree->tid = tid1;
774 io.generic.level = RAW_OPEN_NTCREATEX;
775 io.ntcreatex.in.root_fid.fnum = 0;
776 io.ntcreatex.in.flags = 0;
777 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
778 io.ntcreatex.in.create_options = 0;
779 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
780 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
781 io.ntcreatex.in.alloc_size = 0;
782 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
783 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
784 io.ntcreatex.in.security_flags = 0;
785 io.ntcreatex.in.fname = fname1;
786 status = smb_raw_open(cli->tree, tctx, &io);
787 CHECK_STATUS(status, NT_STATUS_OK);
788 fnum1 = io.ntcreatex.out.file.fnum;
790 torture_comment(tctx, "write using the tid1\n");
791 wr.generic.level = RAW_WRITE_WRITEX;
792 wr.writex.in.file.fnum = fnum1;
793 wr.writex.in.offset = 0;
794 wr.writex.in.wmode = 0;
795 wr.writex.in.remaining = 0;
796 wr.writex.in.count = 1;
797 wr.writex.in.data = &c;
799 status = smb_raw_write(cli->tree, &wr);
800 CHECK_STATUS(status, NT_STATUS_OK);
801 CHECK_VALUE(wr.writex.out.nwritten, 1);
803 torture_comment(tctx, "create a file using the tid2\n");
804 cli->tree->tid = tid2;
805 io.generic.level = RAW_OPEN_NTCREATEX;
806 io.ntcreatex.in.root_fid.fnum = 0;
807 io.ntcreatex.in.flags = 0;
808 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
809 io.ntcreatex.in.create_options = 0;
810 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
811 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
812 io.ntcreatex.in.alloc_size = 0;
813 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
814 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
815 io.ntcreatex.in.security_flags = 0;
816 io.ntcreatex.in.fname = fname2;
817 status = smb_raw_open(cli->tree, tctx, &io);
818 CHECK_STATUS(status, NT_STATUS_OK);
819 fnum2 = io.ntcreatex.out.file.fnum;
821 torture_comment(tctx, "write using the tid2\n");
822 wr.generic.level = RAW_WRITE_WRITEX;
823 wr.writex.in.file.fnum = fnum2;
824 wr.writex.in.offset = 0;
825 wr.writex.in.wmode = 0;
826 wr.writex.in.remaining = 0;
827 wr.writex.in.count = 1;
828 wr.writex.in.data = &c;
830 status = smb_raw_write(cli->tree, &wr);
831 CHECK_STATUS(status, NT_STATUS_OK);
832 CHECK_VALUE(wr.writex.out.nwritten, 1);
834 torture_comment(tctx, "exit the pid\n");
835 status = smb_raw_exit(cli->session);
836 CHECK_STATUS(status, NT_STATUS_OK);
838 torture_comment(tctx, "the fnum1 on tid1 should not be accessible\n");
839 cli->tree->tid = tid1;
840 wr.writex.in.file.fnum = fnum1;
841 status = smb_raw_write(cli->tree, &wr);
842 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
844 torture_comment(tctx, "the fnum1 on tid1 should have been auto-closed\n");
845 cl.close.level = RAW_CLOSE_CLOSE;
846 cl.close.in.file.fnum = fnum1;
847 cl.close.in.write_time = 0;
848 status = smb_raw_close(cli->tree, &cl);
849 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
851 torture_comment(tctx, "the fnum2 on tid2 should not be accessible\n");
852 cli->tree->tid = tid2;
853 wr.writex.in.file.fnum = fnum2;
854 status = smb_raw_write(cli->tree, &wr);
855 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
857 torture_comment(tctx, "the fnum2 on tid2 should have been auto-closed\n");
858 cl.close.level = RAW_CLOSE_CLOSE;
859 cl.close.in.file.fnum = fnum2;
860 cl.close.in.write_time = 0;
861 status = smb_raw_close(cli->tree, &cl);
862 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
864 done:
865 return ret;
870 basic testing of session/tree context calls
872 static bool torture_raw_context_int(struct torture_context *tctx,
873 struct smbcli_state *cli)
875 bool ret = true;
877 ret &= test_session(cli, tctx);
878 ret &= test_tree(cli, tctx);
879 ret &= test_tree_ulogoff(cli, tctx);
880 ret &= test_pid_exit_only_sees_open(cli, tctx);
881 ret &= test_pid_2sess(cli, tctx);
882 ret &= test_pid_2tcon(cli, tctx);
884 smb_raw_exit(cli->session);
885 smbcli_deltree(cli->tree, BASEDIR);
887 return ret;
890 basic testing of session/tree context calls
892 static bool torture_raw_context_all(struct torture_context *torture,
893 struct smbcli_state *cli)
895 bool ret = true;
896 if (lpcfg_use_spnego(torture->lp_ctx)) {
897 ret &= torture_raw_context_int(torture, cli);
898 lpcfg_set_cmdline(torture->lp_ctx, "use spnego", "False");
901 ret &= torture_raw_context_int(torture, cli);
903 return ret;
906 struct torture_suite *torture_raw_context(TALLOC_CTX *mem_ctx)
908 struct torture_suite *suite = torture_suite_create(mem_ctx, "context");
910 torture_suite_add_1smb_test(suite, "all", torture_raw_context_all);
912 return suite;