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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libcli/raw/libcliraw.h"
23 #include "librpc/gen_ndr/ndr_security.h"
24 #include "libcli/composite/composite.h"
25 #include "lib/cmdline/popt_common.h"
26 #include "lib/events/events.h"
28 #define BASEDIR "\\rawcontext"
30 #define CHECK_STATUS(status, correct) do { \
31 if (!NT_STATUS_EQUAL(status, correct)) { \
32 printf("(%s) Incorrect status %s - should be %s\n", \
33 __location__, nt_errstr(status), nt_errstr(correct)); \
38 #define CHECK_VALUE(v, correct) do { \
39 if ((v) != (correct)) { \
40 printf("(%s) Incorrect value %s=%d - should be %d\n", \
41 __location__, #v, v, correct); \
46 #define CHECK_NOT_VALUE(v, correct) do { \
47 if ((v) == (correct)) { \
48 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
49 __location__, #v, v, correct); \
58 static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
62 struct smbcli_session *session;
63 struct smbcli_session *session2;
64 struct smbcli_session *session3;
65 struct smbcli_session *sessions[15];
66 struct composite_context *composite_contexts[15];
67 struct smbcli_tree *tree;
68 struct smb_composite_sesssetup setup;
69 struct smb_composite_sesssetup setups[15];
74 const char *fname = BASEDIR "\\test.txt";
78 printf("TESTING SESSION HANDLING\n");
80 if (!torture_setup_dir(cli, BASEDIR)) {
84 printf("create a second security context on the same transport\n");
85 session = smbcli_session_init(cli->transport, mem_ctx, False);
87 setup.in.sesskey = cli->transport->negotiate.sesskey;
88 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
89 setup.in.workgroup = lp_workgroup();
91 setup.in.credentials = cmdline_credentials;
93 status = smb_composite_sesssetup(session, &setup);
94 CHECK_STATUS(status, NT_STATUS_OK);
96 session->vuid = setup.out.vuid;
98 printf("create a third security context on the same transport, with vuid set\n");
99 session2 = smbcli_session_init(cli->transport, mem_ctx, False);
101 session2->vuid = session->vuid;
102 setup.in.sesskey = cli->transport->negotiate.sesskey;
103 setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
104 setup.in.workgroup = lp_workgroup();
106 setup.in.credentials = cmdline_credentials;
108 status = smb_composite_sesssetup(session2, &setup);
109 CHECK_STATUS(status, NT_STATUS_OK);
111 session2->vuid = setup.out.vuid;
112 printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
114 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
115 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
116 CHECK_VALUE(session2->vuid, session->vuid);
118 CHECK_NOT_VALUE(session2->vuid, session->vuid);
120 talloc_free(session2);
122 if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
123 printf("create a fourth security context on the same transport, without extended security\n");
124 session3 = smbcli_session_init(cli->transport, mem_ctx, False);
126 session3->vuid = session->vuid;
127 setup.in.sesskey = cli->transport->negotiate.sesskey;
128 setup.in.capabilities = 0; /* force a non extended security login (should fail) */
129 setup.in.workgroup = lp_workgroup();
131 setup.in.credentials = cmdline_credentials;
134 status = smb_composite_sesssetup(session3, &setup);
135 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
137 talloc_free(session3);
140 printf("use the same tree as the existing connection\n");
141 tree = smbcli_tree_init(session, mem_ctx, False);
142 tree->tid = cli->tree->tid;
144 printf("create a file using the new vuid\n");
145 io.generic.level = RAW_OPEN_NTCREATEX;
146 io.ntcreatex.in.root_fid = 0;
147 io.ntcreatex.in.flags = 0;
148 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
149 io.ntcreatex.in.create_options = 0;
150 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
151 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
152 io.ntcreatex.in.alloc_size = 0;
153 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
154 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
155 io.ntcreatex.in.security_flags = 0;
156 io.ntcreatex.in.fname = fname;
157 status = smb_raw_open(tree, mem_ctx, &io);
158 CHECK_STATUS(status, NT_STATUS_OK);
159 fnum = io.ntcreatex.out.fnum;
161 printf("write using the old vuid\n");
162 wr.generic.level = RAW_WRITE_WRITEX;
163 wr.writex.in.fnum = fnum;
164 wr.writex.in.offset = 0;
165 wr.writex.in.wmode = 0;
166 wr.writex.in.remaining = 0;
167 wr.writex.in.count = 1;
168 wr.writex.in.data = &c;
170 status = smb_raw_write(cli->tree, &wr);
171 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
173 printf("write with the new vuid\n");
174 status = smb_raw_write(tree, &wr);
175 CHECK_STATUS(status, NT_STATUS_OK);
176 CHECK_VALUE(wr.writex.out.nwritten, 1);
178 printf("logoff the new vuid\n");
179 status = smb_raw_ulogoff(session);
180 CHECK_STATUS(status, NT_STATUS_OK);
182 printf("the new vuid should not now be accessible\n");
183 status = smb_raw_write(tree, &wr);
184 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
186 printf("second logoff for the new vuid should fail\n");
187 status = smb_raw_ulogoff(session);
188 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
189 talloc_free(session);
191 printf("the fnum should have been auto-closed\n");
192 cl.close.level = RAW_CLOSE_CLOSE;
193 cl.close.in.fnum = fnum;
194 cl.close.in.write_time = 0;
195 status = smb_raw_close(cli->tree, &cl);
196 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
198 printf("create %d secondary security contexts on the same transport\n",
199 ARRAY_SIZE(sessions));
200 for (i=0; i <ARRAY_SIZE(sessions); i++) {
201 setups[i].in.sesskey = cli->transport->negotiate.sesskey;
202 setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
203 setups[i].in.workgroup = lp_workgroup();
205 setups[i].in.credentials = cmdline_credentials;
207 sessions[i] = smbcli_session_init(cli->transport, mem_ctx, False);
208 composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
213 /* flush the queue */
214 for (i=0; i < ARRAY_SIZE(sessions); i++) {
215 event_loop_once(composite_contexts[0]->event_ctx);
218 printf("finishing %d secondary security contexts on the same transport\n",
219 ARRAY_SIZE(sessions));
220 for (i=0; i< ARRAY_SIZE(sessions); i++) {
221 status = smb_composite_sesssetup_recv(composite_contexts[i]);
222 CHECK_STATUS(status, NT_STATUS_OK);
223 sessions[i]->vuid = setups[i].out.vuid;
224 printf("VUID: %d\n", sessions[i]->vuid);
225 status = smb_raw_ulogoff(sessions[i]);
226 CHECK_STATUS(status, NT_STATUS_OK);
240 static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
245 struct smbcli_tree *tree;
251 const char *fname = BASEDIR "\\test.txt";
254 printf("TESTING TREE HANDLING\n");
256 if (!torture_setup_dir(cli, BASEDIR)) {
260 share = lp_parm_string(-1, "torture", "share");
262 printf("create a second tree context on the same session\n");
263 tree = smbcli_tree_init(cli->session, mem_ctx, False);
265 tcon.generic.level = RAW_TCON_TCONX;
266 tcon.tconx.in.flags = 0;
267 tcon.tconx.in.password = data_blob(NULL, 0);
268 tcon.tconx.in.path = share;
269 tcon.tconx.in.device = "A:";
270 status = smb_tree_connect(tree, mem_ctx, &tcon);
271 CHECK_STATUS(status, NT_STATUS_OK);
273 tree->tid = tcon.tconx.out.tid;
274 printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
276 printf("try a tconx with a bad device type\n");
277 tcon.tconx.in.device = "FOO";
278 status = smb_tree_connect(tree, mem_ctx, &tcon);
279 CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
282 printf("create a file using the new tid\n");
283 io.generic.level = RAW_OPEN_NTCREATEX;
284 io.ntcreatex.in.root_fid = 0;
285 io.ntcreatex.in.flags = 0;
286 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
287 io.ntcreatex.in.create_options = 0;
288 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
289 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
290 io.ntcreatex.in.alloc_size = 0;
291 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
292 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
293 io.ntcreatex.in.security_flags = 0;
294 io.ntcreatex.in.fname = fname;
295 status = smb_raw_open(tree, mem_ctx, &io);
296 CHECK_STATUS(status, NT_STATUS_OK);
297 fnum = io.ntcreatex.out.fnum;
299 printf("write using the old tid\n");
300 wr.generic.level = RAW_WRITE_WRITEX;
301 wr.writex.in.fnum = fnum;
302 wr.writex.in.offset = 0;
303 wr.writex.in.wmode = 0;
304 wr.writex.in.remaining = 0;
305 wr.writex.in.count = 1;
306 wr.writex.in.data = &c;
308 status = smb_raw_write(cli->tree, &wr);
309 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
311 printf("write with the new tid\n");
312 status = smb_raw_write(tree, &wr);
313 CHECK_STATUS(status, NT_STATUS_OK);
314 CHECK_VALUE(wr.writex.out.nwritten, 1);
316 printf("disconnect the new tid\n");
317 status = smb_tree_disconnect(tree);
318 CHECK_STATUS(status, NT_STATUS_OK);
320 printf("the new tid should not now be accessible\n");
321 status = smb_raw_write(tree, &wr);
322 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
324 printf("the fnum should have been auto-closed\n");
325 cl.close.level = RAW_CLOSE_CLOSE;
326 cl.close.in.fnum = fnum;
327 cl.close.in.write_time = 0;
328 status = smb_raw_close(cli->tree, &cl);
329 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
331 /* close down the new tree */
342 static BOOL test_pid(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
350 const char *fname = BASEDIR "\\test.txt";
354 printf("TESTING PID HANDLING\n");
356 if (!torture_setup_dir(cli, BASEDIR)) {
360 printf("create a second pid\n");
361 pid1 = cli->session->pid;
364 printf("pid1=%d pid2=%d\n", pid1, pid2);
366 printf("create a file using the new pid\n");
367 cli->session->pid = pid2;
368 io.generic.level = RAW_OPEN_NTCREATEX;
369 io.ntcreatex.in.root_fid = 0;
370 io.ntcreatex.in.flags = 0;
371 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
372 io.ntcreatex.in.create_options = 0;
373 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
374 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
375 io.ntcreatex.in.alloc_size = 0;
376 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
377 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
378 io.ntcreatex.in.security_flags = 0;
379 io.ntcreatex.in.fname = fname;
380 status = smb_raw_open(cli->tree, mem_ctx, &io);
381 CHECK_STATUS(status, NT_STATUS_OK);
382 fnum = io.ntcreatex.out.fnum;
384 printf("write using the old pid\n");
385 cli->session->pid = pid1;
386 wr.generic.level = RAW_WRITE_WRITEX;
387 wr.writex.in.fnum = fnum;
388 wr.writex.in.offset = 0;
389 wr.writex.in.wmode = 0;
390 wr.writex.in.remaining = 0;
391 wr.writex.in.count = 1;
392 wr.writex.in.data = &c;
394 status = smb_raw_write(cli->tree, &wr);
395 CHECK_STATUS(status, NT_STATUS_OK);
396 CHECK_VALUE(wr.writex.out.nwritten, 1);
398 printf("write with the new pid\n");
399 cli->session->pid = pid2;
400 status = smb_raw_write(cli->tree, &wr);
401 CHECK_STATUS(status, NT_STATUS_OK);
402 CHECK_VALUE(wr.writex.out.nwritten, 1);
404 printf("exit the old pid\n");
405 cli->session->pid = pid1;
406 status = smb_raw_exit(cli->session);
407 CHECK_STATUS(status, NT_STATUS_OK);
409 printf("the fnum should still be accessible\n");
410 cli->session->pid = pid1;
411 status = smb_raw_write(cli->tree, &wr);
412 CHECK_STATUS(status, NT_STATUS_OK);
413 CHECK_VALUE(wr.writex.out.nwritten, 1);
415 printf("exit the new pid\n");
416 cli->session->pid = pid2;
417 status = smb_raw_exit(cli->session);
418 CHECK_STATUS(status, NT_STATUS_OK);
420 printf("the fnum should not now be accessible\n");
421 cli->session->pid = pid1;
422 status = smb_raw_write(cli->tree, &wr);
423 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
425 printf("the fnum should have been auto-closed\n");
426 cl.close.level = RAW_CLOSE_CLOSE;
427 cl.close.in.fnum = fnum;
428 cl.close.in.write_time = 0;
429 status = smb_raw_close(cli->tree, &cl);
430 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
438 basic testing of session/tree context calls
440 static BOOL torture_raw_context_int(void)
442 struct smbcli_state *cli;
446 if (!torture_open_connection(&cli)) {
450 mem_ctx = talloc_init("torture_raw_context");
452 if (!test_session(cli, mem_ctx)) {
456 if (!test_tree(cli, mem_ctx)) {
460 if (!test_pid(cli, mem_ctx)) {
464 smb_raw_exit(cli->session);
465 smbcli_deltree(cli->tree, BASEDIR);
467 torture_close_connection(cli);
468 talloc_free(mem_ctx);
473 basic testing of session/tree context calls
475 BOOL torture_raw_context(void)
478 if (lp_use_spnego()) {
479 ret &= torture_raw_context_int();
480 lp_set_cmdline("use spnego", "False");
483 ret &= torture_raw_context_int();