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) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 printf("(%s) Incorrect status %s - should be %s\n", \
36 __location__, nt_errstr(status), nt_errstr(correct)); \
41 #define CHECK_VALUE(v, correct) do { \
42 if ((v) != (correct)) { \
43 printf("(%s) Incorrect value %s=%d - should be %d\n", \
44 __location__, #v, v, correct); \
49 #define CHECK_NOT_VALUE(v, correct) do { \
50 if ((v) == (correct)) { \
51 printf("(%s) Incorrect value %s=%d - should not be %d\n", \
52 __location__, #v, v, correct); \
61 static bool test_session(struct smbcli_state
*cli
, struct torture_context
*tctx
)
65 struct smbcli_session
*session
;
66 struct smbcli_session
*session2
;
67 struct smbcli_session
*session3
;
68 struct smbcli_session
*session4
;
69 struct cli_credentials
*anon_creds
;
70 struct smbcli_session
*sessions
[15];
71 struct composite_context
*composite_contexts
[15];
72 struct smbcli_tree
*tree
;
73 struct smb_composite_sesssetup setup
;
74 struct smb_composite_sesssetup setups
[15];
75 struct gensec_settings
*gensec_settings
;
80 const char *fname
= BASEDIR
"\\test.txt";
83 struct smbcli_session_options options
;
85 printf("TESTING SESSION HANDLING\n");
87 if (!torture_setup_dir(cli
, BASEDIR
)) {
91 printf("create a second security context on the same transport\n");
93 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
94 gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
96 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
98 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
99 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
100 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
102 setup
.in
.credentials
= cmdline_credentials
;
103 setup
.in
.gensec_settings
= gensec_settings
;
105 status
= smb_composite_sesssetup(session
, &setup
);
106 CHECK_STATUS(status
, NT_STATUS_OK
);
108 session
->vuid
= setup
.out
.vuid
;
110 printf("create a third security context on the same transport, with vuid set\n");
111 session2
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
113 session2
->vuid
= session
->vuid
;
114 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
115 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
116 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
118 setup
.in
.credentials
= cmdline_credentials
;
120 status
= smb_composite_sesssetup(session2
, &setup
);
121 CHECK_STATUS(status
, NT_STATUS_OK
);
123 session2
->vuid
= setup
.out
.vuid
;
124 printf("vuid1=%d vuid2=%d vuid3=%d\n", cli
->session
->vuid
, session
->vuid
, session2
->vuid
);
126 if (cli
->transport
->negotiate
.capabilities
& CAP_EXTENDED_SECURITY
) {
127 /* Samba4 currently fails this - we need to determine if this insane behaviour is important */
128 if (session2
->vuid
== session
->vuid
) {
129 printf("server allows the user to re-use an existing vuid in session setup \n");
132 CHECK_NOT_VALUE(session2
->vuid
, session
->vuid
);
134 talloc_free(session2
);
136 if (cli
->transport
->negotiate
.capabilities
& CAP_EXTENDED_SECURITY
) {
137 printf("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
= 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 setup
.in
.credentials
= cmdline_credentials
;
147 status
= smb_composite_sesssetup(session3
, &setup
);
148 CHECK_STATUS(status
, NT_STATUS_LOGON_FAILURE
);
150 printf("create a fouth anonymous security context on the same transport, without extended security\n");
151 session4
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
153 session4
->vuid
= session
->vuid
;
154 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
155 setup
.in
.capabilities
&= ~CAP_EXTENDED_SECURITY
; /* force a non extended security login (should fail) */
156 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
158 anon_creds
= cli_credentials_init(tctx
);
159 cli_credentials_set_conf(anon_creds
, tctx
->lp_ctx
);
160 cli_credentials_set_anonymous(anon_creds
);
162 setup
.in
.credentials
= anon_creds
;
164 status
= smb_composite_sesssetup(session3
, &setup
);
165 CHECK_STATUS(status
, NT_STATUS_OK
);
167 talloc_free(session4
);
170 printf("use the same tree as the existing connection\n");
171 tree
= smbcli_tree_init(session
, tctx
, false);
172 tree
->tid
= cli
->tree
->tid
;
174 printf("create a file using the new vuid\n");
175 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
176 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
177 io
.ntcreatex
.in
.flags
= 0;
178 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
179 io
.ntcreatex
.in
.create_options
= 0;
180 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
181 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
182 io
.ntcreatex
.in
.alloc_size
= 0;
183 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
184 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
185 io
.ntcreatex
.in
.security_flags
= 0;
186 io
.ntcreatex
.in
.fname
= fname
;
187 status
= smb_raw_open(tree
, tctx
, &io
);
188 CHECK_STATUS(status
, NT_STATUS_OK
);
189 fnum
= io
.ntcreatex
.out
.file
.fnum
;
191 printf("write using the old vuid\n");
192 wr
.generic
.level
= RAW_WRITE_WRITEX
;
193 wr
.writex
.in
.file
.fnum
= fnum
;
194 wr
.writex
.in
.offset
= 0;
195 wr
.writex
.in
.wmode
= 0;
196 wr
.writex
.in
.remaining
= 0;
197 wr
.writex
.in
.count
= 1;
198 wr
.writex
.in
.data
= &c
;
200 status
= smb_raw_write(cli
->tree
, &wr
);
201 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
203 printf("write with the new vuid\n");
204 status
= smb_raw_write(tree
, &wr
);
205 CHECK_STATUS(status
, NT_STATUS_OK
);
206 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
208 printf("logoff the new vuid\n");
209 status
= smb_raw_ulogoff(session
);
210 CHECK_STATUS(status
, NT_STATUS_OK
);
212 printf("the new vuid should not now be accessible\n");
213 status
= smb_raw_write(tree
, &wr
);
214 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
216 printf("second logoff for the new vuid should fail\n");
217 status
= smb_raw_ulogoff(session
);
218 CHECK_STATUS(status
, NT_STATUS_DOS(ERRSRV
, ERRbaduid
));
219 talloc_free(session
);
221 printf("the fnum should have been auto-closed\n");
222 cl
.close
.level
= RAW_CLOSE_CLOSE
;
223 cl
.close
.in
.file
.fnum
= fnum
;
224 cl
.close
.in
.write_time
= 0;
225 status
= smb_raw_close(cli
->tree
, &cl
);
226 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
228 printf("create %d secondary security contexts on the same transport\n",
229 (int)ARRAY_SIZE(sessions
));
230 for (i
=0; i
<ARRAY_SIZE(sessions
); i
++) {
231 setups
[i
].in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
232 setups
[i
].in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
233 setups
[i
].in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
235 setups
[i
].in
.credentials
= cmdline_credentials
;
236 setups
[i
].in
.gensec_settings
= gensec_settings
;
238 sessions
[i
] = smbcli_session_init(cli
->transport
, tctx
, false, options
);
239 composite_contexts
[i
] = smb_composite_sesssetup_send(sessions
[i
], &setups
[i
]);
244 printf("finishing %d secondary security contexts on the same transport\n",
245 (int)ARRAY_SIZE(sessions
));
246 for (i
=0; i
< ARRAY_SIZE(sessions
); i
++) {
247 status
= smb_composite_sesssetup_recv(composite_contexts
[i
]);
248 CHECK_STATUS(status
, NT_STATUS_OK
);
249 sessions
[i
]->vuid
= setups
[i
].out
.vuid
;
250 printf("VUID: %d\n", sessions
[i
]->vuid
);
251 status
= smb_raw_ulogoff(sessions
[i
]);
252 CHECK_STATUS(status
, NT_STATUS_OK
);
266 static bool test_tree(struct smbcli_state
*cli
, struct torture_context
*tctx
)
270 const char *share
, *host
;
271 struct smbcli_tree
*tree
;
277 const char *fname
= BASEDIR
"\\test.txt";
280 printf("TESTING TREE HANDLING\n");
282 if (!torture_setup_dir(cli
, BASEDIR
)) {
286 share
= torture_setting_string(tctx
, "share", NULL
);
287 host
= torture_setting_string(tctx
, "host", NULL
);
289 printf("create a second tree context on the same session\n");
290 tree
= smbcli_tree_init(cli
->session
, tctx
, false);
292 tcon
.generic
.level
= RAW_TCON_TCONX
;
293 tcon
.tconx
.in
.flags
= 0;
294 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
295 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
296 tcon
.tconx
.in
.device
= "A:";
297 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
298 CHECK_STATUS(status
, NT_STATUS_OK
);
301 tree
->tid
= tcon
.tconx
.out
.tid
;
302 printf("tid1=%d tid2=%d\n", cli
->tree
->tid
, tree
->tid
);
304 printf("try a tconx with a bad device type\n");
305 tcon
.tconx
.in
.device
= "FOO";
306 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
307 CHECK_STATUS(status
, NT_STATUS_BAD_DEVICE_TYPE
);
310 printf("create a file using the new tid\n");
311 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
312 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
313 io
.ntcreatex
.in
.flags
= 0;
314 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
315 io
.ntcreatex
.in
.create_options
= 0;
316 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
317 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
318 io
.ntcreatex
.in
.alloc_size
= 0;
319 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
320 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
321 io
.ntcreatex
.in
.security_flags
= 0;
322 io
.ntcreatex
.in
.fname
= fname
;
323 status
= smb_raw_open(tree
, tctx
, &io
);
324 CHECK_STATUS(status
, NT_STATUS_OK
);
325 fnum
= io
.ntcreatex
.out
.file
.fnum
;
327 printf("write using the old tid\n");
328 wr
.generic
.level
= RAW_WRITE_WRITEX
;
329 wr
.writex
.in
.file
.fnum
= fnum
;
330 wr
.writex
.in
.offset
= 0;
331 wr
.writex
.in
.wmode
= 0;
332 wr
.writex
.in
.remaining
= 0;
333 wr
.writex
.in
.count
= 1;
334 wr
.writex
.in
.data
= &c
;
336 status
= smb_raw_write(cli
->tree
, &wr
);
337 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
339 printf("write with the new tid\n");
340 status
= smb_raw_write(tree
, &wr
);
341 CHECK_STATUS(status
, NT_STATUS_OK
);
342 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
344 printf("disconnect the new tid\n");
345 status
= smb_tree_disconnect(tree
);
346 CHECK_STATUS(status
, NT_STATUS_OK
);
348 printf("the new tid should not now be accessible\n");
349 status
= smb_raw_write(tree
, &wr
);
350 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
352 printf("the fnum should have been auto-closed\n");
353 cl
.close
.level
= RAW_CLOSE_CLOSE
;
354 cl
.close
.in
.file
.fnum
= fnum
;
355 cl
.close
.in
.write_time
= 0;
356 status
= smb_raw_close(cli
->tree
, &cl
);
357 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
359 /* close down the new tree */
367 test tree with ulogoff
368 this demonstrates that a tcon isn't autoclosed by a ulogoff
369 the tcon can be reused using any other valid session later
371 static bool test_tree_ulogoff(struct smbcli_state
*cli
, struct torture_context
*tctx
)
375 const char *share
, *host
;
376 struct smbcli_session
*session1
;
377 struct smbcli_session
*session2
;
378 struct smb_composite_sesssetup setup
;
379 struct smbcli_tree
*tree
;
384 const char *fname1
= BASEDIR
"\\test1.txt";
385 const char *fname2
= BASEDIR
"\\test2.txt";
387 struct smbcli_session_options options
;
389 printf("TESTING TREE with ulogoff\n");
391 if (!torture_setup_dir(cli
, 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 printf("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
= cmdline_credentials
;
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 printf("vuid1=%d\n", session1
->vuid
);
412 printf("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
= 0;
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 printf("tid=%d\n", tree
->tid
);
424 printf("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 printf("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 printf("ulogoff the vuid1\n");
454 status
= smb_raw_ulogoff(session1
);
455 CHECK_STATUS(status
, NT_STATUS_OK
);
457 printf("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
= cmdline_credentials
;
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 printf("vuid2=%d\n", session2
->vuid
);
469 printf("use the existing tree with vuid2\n");
470 tree
->session
= session2
;
472 printf("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 printf("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 printf("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 printf("disconnect the existing tree connection\n");
507 status
= smb_tree_disconnect(tree
);
508 CHECK_STATUS(status
, NT_STATUS_OK
);
510 printf("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 smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
534 const char *fname
= BASEDIR
"\\test.txt";
538 printf("TESTING PID HANDLING exit() only cares about open() PID\n");
540 if (!torture_setup_dir(cli
, BASEDIR
)) {
544 pid1
= cli
->session
->pid
;
547 printf("pid1=%d pid2=%d\n", pid1
, pid2
);
549 printf("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 printf("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 printf("exit pid2\n");
581 cli
->session
->pid
= pid2
;
582 status
= smb_raw_exit(cli
->session
);
583 CHECK_STATUS(status
, NT_STATUS_OK
);
585 printf("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 printf("exit pid2\n");
592 cli
->session
->pid
= pid2
;
593 status
= smb_raw_exit(cli
->session
);
594 CHECK_STATUS(status
, NT_STATUS_OK
);
596 printf("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 printf("exit pid1\n");
607 cli
->session
->pid
= pid1
;
608 status
= smb_raw_exit(cli
->session
);
609 CHECK_STATUS(status
, NT_STATUS_OK
);
611 printf("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 printf("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 smbcli_state
*cli
, struct torture_context
*tctx
)
638 struct smbcli_session
*session
;
639 struct smb_composite_sesssetup setup
;
644 const char *fname
= BASEDIR
"\\test.txt";
646 uint16_t vuid1
, vuid2
;
647 struct smbcli_session_options options
;
649 printf("TESTING PID HANDLING WITH 2 SESSIONS\n");
651 if (!torture_setup_dir(cli
, BASEDIR
)) {
655 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
657 printf("create a second security context on the same transport\n");
658 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
660 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
661 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */
662 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
663 setup
.in
.credentials
= cmdline_credentials
;
664 setup
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
666 status
= smb_composite_sesssetup(session
, &setup
);
667 CHECK_STATUS(status
, NT_STATUS_OK
);
668 session
->vuid
= setup
.out
.vuid
;
670 vuid1
= cli
->session
->vuid
;
671 vuid2
= session
->vuid
;
673 printf("vuid1=%d vuid2=%d\n", vuid1
, vuid2
);
675 printf("create a file using the vuid1\n");
676 cli
->session
->vuid
= vuid1
;
677 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
678 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
679 io
.ntcreatex
.in
.flags
= 0;
680 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
681 io
.ntcreatex
.in
.create_options
= 0;
682 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
683 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
684 io
.ntcreatex
.in
.alloc_size
= 0;
685 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
686 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
687 io
.ntcreatex
.in
.security_flags
= 0;
688 io
.ntcreatex
.in
.fname
= fname
;
689 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
690 CHECK_STATUS(status
, NT_STATUS_OK
);
691 fnum
= io
.ntcreatex
.out
.file
.fnum
;
693 printf("write using the vuid1 (fnum=%d)\n", fnum
);
694 cli
->session
->vuid
= vuid1
;
695 wr
.generic
.level
= RAW_WRITE_WRITEX
;
696 wr
.writex
.in
.file
.fnum
= fnum
;
697 wr
.writex
.in
.offset
= 0;
698 wr
.writex
.in
.wmode
= 0;
699 wr
.writex
.in
.remaining
= 0;
700 wr
.writex
.in
.count
= 1;
701 wr
.writex
.in
.data
= &c
;
703 status
= smb_raw_write(cli
->tree
, &wr
);
704 CHECK_STATUS(status
, NT_STATUS_OK
);
705 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
707 printf("exit the pid with vuid2\n");
708 cli
->session
->vuid
= vuid2
;
709 status
= smb_raw_exit(cli
->session
);
710 CHECK_STATUS(status
, NT_STATUS_OK
);
712 printf("the fnum should still be accessible\n");
713 cli
->session
->vuid
= vuid1
;
714 status
= smb_raw_write(cli
->tree
, &wr
);
715 CHECK_STATUS(status
, NT_STATUS_OK
);
716 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
718 printf("exit the pid with vuid1\n");
719 cli
->session
->vuid
= vuid1
;
720 status
= smb_raw_exit(cli
->session
);
721 CHECK_STATUS(status
, NT_STATUS_OK
);
723 printf("the fnum should not now be accessible\n");
724 status
= smb_raw_write(cli
->tree
, &wr
);
725 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
727 printf("the fnum should have been auto-closed\n");
728 cl
.close
.level
= RAW_CLOSE_CLOSE
;
729 cl
.close
.in
.file
.fnum
= fnum
;
730 cl
.close
.in
.write_time
= 0;
731 status
= smb_raw_close(cli
->tree
, &cl
);
732 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
739 test pid ops with 2 tcons
741 static bool test_pid_2tcon(struct smbcli_state
*cli
, struct torture_context
*tctx
)
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 printf("TESTING PID HANDLING WITH 2 TCONS\n");
759 if (!torture_setup_dir(cli
, BASEDIR
)) {
763 share
= torture_setting_string(tctx
, "share", NULL
);
764 host
= torture_setting_string(tctx
, "host", NULL
);
766 printf("create a second tree context on the same session\n");
767 tree
= smbcli_tree_init(cli
->session
, tctx
, false);
769 tcon
.generic
.level
= RAW_TCON_TCONX
;
770 tcon
.tconx
.in
.flags
= 0;
771 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
772 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
773 tcon
.tconx
.in
.device
= "A:";
774 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
775 CHECK_STATUS(status
, NT_STATUS_OK
);
777 tree
->tid
= tcon
.tconx
.out
.tid
;
779 tid1
= cli
->tree
->tid
;
781 printf("tid1=%d tid2=%d\n", tid1
, tid2
);
783 printf("create a file using the tid1\n");
784 cli
->tree
->tid
= tid1
;
785 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
786 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
787 io
.ntcreatex
.in
.flags
= 0;
788 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
789 io
.ntcreatex
.in
.create_options
= 0;
790 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
791 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
792 io
.ntcreatex
.in
.alloc_size
= 0;
793 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
794 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
795 io
.ntcreatex
.in
.security_flags
= 0;
796 io
.ntcreatex
.in
.fname
= fname1
;
797 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
798 CHECK_STATUS(status
, NT_STATUS_OK
);
799 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
801 printf("write using the tid1\n");
802 wr
.generic
.level
= RAW_WRITE_WRITEX
;
803 wr
.writex
.in
.file
.fnum
= fnum1
;
804 wr
.writex
.in
.offset
= 0;
805 wr
.writex
.in
.wmode
= 0;
806 wr
.writex
.in
.remaining
= 0;
807 wr
.writex
.in
.count
= 1;
808 wr
.writex
.in
.data
= &c
;
810 status
= smb_raw_write(cli
->tree
, &wr
);
811 CHECK_STATUS(status
, NT_STATUS_OK
);
812 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
814 printf("create a file using the tid2\n");
815 cli
->tree
->tid
= tid2
;
816 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
817 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
818 io
.ntcreatex
.in
.flags
= 0;
819 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
820 io
.ntcreatex
.in
.create_options
= 0;
821 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
822 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
823 io
.ntcreatex
.in
.alloc_size
= 0;
824 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
825 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
826 io
.ntcreatex
.in
.security_flags
= 0;
827 io
.ntcreatex
.in
.fname
= fname2
;
828 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
829 CHECK_STATUS(status
, NT_STATUS_OK
);
830 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
832 printf("write using the tid2\n");
833 wr
.generic
.level
= RAW_WRITE_WRITEX
;
834 wr
.writex
.in
.file
.fnum
= fnum2
;
835 wr
.writex
.in
.offset
= 0;
836 wr
.writex
.in
.wmode
= 0;
837 wr
.writex
.in
.remaining
= 0;
838 wr
.writex
.in
.count
= 1;
839 wr
.writex
.in
.data
= &c
;
841 status
= smb_raw_write(cli
->tree
, &wr
);
842 CHECK_STATUS(status
, NT_STATUS_OK
);
843 CHECK_VALUE(wr
.writex
.out
.nwritten
, 1);
845 printf("exit the pid\n");
846 status
= smb_raw_exit(cli
->session
);
847 CHECK_STATUS(status
, NT_STATUS_OK
);
849 printf("the fnum1 on tid1 should not be accessible\n");
850 cli
->tree
->tid
= tid1
;
851 wr
.writex
.in
.file
.fnum
= fnum1
;
852 status
= smb_raw_write(cli
->tree
, &wr
);
853 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
855 printf("the fnum1 on tid1 should have been auto-closed\n");
856 cl
.close
.level
= RAW_CLOSE_CLOSE
;
857 cl
.close
.in
.file
.fnum
= fnum1
;
858 cl
.close
.in
.write_time
= 0;
859 status
= smb_raw_close(cli
->tree
, &cl
);
860 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
862 printf("the fnum2 on tid2 should not be accessible\n");
863 cli
->tree
->tid
= tid2
;
864 wr
.writex
.in
.file
.fnum
= fnum2
;
865 status
= smb_raw_write(cli
->tree
, &wr
);
866 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
868 printf("the fnum2 on tid2 should have been auto-closed\n");
869 cl
.close
.level
= RAW_CLOSE_CLOSE
;
870 cl
.close
.in
.file
.fnum
= fnum2
;
871 cl
.close
.in
.write_time
= 0;
872 status
= smb_raw_close(cli
->tree
, &cl
);
873 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
881 basic testing of session/tree context calls
883 static bool torture_raw_context_int(struct torture_context
*tctx
,
884 struct smbcli_state
*cli
)
888 ret
&= test_session(cli
, tctx
);
889 ret
&= test_tree(cli
, tctx
);
890 ret
&= test_tree_ulogoff(cli
, tctx
);
891 ret
&= test_pid_exit_only_sees_open(cli
, tctx
);
892 ret
&= test_pid_2sess(cli
, tctx
);
893 ret
&= test_pid_2tcon(cli
, tctx
);
895 smb_raw_exit(cli
->session
);
896 smbcli_deltree(cli
->tree
, BASEDIR
);
901 basic testing of session/tree context calls
903 bool torture_raw_context(struct torture_context
*torture
,
904 struct smbcli_state
*cli
)
907 if (lpcfg_use_spnego(torture
->lp_ctx
)) {
908 ret
&= torture_raw_context_int(torture
, cli
);
909 lpcfg_set_cmdline(torture
->lp_ctx
, "use spnego", "False");
912 ret
&= torture_raw_context_int(torture
, cli
);