1 /*
2    Unix SMB/CIFS implementation.
3    test suite for session setup operations
4    Copyright (C) Andrew Tridgell 2003
5 
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.
10 
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.
15 
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.
19 */
20 
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/composite/composite.h"
25 #include "libcli/smb_composite/smb_composite.h"
26 #include "lib/cmdline/popt_common.h"
27 #include "lib/events/events.h"
28 #include "libcli/libcli.h"
29 #include "torture/util.h"
30 #include "auth/credentials/credentials.h"
31 
32 #define BASEDIR "\\rawcontext"
33 
34 #define CHECK_STATUS(status, correct) do { \
35 	if (!NT_STATUS_EQUAL(status, correct)) { \
36 		printf("(%s) Incorrect status %s - should be %s\n", \
37 		       __location__, nt_errstr(status), nt_errstr(correct)); \
38 		ret = False; \
39 		goto done; \
40 	}} while (0)
41 
42 #define CHECK_VALUE(v, correct) do { \
43 	if ((v) != (correct)) { \
44 		printf("(%s) Incorrect value %s=%d - should be %d\n", \
45 		       __location__, #v, v, correct); \
46 		ret = False; \
47 		goto done; \
48 	}} while (0)
49 
50 #define CHECK_NOT_VALUE(v, correct) do { \
51 	if ((v) == (correct)) { \
52 		printf("(%s) Incorrect value %s=%d - should not be %d\n", \
53 		       __location__, #v, v, correct); \
54 		ret = False; \
55 		goto done; \
56 	}} while (0)
57 
58 
59 /*
60   test session ops
61 */
test_session(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)62 static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
63 {
64 	NTSTATUS status;
65 	BOOL ret = True;
66 	struct smbcli_session *session;
67 	struct smbcli_session *session2;
68 	struct smbcli_session *session3;
69 	struct smbcli_session *session4;
70 	struct cli_credentials *anon_creds;
71 	struct smbcli_session *sessions[15];
72 	struct composite_context *composite_contexts[15];
73 	struct smbcli_tree *tree;
74 	struct smb_composite_sesssetup setup;
75 	struct smb_composite_sesssetup setups[15];
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 
84 	printf("TESTING SESSION HANDLING\n");
85 
86 	if (!torture_setup_dir(cli, BASEDIR)) {
87 		return False;
88 	}
89 
90 	printf("create a second security context on the same transport\n");
91 	session = smbcli_session_init(cli->transport, mem_ctx, False);
92 
93 	setup.in.sesskey = cli->transport->negotiate.sesskey;
94 	setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
95 	setup.in.workgroup = lp_workgroup();
96 
97 	setup.in.credentials = cmdline_credentials;
98 
99 	status = smb_composite_sesssetup(session, &setup);
100 	CHECK_STATUS(status, NT_STATUS_OK);
101 
102 	session->vuid = setup.out.vuid;
103 
104 	printf("create a third security context on the same transport, with vuid set\n");
105 	session2 = smbcli_session_init(cli->transport, mem_ctx, False);
106 
107 	session2->vuid = session->vuid;
108 	setup.in.sesskey = cli->transport->negotiate.sesskey;
109 	setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
110 	setup.in.workgroup = lp_workgroup();
111 
112 	setup.in.credentials = cmdline_credentials;
113 
114 	status = smb_composite_sesssetup(session2, &setup);
115 	CHECK_STATUS(status, NT_STATUS_OK);
116 
117 	session2->vuid = setup.out.vuid;
118 	printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid);
119 
120 	if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
121 		/* Samba4 currently fails this - we need to determine if this insane behaviour is important */
122 		if (session2->vuid == session->vuid) {
123 			printf("server allows the user to re-use an existing vuid in session setup \n");
124 		}
125 	} else {
126 		CHECK_NOT_VALUE(session2->vuid, session->vuid);
127 	}
128 	talloc_free(session2);
129 
130 	if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
131 		printf("create a fourth security context on the same transport, without extended security\n");
132 		session3 = smbcli_session_init(cli->transport, mem_ctx, False);
133 
134 		session3->vuid = session->vuid;
135 		setup.in.sesskey = cli->transport->negotiate.sesskey;
136 		setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
137 		setup.in.workgroup = lp_workgroup();
138 
139 		setup.in.credentials = cmdline_credentials;
140 
141 
142 		status = smb_composite_sesssetup(session3, &setup);
143 		CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);
144 
145 		printf("create a fouth anonymous security context on the same transport, without extended security\n");
146 		session4 = smbcli_session_init(cli->transport, mem_ctx, False);
147 
148 		session4->vuid = session->vuid;
149 		setup.in.sesskey = cli->transport->negotiate.sesskey;
150 		setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */
151 		setup.in.workgroup = lp_workgroup();
152 
153 		anon_creds = cli_credentials_init(mem_ctx);
154 		cli_credentials_set_conf(anon_creds);
155 		cli_credentials_set_anonymous(anon_creds);
156 
157 		setup.in.credentials = anon_creds;
158 
159 		status = smb_composite_sesssetup(session3, &setup);
160 		CHECK_STATUS(status, NT_STATUS_OK);
161 
162 		talloc_free(session4);
163 	}
164 
165 	printf("use the same tree as the existing connection\n");
166 	tree = smbcli_tree_init(session, mem_ctx, False);
167 	tree->tid = cli->tree->tid;
168 
169 	printf("create a file using the new vuid\n");
170 	io.generic.level = RAW_OPEN_NTCREATEX;
171 	io.ntcreatex.in.root_fid = 0;
172 	io.ntcreatex.in.flags = 0;
173 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
174 	io.ntcreatex.in.create_options = 0;
175 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
176 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
177 	io.ntcreatex.in.alloc_size = 0;
178 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
179 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
180 	io.ntcreatex.in.security_flags = 0;
181 	io.ntcreatex.in.fname = fname;
182 	status = smb_raw_open(tree, mem_ctx, &io);
183 	CHECK_STATUS(status, NT_STATUS_OK);
184 	fnum = io.ntcreatex.out.file.fnum;
185 
186 	printf("write using the old vuid\n");
187 	wr.generic.level = RAW_WRITE_WRITEX;
188 	wr.writex.in.file.fnum = fnum;
189 	wr.writex.in.offset = 0;
190 	wr.writex.in.wmode = 0;
191 	wr.writex.in.remaining = 0;
192 	wr.writex.in.count = 1;
193 	wr.writex.in.data = &c;
194 
195 	status = smb_raw_write(cli->tree, &wr);
196 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
197 
198 	printf("write with the new vuid\n");
199 	status = smb_raw_write(tree, &wr);
200 	CHECK_STATUS(status, NT_STATUS_OK);
201 	CHECK_VALUE(wr.writex.out.nwritten, 1);
202 
203 	printf("logoff the new vuid\n");
204 	status = smb_raw_ulogoff(session);
205 	CHECK_STATUS(status, NT_STATUS_OK);
206 
207 	printf("the new vuid should not now be accessible\n");
208 	status = smb_raw_write(tree, &wr);
209 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
210 
211 	printf("second logoff for the new vuid should fail\n");
212 	status = smb_raw_ulogoff(session);
213 	CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid));
214 	talloc_free(session);
215 
216 	printf("the fnum should have been auto-closed\n");
217 	cl.close.level = RAW_CLOSE_CLOSE;
218 	cl.close.in.file.fnum = fnum;
219 	cl.close.in.write_time = 0;
220 	status = smb_raw_close(cli->tree, &cl);
221 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
222 
223 	printf("create %d secondary security contexts on the same transport\n",
224 	       (int)ARRAY_SIZE(sessions));
225 	for (i=0; i <ARRAY_SIZE(sessions); i++) {
226 		setups[i].in.sesskey = cli->transport->negotiate.sesskey;
227 		setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
228 		setups[i].in.workgroup = lp_workgroup();
229 
230 		setups[i].in.credentials = cmdline_credentials;
231 
232 		sessions[i] = smbcli_session_init(cli->transport, mem_ctx, False);
233 		composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]);
234 
235 	}
236 
237 
238 	/* flush the queue */
239 	for (i=0; i < ARRAY_SIZE(sessions); i++) {
240 		event_loop_once(composite_contexts[0]->event_ctx);
241 	}
242 
243 	printf("finishing %d secondary security contexts on the same transport\n",
244 	       (int)ARRAY_SIZE(sessions));
245 	for (i=0; i< ARRAY_SIZE(sessions); i++) {
246 		status = smb_composite_sesssetup_recv(composite_contexts[i]);
247 		CHECK_STATUS(status, NT_STATUS_OK);
248 		sessions[i]->vuid = setups[i].out.vuid;
249 		printf("VUID: %d\n", sessions[i]->vuid);
250 		status = smb_raw_ulogoff(sessions[i]);
251 		CHECK_STATUS(status, NT_STATUS_OK);
252 	}
253 
254 
255 	talloc_free(tree);
256 
257 done:
258 	return ret;
259 }
260 
261 
262 /*
263   test tree ops
264 */
test_tree(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)265 static BOOL test_tree(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
266 {
267 	NTSTATUS status;
268 	BOOL ret = True;
269 	const char *share, *host;
270 	struct smbcli_tree *tree;
271 	union smb_tcon tcon;
272 	union smb_open io;
273 	union smb_write wr;
274 	union smb_close cl;
275 	int fnum;
276 	const char *fname = BASEDIR "\\test.txt";
277 	uint8_t c = 1;
278 
279 	printf("TESTING TREE HANDLING\n");
280 
281 	if (!torture_setup_dir(cli, BASEDIR)) {
282 		return False;
283 	}
284 
285 	share = lp_parm_string(-1, "torture", "share");
286 	host  = lp_parm_string(-1, "torture", "host");
287 
288 	printf("create a second tree context on the same session\n");
289 	tree = smbcli_tree_init(cli->session, mem_ctx, False);
290 
291 	tcon.generic.level = RAW_TCON_TCONX;
292 	tcon.tconx.in.flags = 0;
293 	tcon.tconx.in.password = data_blob(NULL, 0);
294 	tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
295 	tcon.tconx.in.device = "A:";
296 	status = smb_raw_tcon(tree, mem_ctx, &tcon);
297 	CHECK_STATUS(status, NT_STATUS_OK);
298 
299 
300 	tree->tid = tcon.tconx.out.tid;
301 	printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid);
302 
303 	printf("try a tconx with a bad device type\n");
304 	tcon.tconx.in.device = "FOO";
305 	status = smb_raw_tcon(tree, mem_ctx, &tcon);
306 	CHECK_STATUS(status, NT_STATUS_BAD_DEVICE_TYPE);
307 
308 
309 	printf("create a file using the new tid\n");
310 	io.generic.level = RAW_OPEN_NTCREATEX;
311 	io.ntcreatex.in.root_fid = 0;
312 	io.ntcreatex.in.flags = 0;
313 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
314 	io.ntcreatex.in.create_options = 0;
315 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
316 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
317 	io.ntcreatex.in.alloc_size = 0;
318 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
319 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
320 	io.ntcreatex.in.security_flags = 0;
321 	io.ntcreatex.in.fname = fname;
322 	status = smb_raw_open(tree, mem_ctx, &io);
323 	CHECK_STATUS(status, NT_STATUS_OK);
324 	fnum = io.ntcreatex.out.file.fnum;
325 
326 	printf("write using the old tid\n");
327 	wr.generic.level = RAW_WRITE_WRITEX;
328 	wr.writex.in.file.fnum = fnum;
329 	wr.writex.in.offset = 0;
330 	wr.writex.in.wmode = 0;
331 	wr.writex.in.remaining = 0;
332 	wr.writex.in.count = 1;
333 	wr.writex.in.data = &c;
334 
335 	status = smb_raw_write(cli->tree, &wr);
336 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
337 
338 	printf("write with the new tid\n");
339 	status = smb_raw_write(tree, &wr);
340 	CHECK_STATUS(status, NT_STATUS_OK);
341 	CHECK_VALUE(wr.writex.out.nwritten, 1);
342 
343 	printf("disconnect the new tid\n");
344 	status = smb_tree_disconnect(tree);
345 	CHECK_STATUS(status, NT_STATUS_OK);
346 
347 	printf("the new tid should not now be accessible\n");
348 	status = smb_raw_write(tree, &wr);
349 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
350 
351 	printf("the fnum should have been auto-closed\n");
352 	cl.close.level = RAW_CLOSE_CLOSE;
353 	cl.close.in.file.fnum = fnum;
354 	cl.close.in.write_time = 0;
355 	status = smb_raw_close(cli->tree, &cl);
356 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
357 
358 	/* close down the new tree */
359 	talloc_free(tree);
360 
361 done:
362 	return ret;
363 }
364 
365 /*
366   test tree with ulogoff
367   this demonstrates that a tcon isn't autoclosed by a ulogoff
368   the tcon can be reused using any other valid session later
369 */
test_tree_ulogoff(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)370 static BOOL test_tree_ulogoff(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
371 {
372 	NTSTATUS status;
373 	BOOL ret = True;
374 	const char *share, *host;
375 	struct smbcli_session *session1;
376 	struct smbcli_session *session2;
377 	struct smb_composite_sesssetup setup;
378 	struct smbcli_tree *tree;
379 	union smb_tcon tcon;
380 	union smb_open io;
381 	union smb_write wr;
382 	int fnum1, fnum2;
383 	const char *fname1 = BASEDIR "\\test1.txt";
384 	const char *fname2 = BASEDIR "\\test2.txt";
385 	uint8_t c = 1;
386 
387 	printf("TESTING TREE with ulogoff\n");
388 
389 	if (!torture_setup_dir(cli, BASEDIR)) {
390 		return False;
391 	}
392 
393 	share = lp_parm_string(-1, "torture", "share");
394 	host  = lp_parm_string(-1, "torture", "host");
395 
396 	printf("create the first new sessions\n");
397 	session1 = smbcli_session_init(cli->transport, mem_ctx, False);
398 	setup.in.sesskey = cli->transport->negotiate.sesskey;
399 	setup.in.capabilities = cli->transport->negotiate.capabilities;
400 	setup.in.workgroup = lp_workgroup();
401 	setup.in.credentials = cmdline_credentials;
402 	status = smb_composite_sesssetup(session1, &setup);
403 	CHECK_STATUS(status, NT_STATUS_OK);
404 	session1->vuid = setup.out.vuid;
405 	printf("vuid1=%d\n", session1->vuid);
406 
407 	printf("create a tree context on the with vuid1\n");
408 	tree = smbcli_tree_init(session1, mem_ctx, False);
409 	tcon.generic.level = RAW_TCON_TCONX;
410 	tcon.tconx.in.flags = 0;
411 	tcon.tconx.in.password = data_blob(NULL, 0);
412 	tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
413 	tcon.tconx.in.device = "A:";
414 	status = smb_raw_tcon(tree, mem_ctx, &tcon);
415 	CHECK_STATUS(status, NT_STATUS_OK);
416 	tree->tid = tcon.tconx.out.tid;
417 	printf("tid=%d\n", tree->tid);
418 
419 	printf("create a file using vuid1\n");
420 	io.generic.level = RAW_OPEN_NTCREATEX;
421 	io.ntcreatex.in.root_fid = 0;
422 	io.ntcreatex.in.flags = 0;
423 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
424 	io.ntcreatex.in.create_options = 0;
425 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
426 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
427 	io.ntcreatex.in.alloc_size = 0;
428 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
429 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
430 	io.ntcreatex.in.security_flags = 0;
431 	io.ntcreatex.in.fname = fname1;
432 	status = smb_raw_open(tree, mem_ctx, &io);
433 	CHECK_STATUS(status, NT_STATUS_OK);
434 	fnum1 = io.ntcreatex.out.file.fnum;
435 
436 	printf("write using vuid1\n");
437 	wr.generic.level = RAW_WRITE_WRITEX;
438 	wr.writex.in.file.fnum = fnum1;
439 	wr.writex.in.offset = 0;
440 	wr.writex.in.wmode = 0;
441 	wr.writex.in.remaining = 0;
442 	wr.writex.in.count = 1;
443 	wr.writex.in.data = &c;
444 	status = smb_raw_write(tree, &wr);
445 	CHECK_STATUS(status, NT_STATUS_OK);
446 	CHECK_VALUE(wr.writex.out.nwritten, 1);
447 
448 	printf("ulogoff the vuid1\n");
449 	status = smb_raw_ulogoff(session1);
450 	CHECK_STATUS(status, NT_STATUS_OK);
451 
452 	printf("create the second new sessions\n");
453 	session2 = smbcli_session_init(cli->transport, mem_ctx, False);
454 	setup.in.sesskey = cli->transport->negotiate.sesskey;
455 	setup.in.capabilities = cli->transport->negotiate.capabilities;
456 	setup.in.workgroup = lp_workgroup();
457 	setup.in.credentials = cmdline_credentials;
458 	status = smb_composite_sesssetup(session2, &setup);
459 	CHECK_STATUS(status, NT_STATUS_OK);
460 	session2->vuid = setup.out.vuid;
461 	printf("vuid2=%d\n", session2->vuid);
462 
463 	printf("use the existing tree with vuid2\n");
464 	tree->session = session2;
465 
466 	printf("create a file using vuid2\n");
467 	io.generic.level = RAW_OPEN_NTCREATEX;
468 	io.ntcreatex.in.root_fid = 0;
469 	io.ntcreatex.in.flags = 0;
470 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
471 	io.ntcreatex.in.create_options = 0;
472 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
473 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
474 	io.ntcreatex.in.alloc_size = 0;
475 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
476 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
477 	io.ntcreatex.in.security_flags = 0;
478 	io.ntcreatex.in.fname = fname2;
479 	status = smb_raw_open(tree, mem_ctx, &io);
480 	CHECK_STATUS(status, NT_STATUS_OK);
481 	fnum2 = io.ntcreatex.out.file.fnum;
482 
483 	printf("write using vuid2\n");
484 	wr.generic.level = RAW_WRITE_WRITEX;
485 	wr.writex.in.file.fnum = fnum2;
486 	wr.writex.in.offset = 0;
487 	wr.writex.in.wmode = 0;
488 	wr.writex.in.remaining = 0;
489 	wr.writex.in.count = 1;
490 	wr.writex.in.data = &c;
491 	status = smb_raw_write(tree, &wr);
492 	CHECK_STATUS(status, NT_STATUS_OK);
493 	CHECK_VALUE(wr.writex.out.nwritten, 1);
494 
495 	printf("ulogoff the vuid2\n");
496 	status = smb_raw_ulogoff(session2);
497 	CHECK_STATUS(status, NT_STATUS_OK);
498 
499 	/* this also demonstrates that SMBtdis doesn't need a valid vuid */
500 	printf("disconnect the existing tree connection\n");
501 	status = smb_tree_disconnect(tree);
502 	CHECK_STATUS(status, NT_STATUS_OK);
503 
504 	printf("disconnect the existing tree connection\n");
505 	status = smb_tree_disconnect(tree);
506 	CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV,ERRinvnid));
507 
508 	/* close down the new tree */
509 	talloc_free(tree);
510 
511 done:
512 	return ret;
513 }
514 
515 /*
516   test pid ops
517   this test demonstrates that exit() only sees the PID
518   used for the open() calls
519 */
test_pid_exit_only_sees_open(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)520 static BOOL test_pid_exit_only_sees_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
521 {
522 	NTSTATUS status;
523 	BOOL ret = True;
524 	union smb_open io;
525 	union smb_write wr;
526 	union smb_close cl;
527 	int fnum;
528 	const char *fname = BASEDIR "\\test.txt";
529 	uint8_t c = 1;
530 	uint16_t pid1, pid2;
531 
532 	printf("TESTING PID HANDLING exit() only cares about open() PID\n");
533 
534 	if (!torture_setup_dir(cli, BASEDIR)) {
535 		return False;
536 	}
537 
538 	pid1 = cli->session->pid;
539 	pid2 = pid1 + 1;
540 
541 	printf("pid1=%d pid2=%d\n", pid1, pid2);
542 
543 	printf("create a file using pid1\n");
544 	cli->session->pid = pid1;
545 	io.generic.level = RAW_OPEN_NTCREATEX;
546 	io.ntcreatex.in.root_fid = 0;
547 	io.ntcreatex.in.flags = 0;
548 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
549 	io.ntcreatex.in.create_options = 0;
550 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
551 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
552 	io.ntcreatex.in.alloc_size = 0;
553 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
554 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
555 	io.ntcreatex.in.security_flags = 0;
556 	io.ntcreatex.in.fname = fname;
557 	status = smb_raw_open(cli->tree, mem_ctx, &io);
558 	CHECK_STATUS(status, NT_STATUS_OK);
559 	fnum = io.ntcreatex.out.file.fnum;
560 
561 	printf("write using pid2\n");
562 	cli->session->pid = pid2;
563 	wr.generic.level = RAW_WRITE_WRITEX;
564 	wr.writex.in.file.fnum = fnum;
565 	wr.writex.in.offset = 0;
566 	wr.writex.in.wmode = 0;
567 	wr.writex.in.remaining = 0;
568 	wr.writex.in.count = 1;
569 	wr.writex.in.data = &c;
570 	status = smb_raw_write(cli->tree, &wr);
571 	CHECK_STATUS(status, NT_STATUS_OK);
572 	CHECK_VALUE(wr.writex.out.nwritten, 1);
573 
574 	printf("exit pid2\n");
575 	cli->session->pid = pid2;
576 	status = smb_raw_exit(cli->session);
577 	CHECK_STATUS(status, NT_STATUS_OK);
578 
579 	printf("the fnum should still be accessible via pid2\n");
580 	cli->session->pid = pid2;
581 	status = smb_raw_write(cli->tree, &wr);
582 	CHECK_STATUS(status, NT_STATUS_OK);
583 	CHECK_VALUE(wr.writex.out.nwritten, 1);
584 
585 	printf("exit pid2\n");
586 	cli->session->pid = pid2;
587 	status = smb_raw_exit(cli->session);
588 	CHECK_STATUS(status, NT_STATUS_OK);
589 
590 	printf("the fnum should still be accessible via pid1 and pid2\n");
591 	cli->session->pid = pid1;
592 	status = smb_raw_write(cli->tree, &wr);
593 	CHECK_STATUS(status, NT_STATUS_OK);
594 	CHECK_VALUE(wr.writex.out.nwritten, 1);
595 	cli->session->pid = pid2;
596 	status = smb_raw_write(cli->tree, &wr);
597 	CHECK_STATUS(status, NT_STATUS_OK);
598 	CHECK_VALUE(wr.writex.out.nwritten, 1);
599 
600 	printf("exit pid1\n");
601 	cli->session->pid = pid1;
602 	status = smb_raw_exit(cli->session);
603 	CHECK_STATUS(status, NT_STATUS_OK);
604 
605 	printf("the fnum should not now be accessible via pid1 or pid2\n");
606 	cli->session->pid = pid1;
607 	status = smb_raw_write(cli->tree, &wr);
608 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
609 	cli->session->pid = pid2;
610 	status = smb_raw_write(cli->tree, &wr);
611 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
612 
613 	printf("the fnum should have been auto-closed\n");
614 	cli->session->pid = pid1;
615 	cl.close.level = RAW_CLOSE_CLOSE;
616 	cl.close.in.file.fnum = fnum;
617 	cl.close.in.write_time = 0;
618 	status = smb_raw_close(cli->tree, &cl);
619 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
620 
621 done:
622 	return ret;
623 }
624 
625 /*
626   test pid ops with 2 sessions
627 */
test_pid_2sess(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)628 static BOOL test_pid_2sess(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
629 {
630 	NTSTATUS status;
631 	BOOL ret = True;
632 	struct smbcli_session *session;
633 	struct smb_composite_sesssetup setup;
634 	union smb_open io;
635 	union smb_write wr;
636 	union smb_close cl;
637 	int fnum;
638 	const char *fname = BASEDIR "\\test.txt";
639 	uint8_t c = 1;
640 	uint16_t vuid1, vuid2;
641 
642 	printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
643 
644 	if (!torture_setup_dir(cli, BASEDIR)) {
645 		return False;
646 	}
647 
648 	printf("create a second security context on the same transport\n");
649 	session = smbcli_session_init(cli->transport, mem_ctx, False);
650 
651 	setup.in.sesskey = cli->transport->negotiate.sesskey;
652 	setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
653 	setup.in.workgroup = lp_workgroup();
654 
655 	setup.in.credentials = cmdline_credentials;
656 
657 	status = smb_composite_sesssetup(session, &setup);
658 	CHECK_STATUS(status, NT_STATUS_OK);
659 	session->vuid = setup.out.vuid;
660 
661 	vuid1 = cli->session->vuid;
662 	vuid2 = session->vuid;
663 
664 	printf("vuid1=%d vuid2=%d\n", vuid1, vuid2);
665 
666 	printf("create a file using the vuid1\n");
667 	cli->session->vuid = vuid1;
668 	io.generic.level = RAW_OPEN_NTCREATEX;
669 	io.ntcreatex.in.root_fid = 0;
670 	io.ntcreatex.in.flags = 0;
671 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
672 	io.ntcreatex.in.create_options = 0;
673 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
674 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
675 	io.ntcreatex.in.alloc_size = 0;
676 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
677 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
678 	io.ntcreatex.in.security_flags = 0;
679 	io.ntcreatex.in.fname = fname;
680 	status = smb_raw_open(cli->tree, mem_ctx, &io);
681 	CHECK_STATUS(status, NT_STATUS_OK);
682 	fnum = io.ntcreatex.out.file.fnum;
683 
684 	printf("write using the vuid1 (fnum=%d)\n", fnum);
685 	cli->session->vuid = vuid1;
686 	wr.generic.level = RAW_WRITE_WRITEX;
687 	wr.writex.in.file.fnum = fnum;
688 	wr.writex.in.offset = 0;
689 	wr.writex.in.wmode = 0;
690 	wr.writex.in.remaining = 0;
691 	wr.writex.in.count = 1;
692 	wr.writex.in.data = &c;
693 
694 	status = smb_raw_write(cli->tree, &wr);
695 	CHECK_STATUS(status, NT_STATUS_OK);
696 	CHECK_VALUE(wr.writex.out.nwritten, 1);
697 
698 	printf("exit the pid with vuid2\n");
699 	cli->session->vuid = vuid2;
700 	status = smb_raw_exit(cli->session);
701 	CHECK_STATUS(status, NT_STATUS_OK);
702 
703 	printf("the fnum should still be accessible\n");
704 	cli->session->vuid = vuid1;
705 	status = smb_raw_write(cli->tree, &wr);
706 	CHECK_STATUS(status, NT_STATUS_OK);
707 	CHECK_VALUE(wr.writex.out.nwritten, 1);
708 
709 	printf("exit the pid with vuid1\n");
710 	cli->session->vuid = vuid1;
711 	status = smb_raw_exit(cli->session);
712 	CHECK_STATUS(status, NT_STATUS_OK);
713 
714 	printf("the fnum should not now be accessible\n");
715 	status = smb_raw_write(cli->tree, &wr);
716 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
717 
718 	printf("the fnum should have been auto-closed\n");
719 	cl.close.level = RAW_CLOSE_CLOSE;
720 	cl.close.in.file.fnum = fnum;
721 	cl.close.in.write_time = 0;
722 	status = smb_raw_close(cli->tree, &cl);
723 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
724 
725 done:
726 	return ret;
727 }
728 
729 /*
730   test pid ops with 2 tcons
731 */
test_pid_2tcon(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)732 static BOOL test_pid_2tcon(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
733 {
734 	NTSTATUS status;
735 	BOOL ret = True;
736 	const char *share, *host;
737 	struct smbcli_tree *tree;
738 	union smb_tcon tcon;
739 	union smb_open io;
740 	union smb_write wr;
741 	union smb_close cl;
742 	int fnum1, fnum2;
743 	const char *fname1 = BASEDIR "\\test1.txt";
744 	const char *fname2 = BASEDIR "\\test2.txt";
745 	uint8_t c = 1;
746 	uint16_t tid1, tid2;
747 
748 	printf("TESTING PID HANDLING WITH 2 TCONS\n");
749 
750 	if (!torture_setup_dir(cli, BASEDIR)) {
751 		return False;
752 	}
753 
754 	share = lp_parm_string(-1, "torture", "share");
755 	host  = lp_parm_string(-1, "torture", "host");
756 
757 	printf("create a second tree context on the same session\n");
758 	tree = smbcli_tree_init(cli->session, mem_ctx, False);
759 
760 	tcon.generic.level = RAW_TCON_TCONX;
761 	tcon.tconx.in.flags = 0;
762 	tcon.tconx.in.password = data_blob(NULL, 0);
763 	tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
764 	tcon.tconx.in.device = "A:";
765 	status = smb_raw_tcon(tree, mem_ctx, &tcon);
766 	CHECK_STATUS(status, NT_STATUS_OK);
767 
768 	tree->tid = tcon.tconx.out.tid;
769 
770 	tid1 = cli->tree->tid;
771 	tid2 = tree->tid;
772 	printf("tid1=%d tid2=%d\n", tid1, tid2);
773 
774 	printf("create a file using the tid1\n");
775 	cli->tree->tid = tid1;
776 	io.generic.level = RAW_OPEN_NTCREATEX;
777 	io.ntcreatex.in.root_fid = 0;
778 	io.ntcreatex.in.flags = 0;
779 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
780 	io.ntcreatex.in.create_options = 0;
781 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
782 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
783 	io.ntcreatex.in.alloc_size = 0;
784 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
785 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
786 	io.ntcreatex.in.security_flags = 0;
787 	io.ntcreatex.in.fname = fname1;
788 	status = smb_raw_open(cli->tree, mem_ctx, &io);
789 	CHECK_STATUS(status, NT_STATUS_OK);
790 	fnum1 = io.ntcreatex.out.file.fnum;
791 
792 	printf("write using the tid1\n");
793 	wr.generic.level = RAW_WRITE_WRITEX;
794 	wr.writex.in.file.fnum = fnum1;
795 	wr.writex.in.offset = 0;
796 	wr.writex.in.wmode = 0;
797 	wr.writex.in.remaining = 0;
798 	wr.writex.in.count = 1;
799 	wr.writex.in.data = &c;
800 
801 	status = smb_raw_write(cli->tree, &wr);
802 	CHECK_STATUS(status, NT_STATUS_OK);
803 	CHECK_VALUE(wr.writex.out.nwritten, 1);
804 
805 	printf("create a file using the tid2\n");
806 	cli->tree->tid = tid2;
807 	io.generic.level = RAW_OPEN_NTCREATEX;
808 	io.ntcreatex.in.root_fid = 0;
809 	io.ntcreatex.in.flags = 0;
810 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
811 	io.ntcreatex.in.create_options = 0;
812 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
813 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
814 	io.ntcreatex.in.alloc_size = 0;
815 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
816 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
817 	io.ntcreatex.in.security_flags = 0;
818 	io.ntcreatex.in.fname = fname2;
819 	status = smb_raw_open(cli->tree, mem_ctx, &io);
820 	CHECK_STATUS(status, NT_STATUS_OK);
821 	fnum2 = io.ntcreatex.out.file.fnum;
822 
823 	printf("write using the tid2\n");
824 	wr.generic.level = RAW_WRITE_WRITEX;
825 	wr.writex.in.file.fnum = fnum2;
826 	wr.writex.in.offset = 0;
827 	wr.writex.in.wmode = 0;
828 	wr.writex.in.remaining = 0;
829 	wr.writex.in.count = 1;
830 	wr.writex.in.data = &c;
831 
832 	status = smb_raw_write(cli->tree, &wr);
833 	CHECK_STATUS(status, NT_STATUS_OK);
834 	CHECK_VALUE(wr.writex.out.nwritten, 1);
835 
836 	printf("exit the pid\n");
837 	status = smb_raw_exit(cli->session);
838 	CHECK_STATUS(status, NT_STATUS_OK);
839 
840 	printf("the fnum1 on tid1 should not be accessible\n");
841 	cli->tree->tid = tid1;
842 	wr.writex.in.file.fnum = fnum1;
843 	status = smb_raw_write(cli->tree, &wr);
844 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
845 
846 	printf("the fnum1 on tid1 should have been auto-closed\n");
847 	cl.close.level = RAW_CLOSE_CLOSE;
848 	cl.close.in.file.fnum = fnum1;
849 	cl.close.in.write_time = 0;
850 	status = smb_raw_close(cli->tree, &cl);
851 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
852 
853 	printf("the fnum2 on tid2 should not be accessible\n");
854 	cli->tree->tid = tid2;
855 	wr.writex.in.file.fnum = fnum2;
856 	status = smb_raw_write(cli->tree, &wr);
857 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
858 
859 	printf("the fnum2 on tid2 should have been auto-closed\n");
860 	cl.close.level = RAW_CLOSE_CLOSE;
861 	cl.close.in.file.fnum = fnum2;
862 	cl.close.in.write_time = 0;
863 	status = smb_raw_close(cli->tree, &cl);
864 	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
865 
866 done:
867 	return ret;
868 }
869 
870 
871 /*
872    basic testing of session/tree context calls
873 */
torture_raw_context_int(void)874 static BOOL torture_raw_context_int(void)
875 {
876 	struct smbcli_state *cli;
877 	BOOL ret = True;
878 	TALLOC_CTX *mem_ctx;
879 
880 	if (!torture_open_connection(&cli, 0)) {
881 		return False;
882 	}
883 
884 	mem_ctx = talloc_init("torture_raw_context");
885 
886 	ret &= test_session(cli, mem_ctx);
887 	ret &= test_tree(cli, mem_ctx);
888 	ret &= test_tree_ulogoff(cli, mem_ctx);
889 	ret &= test_pid_exit_only_sees_open(cli, mem_ctx);
890 	ret &= test_pid_2sess(cli, mem_ctx);
891 	ret &= test_pid_2tcon(cli, mem_ctx);
892 
893 	smb_raw_exit(cli->session);
894 	smbcli_deltree(cli->tree, BASEDIR);
895 
896 	torture_close_connection(cli);
897 	talloc_free(mem_ctx);
898 
899 	return ret;
900 }
901 /*
902    basic testing of session/tree context calls
903 */
torture_raw_context(struct torture_context * torture)904 BOOL torture_raw_context(struct torture_context *torture)
905 {
906 	BOOL ret = True;
907 	if (lp_use_spnego()) {
908 		ret &= torture_raw_context_int();
909 		lp_set_cmdline("use spnego", "False");
910 	}
911 
912 	ret &= torture_raw_context_int();
913 
914 	return ret;
915 }
916