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/cmdline.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 torture_context
*tctx
,
49 struct smbcli_state
*cli
)
53 struct smbcli_session
*session
;
54 struct smbcli_session
*session2
;
56 struct smbcli_session
*session3
;
57 struct smbcli_session
*session4
;
58 struct cli_credentials
*anon_creds
;
59 struct smbcli_session
*sessions
[15];
60 struct composite_context
*composite_contexts
[15];
61 struct smbcli_tree
*tree
;
62 struct smb_composite_sesssetup setup
;
63 struct smb_composite_sesssetup setups
[15];
64 struct gensec_settings
*gensec_settings
;
69 const char *fname
= BASEDIR
"\\test.txt";
72 struct smbcli_session_options options
;
74 torture_comment(tctx
, "TESTING SESSION HANDLING\n");
76 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " 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
= samba_cmdline_get_creds();
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 given vuid\n");
98 session2
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
100 if (cli
->transport
->negotiate
.capabilities
& CAP_EXTENDED_SECURITY
) {
101 vuid3
= session
->vuid
+1;
102 if (vuid3
== cli
->session
->vuid
) {
105 if (vuid3
== UINT16_MAX
) {
109 vuid3
= session
->vuid
;
111 session2
->vuid
= vuid3
;
113 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
114 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
115 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
117 setup
.in
.credentials
= samba_cmdline_get_creds();
119 torture_comment(tctx
, "vuid1=%d vuid2=%d vuid3=%d\n", cli
->session
->vuid
, session
->vuid
, vuid3
);
121 status
= smb_composite_sesssetup(session2
, &setup
);
122 if (cli
->transport
->negotiate
.capabilities
& CAP_EXTENDED_SECURITY
) {
123 CHECK_STATUS(status
, NT_STATUS_DOS(ERRSRV
, ERRbaduid
));
125 CHECK_STATUS(status
, NT_STATUS_OK
);
126 session2
->vuid
= setup
.out
.vuid
;
127 CHECK_NOT_VALUE(session2
->vuid
, vuid3
);
130 torture_comment(tctx
, "vuid1=%d vuid2=%d vuid3=%d=>%d (%s)\n",
131 cli
->session
->vuid
, session
->vuid
,
132 vuid3
, session2
->vuid
, nt_errstr(status
));
134 talloc_free(session2
);
136 if (cli
->transport
->negotiate
.capabilities
& CAP_EXTENDED_SECURITY
) {
137 torture_comment(tctx
, "create a fourth security context on the same transport, without extended security\n");
138 session3
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
140 session3
->vuid
= vuid3
;
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 setup
.in
.credentials
= samba_cmdline_get_creds();
147 status
= smb_composite_sesssetup(session3
, &setup
);
148 if (!NT_STATUS_EQUAL(status
, NT_STATUS_LOGON_FAILURE
)) {
150 * Windows 2008 R2 returns INVALID_PARAMETER
151 * while Windows 2000 sp4 returns LOGON_FAILURE...
153 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
156 torture_comment(tctx
, "create a fouth anonymous security context on the same transport, without extended security\n");
157 session4
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
159 session4
->vuid
= vuid3
;
160 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
161 setup
.in
.capabilities
&= ~CAP_EXTENDED_SECURITY
; /* force a non extended security login (should fail) */
162 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
164 anon_creds
= cli_credentials_init(tctx
);
165 cli_credentials_set_conf(anon_creds
, tctx
->lp_ctx
);
166 cli_credentials_set_anonymous(anon_creds
);
168 setup
.in
.credentials
= anon_creds
;
170 status
= smb_composite_sesssetup(session3
, &setup
);
171 CHECK_STATUS(status
, NT_STATUS_OK
);
173 talloc_free(session4
);
176 torture_comment(tctx
, "use the same tree as the existing connection\n");
177 tree
= smbcli_tree_init(session
, tctx
, false);
178 tree
->tid
= cli
->tree
->tid
;
180 torture_comment(tctx
, "create a file using the new vuid\n");
181 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
182 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
183 io
.ntcreatex
.in
.flags
= 0;
184 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
185 io
.ntcreatex
.in
.create_options
= 0;
186 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
187 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
188 io
.ntcreatex
.in
.alloc_size
= 0;
189 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
190 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
191 io
.ntcreatex
.in
.security_flags
= 0;
192 io
.ntcreatex
.in
.fname
= fname
;
193 status
= smb_raw_open(tree
, tctx
, &io
);
194 CHECK_STATUS(status
, NT_STATUS_OK
);
195 fnum
= io
.ntcreatex
.out
.file
.fnum
;
197 torture_comment(tctx
, "write using the old vuid\n");
198 wr
.generic
.level
= RAW_WRITE_WRITEX
;
199 wr
.writex
.in
.file
.fnum
= fnum
;
200 wr
.writex
.in
.offset
= 0;
201 wr
.writex
.in
.wmode
= 0;
202 wr
.writex
.in
.remaining
= 0;
203 wr
.writex
.in
.count
= 1;
204 wr
.writex
.in
.data
= &c
;
206 status
= smb_raw_write(cli
->tree
, &wr
);
207 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
209 torture_comment(tctx
, "write with the new vuid\n");
210 status
= smb_raw_write(tree
, &wr
);
211 CHECK_STATUS(status
, NT_STATUS_OK
);
212 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
214 torture_comment(tctx
, "logoff the new vuid\n");
215 status
= smb_raw_ulogoff(session
);
216 CHECK_STATUS(status
, NT_STATUS_OK
);
218 torture_comment(tctx
, "the new vuid should not now be accessible\n");
219 status
= smb_raw_write(tree
, &wr
);
220 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
222 torture_comment(tctx
, "second logoff for the new vuid should fail\n");
223 status
= smb_raw_ulogoff(session
);
224 CHECK_STATUS(status
, NT_STATUS_DOS(ERRSRV
, ERRbaduid
));
226 talloc_free(session
);
228 torture_comment(tctx
, "the fnum should have been auto-closed\n");
229 cl
.close
.level
= RAW_CLOSE_CLOSE
;
230 cl
.close
.in
.file
.fnum
= fnum
;
231 cl
.close
.in
.write_time
= 0;
232 status
= smb_raw_close(cli
->tree
, &cl
);
233 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
235 torture_comment(tctx
, "create %d secondary security contexts on the same transport\n",
236 (int)ARRAY_SIZE(sessions
));
237 for (i
=0; i
<ARRAY_SIZE(sessions
); i
++) {
238 setups
[i
].in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
239 setups
[i
].in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
240 setups
[i
].in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
242 setups
[i
].in
.credentials
= samba_cmdline_get_creds();
243 setups
[i
].in
.gensec_settings
= gensec_settings
;
245 sessions
[i
] = smbcli_session_init(cli
->transport
, tctx
, false, options
);
246 composite_contexts
[i
] = smb_composite_sesssetup_send(sessions
[i
], &setups
[i
]);
251 torture_comment(tctx
, "finishing %d secondary security contexts on the same transport\n",
252 (int)ARRAY_SIZE(sessions
));
253 for (i
=0; i
< ARRAY_SIZE(sessions
); i
++) {
254 status
= smb_composite_sesssetup_recv(composite_contexts
[i
]);
255 CHECK_STATUS(status
, NT_STATUS_OK
);
256 sessions
[i
]->vuid
= setups
[i
].out
.vuid
;
257 torture_comment(tctx
, "VUID: %d\n", sessions
[i
]->vuid
);
258 status
= smb_raw_ulogoff(sessions
[i
]);
259 CHECK_STATUS(status
, NT_STATUS_OK
);
270 static bool test_tree(struct torture_context
*tctx
, struct smbcli_state
*cli
)
274 const char *share
, *host
;
275 struct smbcli_tree
*tree
;
281 const char *fname
= BASEDIR
"\\test.txt";
284 torture_comment(tctx
, "TESTING TREE HANDLING\n");
286 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
288 share
= torture_setting_string(tctx
, "share", NULL
);
289 host
= torture_setting_string(tctx
, "host", NULL
);
291 torture_comment(tctx
, "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
= TCONX_FLAG_EXTENDED_RESPONSE
;
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 torture_comment(tctx
, "tid1=%d tid2=%d\n", cli
->tree
->tid
, tree
->tid
);
306 torture_comment(tctx
, "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 torture_comment(tctx
, "create a file using the new tid\n");
313 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
314 io
.ntcreatex
.in
.root_fid
.fnum
= 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 torture_comment(tctx
, "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 torture_comment(tctx
, "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 torture_comment(tctx
, "disconnect the new tid\n");
347 status
= smb_tree_disconnect(tree
);
348 CHECK_STATUS(status
, NT_STATUS_OK
);
350 torture_comment(tctx
, "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 torture_comment(tctx
, "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 torture_context
*tctx
, struct smbcli_state
*cli
)
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 torture_comment(tctx
, "TESTING TREE with ulogoff\n");
393 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
395 share
= torture_setting_string(tctx
, "share", NULL
);
396 host
= torture_setting_string(tctx
, "host", NULL
);
398 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
400 torture_comment(tctx
, "create the first new sessions\n");
401 session1
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
402 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
403 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
404 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
405 setup
.in
.credentials
= samba_cmdline_get_creds();
406 setup
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
407 status
= smb_composite_sesssetup(session1
, &setup
);
408 CHECK_STATUS(status
, NT_STATUS_OK
);
409 session1
->vuid
= setup
.out
.vuid
;
410 torture_comment(tctx
, "vuid1=%d\n", session1
->vuid
);
412 torture_comment(tctx
, "create a tree context on the with vuid1\n");
413 tree
= smbcli_tree_init(session1
, tctx
, false);
414 tcon
.generic
.level
= RAW_TCON_TCONX
;
415 tcon
.tconx
.in
.flags
= TCONX_FLAG_EXTENDED_RESPONSE
;
416 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
417 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
418 tcon
.tconx
.in
.device
= "A:";
419 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
420 CHECK_STATUS(status
, NT_STATUS_OK
);
421 tree
->tid
= tcon
.tconx
.out
.tid
;
422 torture_comment(tctx
, "tid=%d\n", tree
->tid
);
424 torture_comment(tctx
, "create a file using vuid1\n");
425 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
426 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
427 io
.ntcreatex
.in
.flags
= 0;
428 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
429 io
.ntcreatex
.in
.create_options
= 0;
430 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
431 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
432 io
.ntcreatex
.in
.alloc_size
= 0;
433 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
434 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
435 io
.ntcreatex
.in
.security_flags
= 0;
436 io
.ntcreatex
.in
.fname
= fname1
;
437 status
= smb_raw_open(tree
, tctx
, &io
);
438 CHECK_STATUS(status
, NT_STATUS_OK
);
439 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
441 torture_comment(tctx
, "write using vuid1\n");
442 wr
.generic
.level
= RAW_WRITE_WRITEX
;
443 wr
.writex
.in
.file
.fnum
= fnum1
;
444 wr
.writex
.in
.offset
= 0;
445 wr
.writex
.in
.wmode
= 0;
446 wr
.writex
.in
.remaining
= 0;
447 wr
.writex
.in
.count
= 1;
448 wr
.writex
.in
.data
= &c
;
449 status
= smb_raw_write(tree
, &wr
);
450 CHECK_STATUS(status
, NT_STATUS_OK
);
451 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
453 torture_comment(tctx
, "ulogoff the vuid1\n");
454 status
= smb_raw_ulogoff(session1
);
455 CHECK_STATUS(status
, NT_STATUS_OK
);
457 torture_comment(tctx
, "create the second new sessions\n");
458 session2
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
459 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
460 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
461 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
462 setup
.in
.credentials
= samba_cmdline_get_creds();
463 setup
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
464 status
= smb_composite_sesssetup(session2
, &setup
);
465 CHECK_STATUS(status
, NT_STATUS_OK
);
466 session2
->vuid
= setup
.out
.vuid
;
467 torture_comment(tctx
, "vuid2=%d\n", session2
->vuid
);
469 torture_comment(tctx
, "use the existing tree with vuid2\n");
470 tree
->session
= session2
;
472 torture_comment(tctx
, "create a file using vuid2\n");
473 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
474 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
475 io
.ntcreatex
.in
.flags
= 0;
476 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
477 io
.ntcreatex
.in
.create_options
= 0;
478 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
479 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
480 io
.ntcreatex
.in
.alloc_size
= 0;
481 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
482 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
483 io
.ntcreatex
.in
.security_flags
= 0;
484 io
.ntcreatex
.in
.fname
= fname2
;
485 status
= smb_raw_open(tree
, tctx
, &io
);
486 CHECK_STATUS(status
, NT_STATUS_OK
);
487 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
489 torture_comment(tctx
, "write using vuid2\n");
490 wr
.generic
.level
= RAW_WRITE_WRITEX
;
491 wr
.writex
.in
.file
.fnum
= fnum2
;
492 wr
.writex
.in
.offset
= 0;
493 wr
.writex
.in
.wmode
= 0;
494 wr
.writex
.in
.remaining
= 0;
495 wr
.writex
.in
.count
= 1;
496 wr
.writex
.in
.data
= &c
;
497 status
= smb_raw_write(tree
, &wr
);
498 CHECK_STATUS(status
, NT_STATUS_OK
);
499 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
501 torture_comment(tctx
, "ulogoff the vuid2\n");
502 status
= smb_raw_ulogoff(session2
);
503 CHECK_STATUS(status
, NT_STATUS_OK
);
505 /* this also demonstrates that SMBtdis doesn't need a valid vuid */
506 torture_comment(tctx
, "disconnect the existing tree connection\n");
507 status
= smb_tree_disconnect(tree
);
508 CHECK_STATUS(status
, NT_STATUS_OK
);
510 torture_comment(tctx
, "disconnect the existing tree connection\n");
511 status
= smb_tree_disconnect(tree
);
512 CHECK_STATUS(status
, NT_STATUS_DOS(ERRSRV
,ERRinvnid
));
514 /* close down the new tree */
523 this test demonstrates that exit() only sees the PID
524 used for the open() calls
526 static bool test_pid_exit_only_sees_open(struct torture_context
*tctx
,
527 struct smbcli_state
*cli
)
530 TALLOC_CTX
*mem_ctx
= tctx
;
536 const char *fname
= BASEDIR
"\\test.txt";
540 torture_comment(tctx
, "TESTING PID HANDLING exit() only cares about open() PID\n");
542 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
544 pid1
= cli
->session
->pid
;
547 torture_comment(tctx
, "pid1=%d pid2=%d\n", pid1
, pid2
);
549 torture_comment(tctx
, "create a file using pid1\n");
550 cli
->session
->pid
= pid1
;
551 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
552 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
553 io
.ntcreatex
.in
.flags
= 0;
554 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
555 io
.ntcreatex
.in
.create_options
= 0;
556 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
557 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
558 io
.ntcreatex
.in
.alloc_size
= 0;
559 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
560 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
561 io
.ntcreatex
.in
.security_flags
= 0;
562 io
.ntcreatex
.in
.fname
= fname
;
563 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
564 CHECK_STATUS(status
, NT_STATUS_OK
);
565 fnum
= io
.ntcreatex
.out
.file
.fnum
;
567 torture_comment(tctx
, "write using pid2\n");
568 cli
->session
->pid
= pid2
;
569 wr
.generic
.level
= RAW_WRITE_WRITEX
;
570 wr
.writex
.in
.file
.fnum
= fnum
;
571 wr
.writex
.in
.offset
= 0;
572 wr
.writex
.in
.wmode
= 0;
573 wr
.writex
.in
.remaining
= 0;
574 wr
.writex
.in
.count
= 1;
575 wr
.writex
.in
.data
= &c
;
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 pid2\n");
586 cli
->session
->pid
= pid2
;
587 status
= smb_raw_write(cli
->tree
, &wr
);
588 CHECK_STATUS(status
, NT_STATUS_OK
);
589 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
591 torture_comment(tctx
, "exit pid2\n");
592 cli
->session
->pid
= pid2
;
593 status
= smb_raw_exit(cli
->session
);
594 CHECK_STATUS(status
, NT_STATUS_OK
);
596 torture_comment(tctx
, "the fnum should still be accessible via pid1 and pid2\n");
597 cli
->session
->pid
= pid1
;
598 status
= smb_raw_write(cli
->tree
, &wr
);
599 CHECK_STATUS(status
, NT_STATUS_OK
);
600 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
601 cli
->session
->pid
= pid2
;
602 status
= smb_raw_write(cli
->tree
, &wr
);
603 CHECK_STATUS(status
, NT_STATUS_OK
);
604 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
606 torture_comment(tctx
, "exit pid1\n");
607 cli
->session
->pid
= pid1
;
608 status
= smb_raw_exit(cli
->session
);
609 CHECK_STATUS(status
, NT_STATUS_OK
);
611 torture_comment(tctx
, "the fnum should not now be accessible via pid1 or pid2\n");
612 cli
->session
->pid
= pid1
;
613 status
= smb_raw_write(cli
->tree
, &wr
);
614 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
615 cli
->session
->pid
= pid2
;
616 status
= smb_raw_write(cli
->tree
, &wr
);
617 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
619 torture_comment(tctx
, "the fnum should have been auto-closed\n");
620 cli
->session
->pid
= pid1
;
621 cl
.close
.level
= RAW_CLOSE_CLOSE
;
622 cl
.close
.in
.file
.fnum
= fnum
;
623 cl
.close
.in
.write_time
= 0;
624 status
= smb_raw_close(cli
->tree
, &cl
);
625 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
632 test pid ops with 2 sessions
634 static bool test_pid_2sess(struct torture_context
*tctx
,
635 struct smbcli_state
*cli
)
639 struct smbcli_session
*session
;
640 struct smb_composite_sesssetup setup
;
645 const char *fname
= BASEDIR
"\\test.txt";
647 uint16_t vuid1
, vuid2
;
648 struct smbcli_session_options options
;
650 torture_comment(tctx
, "TESTING PID HANDLING WITH 2 SESSIONS\n");
652 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
654 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
656 torture_comment(tctx
, "create a second security context on the same transport\n");
657 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
659 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
660 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
661 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
662 setup
.in
.credentials
= samba_cmdline_get_creds();
663 setup
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
665 status
= smb_composite_sesssetup(session
, &setup
);
666 CHECK_STATUS(status
, NT_STATUS_OK
);
667 session
->vuid
= setup
.out
.vuid
;
669 vuid1
= cli
->session
->vuid
;
670 vuid2
= session
->vuid
;
672 torture_comment(tctx
, "vuid1=%d vuid2=%d\n", vuid1
, vuid2
);
674 torture_comment(tctx
, "create a file using the vuid1\n");
675 cli
->session
->vuid
= vuid1
;
676 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
677 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
678 io
.ntcreatex
.in
.flags
= 0;
679 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
680 io
.ntcreatex
.in
.create_options
= 0;
681 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
682 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
683 io
.ntcreatex
.in
.alloc_size
= 0;
684 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
685 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
686 io
.ntcreatex
.in
.security_flags
= 0;
687 io
.ntcreatex
.in
.fname
= fname
;
688 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
689 CHECK_STATUS(status
, NT_STATUS_OK
);
690 fnum
= io
.ntcreatex
.out
.file
.fnum
;
692 torture_comment(tctx
, "write using the vuid1 (fnum=%d)\n", fnum
);
693 cli
->session
->vuid
= vuid1
;
694 wr
.generic
.level
= RAW_WRITE_WRITEX
;
695 wr
.writex
.in
.file
.fnum
= fnum
;
696 wr
.writex
.in
.offset
= 0;
697 wr
.writex
.in
.wmode
= 0;
698 wr
.writex
.in
.remaining
= 0;
699 wr
.writex
.in
.count
= 1;
700 wr
.writex
.in
.data
= &c
;
702 status
= smb_raw_write(cli
->tree
, &wr
);
703 CHECK_STATUS(status
, NT_STATUS_OK
);
704 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
706 torture_comment(tctx
, "exit the pid with vuid2\n");
707 cli
->session
->vuid
= vuid2
;
708 status
= smb_raw_exit(cli
->session
);
709 CHECK_STATUS(status
, NT_STATUS_OK
);
711 torture_comment(tctx
, "the fnum should still be accessible\n");
712 cli
->session
->vuid
= vuid1
;
713 status
= smb_raw_write(cli
->tree
, &wr
);
714 CHECK_STATUS(status
, NT_STATUS_OK
);
715 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
717 torture_comment(tctx
, "exit the pid with vuid1\n");
718 cli
->session
->vuid
= vuid1
;
719 status
= smb_raw_exit(cli
->session
);
720 CHECK_STATUS(status
, NT_STATUS_OK
);
722 torture_comment(tctx
, "the fnum should not now be accessible\n");
723 status
= smb_raw_write(cli
->tree
, &wr
);
724 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
726 torture_comment(tctx
, "the fnum should have been auto-closed\n");
727 cl
.close
.level
= RAW_CLOSE_CLOSE
;
728 cl
.close
.in
.file
.fnum
= fnum
;
729 cl
.close
.in
.write_time
= 0;
730 status
= smb_raw_close(cli
->tree
, &cl
);
731 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
738 test pid ops with 2 tcons
740 static bool test_pid_2tcon(struct torture_context
*tctx
,
741 struct smbcli_state
*cli
)
745 const char *share
, *host
;
746 struct smbcli_tree
*tree
;
752 const char *fname1
= BASEDIR
"\\test1.txt";
753 const char *fname2
= BASEDIR
"\\test2.txt";
757 torture_comment(tctx
, "TESTING PID HANDLING WITH 2 TCONS\n");
759 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
761 share
= torture_setting_string(tctx
, "share", NULL
);
762 host
= torture_setting_string(tctx
, "host", NULL
);
764 torture_comment(tctx
, "create a second tree context on the same session\n");
765 tree
= smbcli_tree_init(cli
->session
, tctx
, false);
767 tcon
.generic
.level
= RAW_TCON_TCONX
;
768 tcon
.tconx
.in
.flags
= TCONX_FLAG_EXTENDED_RESPONSE
;
769 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
770 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
771 tcon
.tconx
.in
.device
= "A:";
772 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
773 CHECK_STATUS(status
, NT_STATUS_OK
);
775 tree
->tid
= tcon
.tconx
.out
.tid
;
777 tid1
= cli
->tree
->tid
;
779 torture_comment(tctx
, "tid1=%d tid2=%d\n", tid1
, tid2
);
781 torture_comment(tctx
, "create a file using the tid1\n");
782 cli
->tree
->tid
= tid1
;
783 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
784 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
785 io
.ntcreatex
.in
.flags
= 0;
786 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
787 io
.ntcreatex
.in
.create_options
= 0;
788 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
789 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
790 io
.ntcreatex
.in
.alloc_size
= 0;
791 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
792 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
793 io
.ntcreatex
.in
.security_flags
= 0;
794 io
.ntcreatex
.in
.fname
= fname1
;
795 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
796 CHECK_STATUS(status
, NT_STATUS_OK
);
797 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
799 torture_comment(tctx
, "write using the tid1\n");
800 wr
.generic
.level
= RAW_WRITE_WRITEX
;
801 wr
.writex
.in
.file
.fnum
= fnum1
;
802 wr
.writex
.in
.offset
= 0;
803 wr
.writex
.in
.wmode
= 0;
804 wr
.writex
.in
.remaining
= 0;
805 wr
.writex
.in
.count
= 1;
806 wr
.writex
.in
.data
= &c
;
808 status
= smb_raw_write(cli
->tree
, &wr
);
809 CHECK_STATUS(status
, NT_STATUS_OK
);
810 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
812 torture_comment(tctx
, "create a file using the tid2\n");
813 cli
->tree
->tid
= tid2
;
814 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
815 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
816 io
.ntcreatex
.in
.flags
= 0;
817 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
818 io
.ntcreatex
.in
.create_options
= 0;
819 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
820 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
821 io
.ntcreatex
.in
.alloc_size
= 0;
822 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
823 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
824 io
.ntcreatex
.in
.security_flags
= 0;
825 io
.ntcreatex
.in
.fname
= fname2
;
826 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
827 CHECK_STATUS(status
, NT_STATUS_OK
);
828 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
830 torture_comment(tctx
, "write using the tid2\n");
831 wr
.generic
.level
= RAW_WRITE_WRITEX
;
832 wr
.writex
.in
.file
.fnum
= fnum2
;
833 wr
.writex
.in
.offset
= 0;
834 wr
.writex
.in
.wmode
= 0;
835 wr
.writex
.in
.remaining
= 0;
836 wr
.writex
.in
.count
= 1;
837 wr
.writex
.in
.data
= &c
;
839 status
= smb_raw_write(cli
->tree
, &wr
);
840 CHECK_STATUS(status
, NT_STATUS_OK
);
841 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
843 torture_comment(tctx
, "exit the pid\n");
844 status
= smb_raw_exit(cli
->session
);
845 CHECK_STATUS(status
, NT_STATUS_OK
);
847 torture_comment(tctx
, "the fnum1 on tid1 should not be accessible\n");
848 cli
->tree
->tid
= tid1
;
849 wr
.writex
.in
.file
.fnum
= fnum1
;
850 status
= smb_raw_write(cli
->tree
, &wr
);
851 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
853 torture_comment(tctx
, "the fnum1 on tid1 should have been auto-closed\n");
854 cl
.close
.level
= RAW_CLOSE_CLOSE
;
855 cl
.close
.in
.file
.fnum
= fnum1
;
856 cl
.close
.in
.write_time
= 0;
857 status
= smb_raw_close(cli
->tree
, &cl
);
858 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
860 torture_comment(tctx
, "the fnum2 on tid2 should not be accessible\n");
861 cli
->tree
->tid
= tid2
;
862 wr
.writex
.in
.file
.fnum
= fnum2
;
863 status
= smb_raw_write(cli
->tree
, &wr
);
864 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
866 torture_comment(tctx
, "the fnum2 on tid2 should have been auto-closed\n");
867 cl
.close
.level
= RAW_CLOSE_CLOSE
;
868 cl
.close
.in
.file
.fnum
= fnum2
;
869 cl
.close
.in
.write_time
= 0;
870 status
= smb_raw_close(cli
->tree
, &cl
);
871 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
877 struct torture_suite
*torture_raw_context(TALLOC_CTX
*mem_ctx
)
879 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "context");
881 torture_suite_add_1smb_test(suite
, "session1", test_session
);
883 * TODO: add test_session with 'use spnego = false'
884 * torture_suite_add_1smb_test(suite, "session1", test_session);
886 torture_suite_add_1smb_test(suite
, "tree", test_tree
);
887 torture_suite_add_1smb_test(suite
, "tree_ulogoff", test_tree_ulogoff
);
888 torture_suite_add_1smb_test(suite
, "pid_only_sess", test_pid_exit_only_sees_open
);
889 torture_suite_add_1smb_test(suite
, "pid_2sess", test_pid_2sess
);
890 torture_suite_add_1smb_test(suite
, "pid_2tcon", test_pid_2tcon
);