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