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/>.
21 #include "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/raw/raw_proto.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 #include "param/param.h"
33 #define BASEDIR "\\rawcontext"
35 #define CHECK_STATUS(status, correct) do { \
36 if (!NT_STATUS_EQUAL(status, correct)) { \
37 printf("(%s) Incorrect status %s - should be %s\n", \
38 __location__, nt_errstr(status), nt_errstr(correct)); \
43 #define CHECK_VALUE(v, correct) do { \
44 if ((v) != (correct)) { \
45 printf("(%s) Incorrect value %s=%d - should be %d\n", \
46 __location__, #v, v, correct); \
51 #define CHECK_NOT_VALUE(v, correct) do { \
52 if ((v) == (correct)) { \
53 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
54 __location__, #v, v, correct); \
63 static bool test_session(struct smbcli_state
*cli
, struct torture_context
*tctx
)
67 struct smbcli_session
*session
;
68 struct smbcli_session
*session2
;
69 struct smbcli_session
*session3
;
70 struct smbcli_session
*session4
;
71 struct cli_credentials
*anon_creds
;
72 struct smbcli_session
*sessions
[15];
73 struct composite_context
*composite_contexts
[15];
74 struct smbcli_tree
*tree
;
75 struct smb_composite_sesssetup setup
;
76 struct smb_composite_sesssetup setups
[15];
77 struct gensec_settings
*gensec_settings
;
82 const char *fname
= BASEDIR
"\\test.txt";
85 struct smbcli_session_options options
;
87 printf("TESTING SESSION HANDLING\n");
89 if (!torture_setup_dir(cli
, BASEDIR
)) {
93 printf("create a second security context on the same transport\n");
95 lp_smbcli_session_options(tctx
->lp_ctx
, &options
);
96 gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
98 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
100 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
101 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
102 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
104 setup
.in
.credentials
= cmdline_credentials
;
105 setup
.in
.gensec_settings
= gensec_settings
;
107 status
= smb_composite_sesssetup(session
, &setup
);
108 CHECK_STATUS(status
, NT_STATUS_OK
);
110 session
->vuid
= setup
.out
.vuid
;
112 printf("create a third security context on the same transport, with vuid set\n");
113 session2
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
115 session2
->vuid
= session
->vuid
;
116 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
117 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
118 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
120 setup
.in
.credentials
= cmdline_credentials
;
122 status
= smb_composite_sesssetup(session2
, &setup
);
123 CHECK_STATUS(status
, NT_STATUS_OK
);
125 session2
->vuid
= setup
.out
.vuid
;
126 printf("vuid1=%d vuid2=%d vuid3=%d\n", cli
->session
->vuid
, session
->vuid
, session2
->vuid
);
128 if (cli
->transport
->negotiate
.capabilities
& CAP_EXTENDED_SECURITY
) {
129 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
130 if (session2
->vuid
== session
->vuid
) {
131 printf("server allows the user to re-use an existing vuid in session setup \n");
134 CHECK_NOT_VALUE(session2
->vuid
, session
->vuid
);
136 talloc_free(session2
);
138 if (cli
->transport
->negotiate
.capabilities
& CAP_EXTENDED_SECURITY
) {
139 printf("create a fourth security context on the same transport, without extended security\n");
140 session3
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
142 session3
->vuid
= session
->vuid
;
143 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
144 setup
.in
.capabilities
&= ~CAP_EXTENDED_SECURITY
; /* force a non extended security login (should fail) */
145 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
147 setup
.in
.credentials
= cmdline_credentials
;
149 status
= smb_composite_sesssetup(session3
, &setup
);
150 CHECK_STATUS(status
, NT_STATUS_LOGON_FAILURE
);
152 printf("create a fouth anonymous security context on the same transport, without extended security\n");
153 session4
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
155 session4
->vuid
= session
->vuid
;
156 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
157 setup
.in
.capabilities
&= ~CAP_EXTENDED_SECURITY
; /* force a non extended security login (should fail) */
158 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
160 anon_creds
= cli_credentials_init(tctx
);
161 cli_credentials_set_conf(anon_creds
, tctx
->lp_ctx
);
162 cli_credentials_set_anonymous(anon_creds
);
164 setup
.in
.credentials
= anon_creds
;
166 status
= smb_composite_sesssetup(session3
, &setup
);
167 CHECK_STATUS(status
, NT_STATUS_OK
);
169 talloc_free(session4
);
172 printf("use the same tree as the existing connection\n");
173 tree
= smbcli_tree_init(session
, tctx
, false);
174 tree
->tid
= cli
->tree
->tid
;
176 printf("create a file using the new vuid\n");
177 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
178 io
.ntcreatex
.in
.root_fid
= 0;
179 io
.ntcreatex
.in
.flags
= 0;
180 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
181 io
.ntcreatex
.in
.create_options
= 0;
182 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
183 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
184 io
.ntcreatex
.in
.alloc_size
= 0;
185 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
186 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
187 io
.ntcreatex
.in
.security_flags
= 0;
188 io
.ntcreatex
.in
.fname
= fname
;
189 status
= smb_raw_open(tree
, tctx
, &io
);
190 CHECK_STATUS(status
, NT_STATUS_OK
);
191 fnum
= io
.ntcreatex
.out
.file
.fnum
;
193 printf("write using the old vuid\n");
194 wr
.generic
.level
= RAW_WRITE_WRITEX
;
195 wr
.writex
.in
.file
.fnum
= fnum
;
196 wr
.writex
.in
.offset
= 0;
197 wr
.writex
.in
.wmode
= 0;
198 wr
.writex
.in
.remaining
= 0;
199 wr
.writex
.in
.count
= 1;
200 wr
.writex
.in
.data
= &c
;
202 status
= smb_raw_write(cli
->tree
, &wr
);
203 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
205 printf("write with the new vuid\n");
206 status
= smb_raw_write(tree
, &wr
);
207 CHECK_STATUS(status
, NT_STATUS_OK
);
208 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
210 printf("logoff the new vuid\n");
211 status
= smb_raw_ulogoff(session
);
212 CHECK_STATUS(status
, NT_STATUS_OK
);
214 printf("the new vuid should not now be accessible\n");
215 status
= smb_raw_write(tree
, &wr
);
216 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
218 printf("second logoff for the new vuid should fail\n");
219 status
= smb_raw_ulogoff(session
);
220 CHECK_STATUS(status
, NT_STATUS_DOS(ERRSRV
, ERRbaduid
));
221 talloc_free(session
);
223 printf("the fnum should have been auto-closed\n");
224 cl
.close
.level
= RAW_CLOSE_CLOSE
;
225 cl
.close
.in
.file
.fnum
= fnum
;
226 cl
.close
.in
.write_time
= 0;
227 status
= smb_raw_close(cli
->tree
, &cl
);
228 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
230 printf("create %d secondary security contexts on the same transport\n",
231 (int)ARRAY_SIZE(sessions
));
232 for (i
=0; i
<ARRAY_SIZE(sessions
); i
++) {
233 setups
[i
].in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
234 setups
[i
].in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
235 setups
[i
].in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
237 setups
[i
].in
.credentials
= cmdline_credentials
;
238 setups
[i
].in
.gensec_settings
= gensec_settings
;
240 sessions
[i
] = smbcli_session_init(cli
->transport
, tctx
, false, options
);
241 composite_contexts
[i
] = smb_composite_sesssetup_send(sessions
[i
], &setups
[i
]);
246 printf("finishing %d secondary security contexts on the same transport\n",
247 (int)ARRAY_SIZE(sessions
));
248 for (i
=0; i
< ARRAY_SIZE(sessions
); i
++) {
249 status
= smb_composite_sesssetup_recv(composite_contexts
[i
]);
250 CHECK_STATUS(status
, NT_STATUS_OK
);
251 sessions
[i
]->vuid
= setups
[i
].out
.vuid
;
252 printf("VUID: %d\n", sessions
[i
]->vuid
);
253 status
= smb_raw_ulogoff(sessions
[i
]);
254 CHECK_STATUS(status
, NT_STATUS_OK
);
268 static bool test_tree(struct smbcli_state
*cli
, struct torture_context
*tctx
)
272 const char *share
, *host
;
273 struct smbcli_tree
*tree
;
279 const char *fname
= BASEDIR
"\\test.txt";
282 printf("TESTING TREE HANDLING\n");
284 if (!torture_setup_dir(cli
, BASEDIR
)) {
288 share
= torture_setting_string(tctx
, "share", NULL
);
289 host
= torture_setting_string(tctx
, "host", NULL
);
291 printf("create a second tree context on the same session\n");
292 tree
= smbcli_tree_init(cli
->session
, tctx
, false);
294 tcon
.generic
.level
= RAW_TCON_TCONX
;
295 tcon
.tconx
.in
.flags
= 0;
296 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
297 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
298 tcon
.tconx
.in
.device
= "A:";
299 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
300 CHECK_STATUS(status
, NT_STATUS_OK
);
303 tree
->tid
= tcon
.tconx
.out
.tid
;
304 printf("tid1=%d tid2=%d\n", cli
->tree
->tid
, tree
->tid
);
306 printf("try a tconx with a bad device type\n");
307 tcon
.tconx
.in
.device
= "FOO";
308 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
309 CHECK_STATUS(status
, NT_STATUS_BAD_DEVICE_TYPE
);
312 printf("create a file using the new tid\n");
313 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
314 io
.ntcreatex
.in
.root_fid
= 0;
315 io
.ntcreatex
.in
.flags
= 0;
316 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
317 io
.ntcreatex
.in
.create_options
= 0;
318 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
319 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
320 io
.ntcreatex
.in
.alloc_size
= 0;
321 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
322 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
323 io
.ntcreatex
.in
.security_flags
= 0;
324 io
.ntcreatex
.in
.fname
= fname
;
325 status
= smb_raw_open(tree
, tctx
, &io
);
326 CHECK_STATUS(status
, NT_STATUS_OK
);
327 fnum
= io
.ntcreatex
.out
.file
.fnum
;
329 printf("write using the old tid\n");
330 wr
.generic
.level
= RAW_WRITE_WRITEX
;
331 wr
.writex
.in
.file
.fnum
= fnum
;
332 wr
.writex
.in
.offset
= 0;
333 wr
.writex
.in
.wmode
= 0;
334 wr
.writex
.in
.remaining
= 0;
335 wr
.writex
.in
.count
= 1;
336 wr
.writex
.in
.data
= &c
;
338 status
= smb_raw_write(cli
->tree
, &wr
);
339 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
341 printf("write with the new tid\n");
342 status
= smb_raw_write(tree
, &wr
);
343 CHECK_STATUS(status
, NT_STATUS_OK
);
344 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
346 printf("disconnect the new tid\n");
347 status
= smb_tree_disconnect(tree
);
348 CHECK_STATUS(status
, NT_STATUS_OK
);
350 printf("the new tid should not now be accessible\n");
351 status
= smb_raw_write(tree
, &wr
);
352 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
354 printf("the fnum should have been auto-closed\n");
355 cl
.close
.level
= RAW_CLOSE_CLOSE
;
356 cl
.close
.in
.file
.fnum
= fnum
;
357 cl
.close
.in
.write_time
= 0;
358 status
= smb_raw_close(cli
->tree
, &cl
);
359 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
361 /* close down the new tree */
369 test tree with ulogoff
370 this demonstrates that a tcon isn't autoclosed by a ulogoff
371 the tcon can be reused using any other valid session later
373 static bool test_tree_ulogoff(struct smbcli_state
*cli
, struct torture_context
*tctx
)
377 const char *share
, *host
;
378 struct smbcli_session
*session1
;
379 struct smbcli_session
*session2
;
380 struct smb_composite_sesssetup setup
;
381 struct smbcli_tree
*tree
;
386 const char *fname1
= BASEDIR
"\\test1.txt";
387 const char *fname2
= BASEDIR
"\\test2.txt";
389 struct smbcli_session_options options
;
391 printf("TESTING TREE with ulogoff\n");
393 if (!torture_setup_dir(cli
, BASEDIR
)) {
397 share
= torture_setting_string(tctx
, "share", NULL
);
398 host
= torture_setting_string(tctx
, "host", NULL
);
400 lp_smbcli_session_options(tctx
->lp_ctx
, &options
);
402 printf("create the first new sessions\n");
403 session1
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
404 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
405 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
406 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
407 setup
.in
.credentials
= cmdline_credentials
;
408 setup
.in
.gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
409 status
= smb_composite_sesssetup(session1
, &setup
);
410 CHECK_STATUS(status
, NT_STATUS_OK
);
411 session1
->vuid
= setup
.out
.vuid
;
412 printf("vuid1=%d\n", session1
->vuid
);
414 printf("create a tree context on the with vuid1\n");
415 tree
= smbcli_tree_init(session1
, tctx
, false);
416 tcon
.generic
.level
= RAW_TCON_TCONX
;
417 tcon
.tconx
.in
.flags
= 0;
418 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
419 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
420 tcon
.tconx
.in
.device
= "A:";
421 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
422 CHECK_STATUS(status
, NT_STATUS_OK
);
423 tree
->tid
= tcon
.tconx
.out
.tid
;
424 printf("tid=%d\n", tree
->tid
);
426 printf("create a file using vuid1\n");
427 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
428 io
.ntcreatex
.in
.root_fid
= 0;
429 io
.ntcreatex
.in
.flags
= 0;
430 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
431 io
.ntcreatex
.in
.create_options
= 0;
432 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
433 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
434 io
.ntcreatex
.in
.alloc_size
= 0;
435 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
436 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
437 io
.ntcreatex
.in
.security_flags
= 0;
438 io
.ntcreatex
.in
.fname
= fname1
;
439 status
= smb_raw_open(tree
, tctx
, &io
);
440 CHECK_STATUS(status
, NT_STATUS_OK
);
441 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
443 printf("write using vuid1\n");
444 wr
.generic
.level
= RAW_WRITE_WRITEX
;
445 wr
.writex
.in
.file
.fnum
= fnum1
;
446 wr
.writex
.in
.offset
= 0;
447 wr
.writex
.in
.wmode
= 0;
448 wr
.writex
.in
.remaining
= 0;
449 wr
.writex
.in
.count
= 1;
450 wr
.writex
.in
.data
= &c
;
451 status
= smb_raw_write(tree
, &wr
);
452 CHECK_STATUS(status
, NT_STATUS_OK
);
453 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
455 printf("ulogoff the vuid1\n");
456 status
= smb_raw_ulogoff(session1
);
457 CHECK_STATUS(status
, NT_STATUS_OK
);
459 printf("create the second new sessions\n");
460 session2
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
461 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
462 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
463 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
464 setup
.in
.credentials
= cmdline_credentials
;
465 setup
.in
.gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
466 status
= smb_composite_sesssetup(session2
, &setup
);
467 CHECK_STATUS(status
, NT_STATUS_OK
);
468 session2
->vuid
= setup
.out
.vuid
;
469 printf("vuid2=%d\n", session2
->vuid
);
471 printf("use the existing tree with vuid2\n");
472 tree
->session
= session2
;
474 printf("create a file using vuid2\n");
475 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
476 io
.ntcreatex
.in
.root_fid
= 0;
477 io
.ntcreatex
.in
.flags
= 0;
478 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
479 io
.ntcreatex
.in
.create_options
= 0;
480 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
481 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
482 io
.ntcreatex
.in
.alloc_size
= 0;
483 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
484 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
485 io
.ntcreatex
.in
.security_flags
= 0;
486 io
.ntcreatex
.in
.fname
= fname2
;
487 status
= smb_raw_open(tree
, tctx
, &io
);
488 CHECK_STATUS(status
, NT_STATUS_OK
);
489 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
491 printf("write using vuid2\n");
492 wr
.generic
.level
= RAW_WRITE_WRITEX
;
493 wr
.writex
.in
.file
.fnum
= fnum2
;
494 wr
.writex
.in
.offset
= 0;
495 wr
.writex
.in
.wmode
= 0;
496 wr
.writex
.in
.remaining
= 0;
497 wr
.writex
.in
.count
= 1;
498 wr
.writex
.in
.data
= &c
;
499 status
= smb_raw_write(tree
, &wr
);
500 CHECK_STATUS(status
, NT_STATUS_OK
);
501 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
503 printf("ulogoff the vuid2\n");
504 status
= smb_raw_ulogoff(session2
);
505 CHECK_STATUS(status
, NT_STATUS_OK
);
507 /* this also demonstrates that SMBtdis doesn't need a valid vuid */
508 printf("disconnect the existing tree connection\n");
509 status
= smb_tree_disconnect(tree
);
510 CHECK_STATUS(status
, NT_STATUS_OK
);
512 printf("disconnect the existing tree connection\n");
513 status
= smb_tree_disconnect(tree
);
514 CHECK_STATUS(status
, NT_STATUS_DOS(ERRSRV
,ERRinvnid
));
516 /* close down the new tree */
525 this test demonstrates that exit() only sees the PID
526 used for the open() calls
528 static bool test_pid_exit_only_sees_open(struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
536 const char *fname
= BASEDIR
"\\test.txt";
540 printf("TESTING PID HANDLING exit() only cares about open() PID\n");
542 if (!torture_setup_dir(cli
, BASEDIR
)) {
546 pid1
= cli
->session
->pid
;
549 printf("pid1=%d pid2=%d\n", pid1
, pid2
);
551 printf("create a file using pid1\n");
552 cli
->session
->pid
= pid1
;
553 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
554 io
.ntcreatex
.in
.root_fid
= 0;
555 io
.ntcreatex
.in
.flags
= 0;
556 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
557 io
.ntcreatex
.in
.create_options
= 0;
558 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
559 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
560 io
.ntcreatex
.in
.alloc_size
= 0;
561 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
562 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
563 io
.ntcreatex
.in
.security_flags
= 0;
564 io
.ntcreatex
.in
.fname
= fname
;
565 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
566 CHECK_STATUS(status
, NT_STATUS_OK
);
567 fnum
= io
.ntcreatex
.out
.file
.fnum
;
569 printf("write using pid2\n");
570 cli
->session
->pid
= pid2
;
571 wr
.generic
.level
= RAW_WRITE_WRITEX
;
572 wr
.writex
.in
.file
.fnum
= fnum
;
573 wr
.writex
.in
.offset
= 0;
574 wr
.writex
.in
.wmode
= 0;
575 wr
.writex
.in
.remaining
= 0;
576 wr
.writex
.in
.count
= 1;
577 wr
.writex
.in
.data
= &c
;
578 status
= smb_raw_write(cli
->tree
, &wr
);
579 CHECK_STATUS(status
, NT_STATUS_OK
);
580 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
582 printf("exit pid2\n");
583 cli
->session
->pid
= pid2
;
584 status
= smb_raw_exit(cli
->session
);
585 CHECK_STATUS(status
, NT_STATUS_OK
);
587 printf("the fnum should still be accessible via pid2\n");
588 cli
->session
->pid
= pid2
;
589 status
= smb_raw_write(cli
->tree
, &wr
);
590 CHECK_STATUS(status
, NT_STATUS_OK
);
591 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
593 printf("exit pid2\n");
594 cli
->session
->pid
= pid2
;
595 status
= smb_raw_exit(cli
->session
);
596 CHECK_STATUS(status
, NT_STATUS_OK
);
598 printf("the fnum should still be accessible via pid1 and pid2\n");
599 cli
->session
->pid
= pid1
;
600 status
= smb_raw_write(cli
->tree
, &wr
);
601 CHECK_STATUS(status
, NT_STATUS_OK
);
602 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
603 cli
->session
->pid
= pid2
;
604 status
= smb_raw_write(cli
->tree
, &wr
);
605 CHECK_STATUS(status
, NT_STATUS_OK
);
606 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
608 printf("exit pid1\n");
609 cli
->session
->pid
= pid1
;
610 status
= smb_raw_exit(cli
->session
);
611 CHECK_STATUS(status
, NT_STATUS_OK
);
613 printf("the fnum should not now be accessible via pid1 or pid2\n");
614 cli
->session
->pid
= pid1
;
615 status
= smb_raw_write(cli
->tree
, &wr
);
616 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
617 cli
->session
->pid
= pid2
;
618 status
= smb_raw_write(cli
->tree
, &wr
);
619 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
621 printf("the fnum should have been auto-closed\n");
622 cli
->session
->pid
= pid1
;
623 cl
.close
.level
= RAW_CLOSE_CLOSE
;
624 cl
.close
.in
.file
.fnum
= fnum
;
625 cl
.close
.in
.write_time
= 0;
626 status
= smb_raw_close(cli
->tree
, &cl
);
627 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
634 test pid ops with 2 sessions
636 static bool test_pid_2sess(struct smbcli_state
*cli
, struct torture_context
*tctx
)
640 struct smbcli_session
*session
;
641 struct smb_composite_sesssetup setup
;
646 const char *fname
= BASEDIR
"\\test.txt";
648 uint16_t vuid1
, vuid2
;
649 struct smbcli_session_options options
;
651 printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
653 if (!torture_setup_dir(cli
, BASEDIR
)) {
657 lp_smbcli_session_options(tctx
->lp_ctx
, &options
);
659 printf("create a second security context on the same transport\n");
660 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
662 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
663 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
664 setup
.in
.workgroup
= lp_workgroup(tctx
->lp_ctx
);
665 setup
.in
.credentials
= cmdline_credentials
;
666 setup
.in
.gensec_settings
= lp_gensec_settings(tctx
, tctx
->lp_ctx
);
668 status
= smb_composite_sesssetup(session
, &setup
);
669 CHECK_STATUS(status
, NT_STATUS_OK
);
670 session
->vuid
= setup
.out
.vuid
;
672 vuid1
= cli
->session
->vuid
;
673 vuid2
= session
->vuid
;
675 printf("vuid1=%d vuid2=%d\n", vuid1
, vuid2
);
677 printf("create a file using the vuid1\n");
678 cli
->session
->vuid
= vuid1
;
679 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
680 io
.ntcreatex
.in
.root_fid
= 0;
681 io
.ntcreatex
.in
.flags
= 0;
682 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
683 io
.ntcreatex
.in
.create_options
= 0;
684 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
685 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
686 io
.ntcreatex
.in
.alloc_size
= 0;
687 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
688 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
689 io
.ntcreatex
.in
.security_flags
= 0;
690 io
.ntcreatex
.in
.fname
= fname
;
691 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
692 CHECK_STATUS(status
, NT_STATUS_OK
);
693 fnum
= io
.ntcreatex
.out
.file
.fnum
;
695 printf("write using the vuid1 (fnum=%d)\n", fnum
);
696 cli
->session
->vuid
= vuid1
;
697 wr
.generic
.level
= RAW_WRITE_WRITEX
;
698 wr
.writex
.in
.file
.fnum
= fnum
;
699 wr
.writex
.in
.offset
= 0;
700 wr
.writex
.in
.wmode
= 0;
701 wr
.writex
.in
.remaining
= 0;
702 wr
.writex
.in
.count
= 1;
703 wr
.writex
.in
.data
= &c
;
705 status
= smb_raw_write(cli
->tree
, &wr
);
706 CHECK_STATUS(status
, NT_STATUS_OK
);
707 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
709 printf("exit the pid with vuid2\n");
710 cli
->session
->vuid
= vuid2
;
711 status
= smb_raw_exit(cli
->session
);
712 CHECK_STATUS(status
, NT_STATUS_OK
);
714 printf("the fnum should still be accessible\n");
715 cli
->session
->vuid
= vuid1
;
716 status
= smb_raw_write(cli
->tree
, &wr
);
717 CHECK_STATUS(status
, NT_STATUS_OK
);
718 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
720 printf("exit the pid with vuid1\n");
721 cli
->session
->vuid
= vuid1
;
722 status
= smb_raw_exit(cli
->session
);
723 CHECK_STATUS(status
, NT_STATUS_OK
);
725 printf("the fnum should not now be accessible\n");
726 status
= smb_raw_write(cli
->tree
, &wr
);
727 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
729 printf("the fnum should have been auto-closed\n");
730 cl
.close
.level
= RAW_CLOSE_CLOSE
;
731 cl
.close
.in
.file
.fnum
= fnum
;
732 cl
.close
.in
.write_time
= 0;
733 status
= smb_raw_close(cli
->tree
, &cl
);
734 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
741 test pid ops with 2 tcons
743 static bool test_pid_2tcon(struct smbcli_state
*cli
, struct torture_context
*tctx
)
747 const char *share
, *host
;
748 struct smbcli_tree
*tree
;
754 const char *fname1
= BASEDIR
"\\test1.txt";
755 const char *fname2
= BASEDIR
"\\test2.txt";
759 printf("TESTING PID HANDLING WITH 2 TCONS\n");
761 if (!torture_setup_dir(cli
, BASEDIR
)) {
765 share
= torture_setting_string(tctx
, "share", NULL
);
766 host
= torture_setting_string(tctx
, "host", NULL
);
768 printf("create a second tree context on the same session\n");
769 tree
= smbcli_tree_init(cli
->session
, tctx
, false);
771 tcon
.generic
.level
= RAW_TCON_TCONX
;
772 tcon
.tconx
.in
.flags
= 0;
773 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
774 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
775 tcon
.tconx
.in
.device
= "A:";
776 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
777 CHECK_STATUS(status
, NT_STATUS_OK
);
779 tree
->tid
= tcon
.tconx
.out
.tid
;
781 tid1
= cli
->tree
->tid
;
783 printf("tid1=%d tid2=%d\n", tid1
, tid2
);
785 printf("create a file using the tid1\n");
786 cli
->tree
->tid
= tid1
;
787 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
788 io
.ntcreatex
.in
.root_fid
= 0;
789 io
.ntcreatex
.in
.flags
= 0;
790 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
791 io
.ntcreatex
.in
.create_options
= 0;
792 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
793 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
794 io
.ntcreatex
.in
.alloc_size
= 0;
795 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
796 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
797 io
.ntcreatex
.in
.security_flags
= 0;
798 io
.ntcreatex
.in
.fname
= fname1
;
799 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
800 CHECK_STATUS(status
, NT_STATUS_OK
);
801 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
803 printf("write using the tid1\n");
804 wr
.generic
.level
= RAW_WRITE_WRITEX
;
805 wr
.writex
.in
.file
.fnum
= fnum1
;
806 wr
.writex
.in
.offset
= 0;
807 wr
.writex
.in
.wmode
= 0;
808 wr
.writex
.in
.remaining
= 0;
809 wr
.writex
.in
.count
= 1;
810 wr
.writex
.in
.data
= &c
;
812 status
= smb_raw_write(cli
->tree
, &wr
);
813 CHECK_STATUS(status
, NT_STATUS_OK
);
814 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
816 printf("create a file using the tid2\n");
817 cli
->tree
->tid
= tid2
;
818 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
819 io
.ntcreatex
.in
.root_fid
= 0;
820 io
.ntcreatex
.in
.flags
= 0;
821 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
822 io
.ntcreatex
.in
.create_options
= 0;
823 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
824 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
825 io
.ntcreatex
.in
.alloc_size
= 0;
826 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
827 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
828 io
.ntcreatex
.in
.security_flags
= 0;
829 io
.ntcreatex
.in
.fname
= fname2
;
830 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
831 CHECK_STATUS(status
, NT_STATUS_OK
);
832 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
834 printf("write using the tid2\n");
835 wr
.generic
.level
= RAW_WRITE_WRITEX
;
836 wr
.writex
.in
.file
.fnum
= fnum2
;
837 wr
.writex
.in
.offset
= 0;
838 wr
.writex
.in
.wmode
= 0;
839 wr
.writex
.in
.remaining
= 0;
840 wr
.writex
.in
.count
= 1;
841 wr
.writex
.in
.data
= &c
;
843 status
= smb_raw_write(cli
->tree
, &wr
);
844 CHECK_STATUS(status
, NT_STATUS_OK
);
845 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
847 printf("exit the pid\n");
848 status
= smb_raw_exit(cli
->session
);
849 CHECK_STATUS(status
, NT_STATUS_OK
);
851 printf("the fnum1 on tid1 should not be accessible\n");
852 cli
->tree
->tid
= tid1
;
853 wr
.writex
.in
.file
.fnum
= fnum1
;
854 status
= smb_raw_write(cli
->tree
, &wr
);
855 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
857 printf("the fnum1 on tid1 should have been auto-closed\n");
858 cl
.close
.level
= RAW_CLOSE_CLOSE
;
859 cl
.close
.in
.file
.fnum
= fnum1
;
860 cl
.close
.in
.write_time
= 0;
861 status
= smb_raw_close(cli
->tree
, &cl
);
862 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
864 printf("the fnum2 on tid2 should not be accessible\n");
865 cli
->tree
->tid
= tid2
;
866 wr
.writex
.in
.file
.fnum
= fnum2
;
867 status
= smb_raw_write(cli
->tree
, &wr
);
868 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
870 printf("the fnum2 on tid2 should have been auto-closed\n");
871 cl
.close
.level
= RAW_CLOSE_CLOSE
;
872 cl
.close
.in
.file
.fnum
= fnum2
;
873 cl
.close
.in
.write_time
= 0;
874 status
= smb_raw_close(cli
->tree
, &cl
);
875 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
883 basic testing of session/tree context calls
885 static bool torture_raw_context_int(struct torture_context
*tctx
,
886 struct smbcli_state
*cli
)
890 ret
&= test_session(cli
, tctx
);
891 ret
&= test_tree(cli
, tctx
);
892 ret
&= test_tree_ulogoff(cli
, tctx
);
893 ret
&= test_pid_exit_only_sees_open(cli
, tctx
);
894 ret
&= test_pid_2sess(cli
, tctx
);
895 ret
&= test_pid_2tcon(cli
, tctx
);
897 smb_raw_exit(cli
->session
);
898 smbcli_deltree(cli
->tree
, BASEDIR
);
903 basic testing of session/tree context calls
905 bool torture_raw_context(struct torture_context
*torture
,
906 struct smbcli_state
*cli
)
909 if (lp_use_spnego(torture
->lp_ctx
)) {
910 ret
&= torture_raw_context_int(torture
, cli
);
911 lp_set_cmdline(torture
->lp_ctx
, "use spnego", "False");
914 ret
&= torture_raw_context_int(torture
, cli
);