2 Unix SMB/CIFS implementation.
3 test suite for session setup operations
4 Copyright (C) Gregor Beck 2012
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/>.
23 #include "torture/raw/proto.h"
24 #include "smb_composite/smb_composite.h"
25 #include "lib/cmdline/popt_common.h"
26 #include "param/param.h"
27 #include "torture/util.h"
28 #include "auth/credentials/credentials.h"
29 #include "libcli/resolve/resolve.h"
32 static bool test_session_reauth1(struct torture_context
*tctx
,
33 struct smbcli_state
*cli
)
36 struct smb_composite_sesssetup io
;
43 uint16_t vuid1
= cli
->session
->vuid
;
45 data
= generate_random_str(tctx
, dlen
);
46 torture_assert(tctx
, (data
!= NULL
), "memory allocation failed");
47 snprintf(fname
, sizeof(fname
), "raw_session_reconnect_%.8s.dat", data
);
49 fnum
= smbcli_nt_create_full(cli
->tree
, fname
, 0,
51 FILE_ATTRIBUTE_NORMAL
,
52 NTCREATEX_SHARE_ACCESS_NONE
,
53 NTCREATEX_DISP_OPEN_IF
,
54 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
,
56 torture_assert_ntstatus_ok_goto(tctx
, smbcli_nt_error(cli
->tree
), ok
,
58 torture_assert_goto(tctx
, fnum
> 0, ok
, done
, "create file");
60 num
= smbcli_smbwrite(cli
->tree
, fnum
, data
, 0, dlen
);
61 torture_assert_int_equal_goto(tctx
, num
, dlen
, ok
, done
, "write file");
64 io
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
65 io
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
66 io
.in
.credentials
= cmdline_credentials
;
67 io
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
68 io
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
69 status
= smb_composite_sesssetup(cli
->session
, &io
);
70 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
, "setup2");
71 torture_assert_int_equal_goto(tctx
, io
.out
.vuid
, vuid1
, ok
, done
, "setup2");
73 num
= smbcli_read(cli
->tree
, fnum
, &buf
, 0, dlen
);
74 torture_assert_int_equal_goto(tctx
, num
, dlen
, ok
, done
, "read file");
75 torture_assert_str_equal_goto(tctx
, buf
, data
, ok
, done
, "read file");
81 status
= smbcli_close(cli
->tree
, fnum
);
82 torture_assert_ntstatus_ok(tctx
, status
, "close");
87 static bool test_session_reauth2_oplock_timeout(
88 struct smbcli_transport
*transport
, uint16_t tid
, uint16_t fnum
,
89 uint8_t level
, void *private_data
)
94 static bool test_session_reauth2(struct torture_context
*tctx
,
95 struct smbcli_state
*cli
)
99 union smb_open io_open
;
100 struct smb_composite_sesssetup io_sesssetup
;
101 union smb_fileinfo io_qsecdesc
;
102 struct smbcli_request
*req
;
103 struct cli_credentials
*anon_creds
;
107 uint16_t vuid1
= cli
->session
->vuid
;
109 random_string
= generate_random_str(tctx
, 8);
110 torture_assert(tctx
, (random_string
!= NULL
),
111 "memory allocation failed");
112 fname
= talloc_asprintf(tctx
, "raw_session_reauth2_%s.dat",
114 talloc_free(random_string
);
115 torture_assert(tctx
, (fname
!= NULL
), "memory allocation failed");
117 smbcli_unlink(cli
->tree
, fname
);
118 smbcli_oplock_handler(cli
->transport
,
119 test_session_reauth2_oplock_timeout
,
125 ZERO_STRUCT(io_open
);
126 io_open
.generic
.level
= RAW_OPEN_NTCREATEX
;
127 io_open
.ntcreatex
.in
.root_fid
.fnum
= 0;
128 io_open
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
129 SEC_RIGHTS_FILE_WRITE
| SEC_STD_DELETE
;
130 io_open
.ntcreatex
.in
.alloc_size
= 0;
131 io_open
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
132 io_open
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
133 NTCREATEX_SHARE_ACCESS_WRITE
;
134 io_open
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
135 io_open
.ntcreatex
.in
.create_options
= 0;
136 io_open
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
137 io_open
.ntcreatex
.in
.security_flags
= 0;
138 io_open
.ntcreatex
.in
.fname
= fname
;
140 torture_comment(tctx
, "open with batch oplock\n");
141 io_open
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
142 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
143 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
145 status
= smb_raw_open(cli
->tree
, tctx
, &io_open
);
146 torture_assert_ntstatus_ok(tctx
, status
, "smb_raw_open failed");
148 fnum
= io_open
.ntcreatex
.out
.file
.fnum
;
151 (io_open
.ntcreatex
.out
.oplock_level
== BATCH_OPLOCK_RETURN
),
152 "did not get batch oplock");
154 io_open
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
155 req
= smb_raw_open_send(cli
->tree
, &io_open
);
156 torture_assert(tctx
, (req
!= NULL
), "memory allocation failed");
159 * Make sure the open went through
161 status
= smbcli_chkpath(cli
->tree
, "\\");
162 torture_assert_ntstatus_ok(tctx
, status
, "smb_chkpath failed");
164 status
= smbcli_nt_delete_on_close(cli
->tree
, fnum
, true);
165 torture_assert_ntstatus_ok(tctx
, status
, "could not set delete on "
168 anon_creds
= cli_credentials_init_anon(tctx
);
169 torture_assert(tctx
, (anon_creds
!= NULL
), "memory allocation failed");
171 ZERO_STRUCT(io_sesssetup
);
172 io_sesssetup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
173 io_sesssetup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
174 io_sesssetup
.in
.credentials
= anon_creds
;
175 io_sesssetup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
176 io_sesssetup
.in
.gensec_settings
= lpcfg_gensec_settings(
178 status
= smb_composite_sesssetup(cli
->session
, &io_sesssetup
);
179 torture_assert_ntstatus_ok(tctx
, status
, "setup2 failed");
180 torture_assert_int_equal(tctx
, io_sesssetup
.out
.vuid
, vuid1
, "setup2");
182 status
= smbcli_close(cli
->tree
, fnum
);
183 torture_assert_ntstatus_ok(tctx
, status
, "close failed");
185 status
= smb_raw_open_recv(req
, tctx
, &io_open
);
186 torture_assert_ntstatus_ok(tctx
, status
, "2nd open failed");
188 fnum
= io_open
.ntcreatex
.out
.file
.fnum
;
190 nwritten
= smbcli_write(cli
->tree
, fnum
, 0, fname
, 0, strlen(fname
));
191 torture_assert(tctx
, (nwritten
== strlen(fname
)),
192 "smbcli_write failed");
194 ZERO_STRUCT(io_qsecdesc
);
195 io_qsecdesc
.query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
196 io_qsecdesc
.query_secdesc
.in
.file
.fnum
= fnum
;
197 io_qsecdesc
.query_secdesc
.in
.secinfo_flags
= SECINFO_OWNER
;
198 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &io_qsecdesc
);
199 torture_assert_ntstatus_equal(
200 tctx
, status
, NT_STATUS_ACCESS_DENIED
,
201 "anon qsecdesc did not return ACCESS_DENIED");
203 ZERO_STRUCT(io_sesssetup
);
204 io_sesssetup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
205 io_sesssetup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
206 io_sesssetup
.in
.credentials
= cmdline_credentials
;
207 io_sesssetup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
208 io_sesssetup
.in
.gensec_settings
= lpcfg_gensec_settings(
210 status
= smb_composite_sesssetup(cli
->session
, &io_sesssetup
);
211 torture_assert_ntstatus_ok(tctx
, status
, "setup3 failed");
212 torture_assert_int_equal(tctx
, io_sesssetup
.out
.vuid
, vuid1
, "setup2");
214 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &io_qsecdesc
);
215 torture_assert_ntstatus_ok(tctx
, status
, "2nd qsecdesc failed");
217 status
= smbcli_nt_delete_on_close(cli
->tree
, fnum
, true);
218 torture_assert_ntstatus_ok(tctx
, status
, "could not set delete on "
221 status
= smbcli_close(cli
->tree
, fnum
);
222 torture_assert_ntstatus_ok(tctx
, status
, "close failed");
227 static bool test_session_expire1(struct torture_context
*tctx
)
231 struct smbcli_options options
;
232 struct smbcli_session_options session_options
;
233 const char *host
= torture_setting_string(tctx
, "host", NULL
);
234 const char *share
= torture_setting_string(tctx
, "share", NULL
);
235 struct cli_credentials
*credentials
= cmdline_credentials
;
236 struct smbcli_state
*cli
= NULL
;
237 enum credentials_use_kerberos use_kerberos
;
239 union smb_fileinfo qfinfo
;
242 struct smb_composite_sesssetup io_sesssetup
;
245 use_kerberos
= cli_credentials_get_kerberos_state(credentials
);
246 if (use_kerberos
!= CRED_MUST_USE_KERBEROS
) {
247 torture_warning(tctx
, "smb2.session.expire1 requires -k yes!");
248 torture_skip(tctx
, "smb2.session.expire1 requires -k yes!");
251 torture_assert_int_equal(tctx
, use_kerberos
, CRED_MUST_USE_KERBEROS
,
252 "please use -k yes");
254 lpcfg_set_option(tctx
->lp_ctx
, "gensec_gssapi:requested_life_time=4");
256 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
258 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
260 status
= smbcli_full_connection(tctx
, &cli
,
262 lpcfg_smb_ports(tctx
->lp_ctx
),
264 lpcfg_socket_options(tctx
->lp_ctx
),
266 lpcfg_resolve_context(tctx
->lp_ctx
),
267 tctx
->ev
, &options
, &session_options
,
268 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
269 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
270 "smbcli_full_connection failed");
272 vuid
= cli
->session
->vuid
;
274 /* Add some random component to the file name. */
275 snprintf(fname
, 256, "session_expire1_%s.dat",
276 generate_random_str(tctx
, 8));
278 smbcli_unlink(cli
->tree
, fname
);
280 fnum
= smbcli_nt_create_full(cli
->tree
, fname
, 0,
282 FILE_ATTRIBUTE_NORMAL
,
283 NTCREATEX_SHARE_ACCESS_NONE
,
284 NTCREATEX_DISP_OPEN_IF
,
285 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
,
287 torture_assert_ntstatus_ok_goto(tctx
, smbcli_nt_error(cli
->tree
), ret
,
288 done
, "create file");
289 torture_assert_goto(tctx
, fnum
> 0, ret
, done
, "create file");
291 /* get the access information */
295 qfinfo
.access_information
.level
= RAW_FILEINFO_ACCESS_INFORMATION
;
296 qfinfo
.access_information
.in
.file
.fnum
= fnum
;
298 for (i
=0; i
< 2; i
++) {
299 torture_comment(tctx
, "query info => OK\n");
300 ZERO_STRUCT(qfinfo
.access_information
.out
);
301 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &qfinfo
);
302 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
303 "raw_fileinfo failed");
305 torture_comment(tctx
, "sleep 5 seconds\n");
310 * the krb5 library may not handle expired creds
311 * well, lets start with an empty ccache.
313 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
316 * now with CAP_DYNAMIC_REAUTH
318 * This should trigger NT_STATUS_NETWORK_SESSION_EXPIRED
320 ZERO_STRUCT(io_sesssetup
);
321 io_sesssetup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
322 io_sesssetup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
323 io_sesssetup
.in
.capabilities
|= CAP_DYNAMIC_REAUTH
;
324 io_sesssetup
.in
.credentials
= credentials
;
325 io_sesssetup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
326 io_sesssetup
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
,
329 torture_comment(tctx
, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
330 ZERO_STRUCT(io_sesssetup
.out
);
331 status
= smb_composite_sesssetup(cli
->session
, &io_sesssetup
);
332 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
334 torture_assert_int_equal_goto(tctx
, io_sesssetup
.out
.vuid
, vuid
,
335 ret
, done
, "reauth");
337 for (i
=0; i
< 2; i
++) {
338 torture_comment(tctx
, "query info => OK\n");
339 ZERO_STRUCT(qfinfo
.access_information
.out
);
340 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &qfinfo
);
341 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
342 "raw_fileinfo failed");
344 torture_comment(tctx
, "sleep 5 seconds\n");
347 torture_comment(tctx
, "query info => EXPIRED\n");
348 ZERO_STRUCT(qfinfo
.access_information
.out
);
349 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &qfinfo
);
350 torture_assert_ntstatus_equal_goto(tctx
, status
,
351 NT_STATUS_NETWORK_SESSION_EXPIRED
,
352 ret
, done
, "raw_fileinfo expired");
355 * the krb5 library may not handle expired creds
356 * well, lets start with an empty ccache.
358 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
360 torture_comment(tctx
, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
361 ZERO_STRUCT(io_sesssetup
.out
);
362 status
= smb_composite_sesssetup(cli
->session
, &io_sesssetup
);
363 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
365 torture_assert_int_equal_goto(tctx
, io_sesssetup
.out
.vuid
, vuid
,
366 ret
, done
, "reauth");
369 torture_comment(tctx
, "query info => OK\n");
370 ZERO_STRUCT(qfinfo
.access_information
.out
);
371 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &qfinfo
);
372 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
373 "raw_fileinfo failed");
376 * the krb5 library may not handle expired creds
377 * well, lets start with an empty ccache.
379 cli_credentials_invalidate_ccache(credentials
, CRED_SPECIFIED
);
382 * now without CAP_DYNAMIC_REAUTH
384 * This should not trigger NT_STATUS_NETWORK_SESSION_EXPIRED
386 torture_comment(tctx
, "reauth without CAP_DYNAMIC_REAUTH => OK\n");
387 io_sesssetup
.in
.capabilities
&= ~CAP_DYNAMIC_REAUTH
;
389 ZERO_STRUCT(io_sesssetup
.out
);
390 status
= smb_composite_sesssetup(cli
->session
, &io_sesssetup
);
391 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
393 torture_assert_int_equal_goto(tctx
, io_sesssetup
.out
.vuid
, vuid
,
394 ret
, done
, "reauth");
396 for (i
=0; i
< 2; i
++) {
397 torture_comment(tctx
, "query info => OK\n");
399 ZERO_STRUCT(qfinfo
.access_information
.out
);
400 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &qfinfo
);
401 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
402 "raw_fileinfo failed");
404 torture_comment(tctx
, "sleep 5 seconds\n");
408 torture_comment(tctx
, "query info => OK\n");
409 ZERO_STRUCT(qfinfo
.access_information
.out
);
410 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &qfinfo
);
411 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
412 "raw_fileinfo failed");
417 smbcli_close(cli
->tree
, fnum
);
421 lpcfg_set_option(tctx
->lp_ctx
, "gensec_gssapi:requested_life_time=0");
425 struct torture_suite
*torture_raw_session(TALLOC_CTX
*mem_ctx
)
427 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "session");
428 suite
->description
= talloc_strdup(suite
, "RAW-SESSION tests");
430 torture_suite_add_1smb_test(suite
, "reauth1", test_session_reauth1
);
431 torture_suite_add_1smb_test(suite
, "reauth2", test_session_reauth2
);
432 torture_suite_add_simple_test(suite
, "expire1", test_session_expire1
);