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