Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : test suite for session setup operations
4 : Copyright (C) Gregor Beck 2012
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "torture.h"
22 : #include "libcli/libcli.h"
23 : #include "torture/raw/proto.h"
24 : #include "smb_composite/smb_composite.h"
25 : #include "lib/cmdline/cmdline.h"
26 : #include "param/param.h"
27 : #include "torture/util.h"
28 : #include "auth/credentials/credentials.h"
29 : #include "libcli/resolve/resolve.h"
30 :
31 :
32 9 : static bool test_session_reauth1(struct torture_context *tctx,
33 : struct smbcli_state *cli)
34 9 : {
35 0 : NTSTATUS status;
36 0 : struct smb_composite_sesssetup io;
37 0 : int fnum, num;
38 9 : const int dlen = 255;
39 0 : char *data;
40 0 : char fname[256];
41 9 : char buf[dlen+1];
42 9 : bool ok = true;
43 9 : uint16_t vuid1 = cli->session->vuid;
44 :
45 9 : data = generate_random_str(tctx, dlen);
46 9 : torture_assert(tctx, (data != NULL), "memory allocation failed");
47 9 : snprintf(fname, sizeof(fname), "raw_session_reconnect_%.8s.dat", data);
48 :
49 9 : fnum = smbcli_nt_create_full(cli->tree, fname, 0,
50 : SEC_RIGHTS_FILE_ALL,
51 : FILE_ATTRIBUTE_NORMAL,
52 : NTCREATEX_SHARE_ACCESS_NONE,
53 : NTCREATEX_DISP_OPEN_IF,
54 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE,
55 : 0);
56 9 : torture_assert_ntstatus_ok_goto(tctx, smbcli_nt_error(cli->tree), ok,
57 : done, "create file");
58 7 : torture_assert_goto(tctx, fnum > 0, ok, done, "create file");
59 :
60 7 : num = smbcli_smbwrite(cli->tree, fnum, data, 0, dlen);
61 7 : torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "write file");
62 :
63 7 : ZERO_STRUCT(io);
64 7 : io.in.sesskey = cli->transport->negotiate.sesskey;
65 7 : io.in.capabilities = cli->transport->negotiate.capabilities;
66 7 : io.in.credentials = samba_cmdline_get_creds();
67 7 : io.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
68 7 : io.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
69 7 : status = smb_composite_sesssetup(cli->session, &io);
70 7 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "setup2");
71 6 : torture_assert_int_equal_goto(tctx, io.out.vuid, vuid1, ok, done, "setup2");
72 :
73 6 : buf[dlen] = '\0';
74 :
75 6 : num = smbcli_read(cli->tree, fnum, &buf, 0, dlen);
76 6 : torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "read file");
77 6 : torture_assert_str_equal_goto(tctx, buf, data, ok, done, "read file");
78 :
79 6 : done:
80 9 : talloc_free(data);
81 :
82 9 : if (fnum > 0) {
83 7 : status = smbcli_close(cli->tree, fnum);
84 7 : torture_assert_ntstatus_ok(tctx, status, "close");
85 : }
86 9 : return ok;
87 : }
88 :
89 7 : static bool test_session_reauth2_oplock_timeout(
90 : struct smbcli_transport *transport, uint16_t tid, uint16_t fnum,
91 : uint8_t level, void *private_data)
92 : {
93 7 : return true;
94 : }
95 :
96 9 : static bool test_session_reauth2(struct torture_context *tctx,
97 : struct smbcli_state *cli)
98 : {
99 0 : char *random_string;
100 0 : char *fname;
101 0 : union smb_open io_open;
102 0 : struct smb_composite_sesssetup io_sesssetup;
103 0 : union smb_fileinfo io_qsecdesc;
104 0 : struct smbcli_request *req;
105 0 : struct cli_credentials *anon_creds;
106 0 : NTSTATUS status;
107 0 : uint16_t fnum;
108 0 : ssize_t nwritten;
109 9 : uint16_t vuid1 = cli->session->vuid;
110 :
111 9 : random_string = generate_random_str(tctx, 8);
112 9 : torture_assert(tctx, (random_string != NULL),
113 : "memory allocation failed");
114 9 : fname = talloc_asprintf(tctx, "raw_session_reauth2_%s.dat",
115 : random_string);
116 9 : talloc_free(random_string);
117 9 : torture_assert(tctx, (fname != NULL), "memory allocation failed");
118 :
119 9 : smbcli_unlink(cli->tree, fname);
120 9 : smbcli_oplock_handler(cli->transport,
121 : test_session_reauth2_oplock_timeout,
122 9 : cli->tree);
123 :
124 : /*
125 : base ntcreatex parms
126 : */
127 9 : ZERO_STRUCT(io_open);
128 9 : io_open.generic.level = RAW_OPEN_NTCREATEX;
129 9 : io_open.ntcreatex.in.root_fid.fnum = 0;
130 9 : io_open.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
131 : SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
132 9 : io_open.ntcreatex.in.alloc_size = 0;
133 9 : io_open.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
134 9 : io_open.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
135 : NTCREATEX_SHARE_ACCESS_WRITE;
136 9 : io_open.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
137 9 : io_open.ntcreatex.in.create_options = 0;
138 9 : io_open.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
139 9 : io_open.ntcreatex.in.security_flags = 0;
140 9 : io_open.ntcreatex.in.fname = fname;
141 :
142 9 : torture_comment(tctx, "open with batch oplock\n");
143 9 : io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
144 : NTCREATEX_FLAGS_REQUEST_OPLOCK |
145 : NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
146 :
147 9 : status = smb_raw_open(cli->tree, tctx, &io_open);
148 9 : torture_assert_ntstatus_ok(tctx, status, "smb_raw_open failed");
149 :
150 7 : fnum = io_open.ntcreatex.out.file.fnum;
151 7 : torture_assert(
152 : tctx,
153 : (io_open.ntcreatex.out.oplock_level == BATCH_OPLOCK_RETURN),
154 : "did not get batch oplock");
155 :
156 7 : io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
157 7 : req = smb_raw_open_send(cli->tree, &io_open);
158 7 : torture_assert(tctx, (req != NULL), "memory allocation failed");
159 :
160 : /*
161 : * Make sure the open went through
162 : */
163 7 : status = smbcli_chkpath(cli->tree, "\\");
164 7 : torture_assert_ntstatus_ok(tctx, status, "smb_chkpath failed");
165 :
166 7 : status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
167 7 : torture_assert_ntstatus_ok(tctx, status, "could not set delete on "
168 : "close");
169 :
170 7 : anon_creds = cli_credentials_init_anon(tctx);
171 7 : torture_assert(tctx, (anon_creds != NULL), "memory allocation failed");
172 :
173 7 : ZERO_STRUCT(io_sesssetup);
174 7 : io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey;
175 7 : io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
176 7 : io_sesssetup.in.credentials = anon_creds;
177 7 : io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
178 7 : io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(
179 : tctx, tctx->lp_ctx);
180 7 : status = smb_composite_sesssetup(cli->session, &io_sesssetup);
181 7 : torture_assert_ntstatus_ok(tctx, status, "setup2 failed");
182 6 : torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2");
183 :
184 6 : status = smbcli_close(cli->tree, fnum);
185 6 : torture_assert_ntstatus_ok(tctx, status, "close failed");
186 :
187 6 : status = smb_raw_open_recv(req, tctx, &io_open);
188 6 : torture_assert_ntstatus_ok(tctx, status, "2nd open failed");
189 :
190 6 : fnum = io_open.ntcreatex.out.file.fnum;
191 :
192 6 : nwritten = smbcli_write(cli->tree, fnum, 0, fname, 0, strlen(fname));
193 6 : torture_assert(tctx, (nwritten == strlen(fname)),
194 : "smbcli_write failed");
195 :
196 6 : ZERO_STRUCT(io_qsecdesc);
197 6 : io_qsecdesc.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
198 6 : io_qsecdesc.query_secdesc.in.file.fnum = fnum;
199 6 : io_qsecdesc.query_secdesc.in.secinfo_flags = SECINFO_OWNER;
200 6 : status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc);
201 6 : torture_assert_ntstatus_equal(
202 : tctx, status, NT_STATUS_ACCESS_DENIED,
203 : "anon qsecdesc did not return ACCESS_DENIED");
204 :
205 0 : ZERO_STRUCT(io_sesssetup);
206 0 : io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey;
207 0 : io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
208 0 : io_sesssetup.in.credentials = samba_cmdline_get_creds();
209 0 : io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
210 0 : io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(
211 : tctx, tctx->lp_ctx);
212 0 : status = smb_composite_sesssetup(cli->session, &io_sesssetup);
213 0 : torture_assert_ntstatus_ok(tctx, status, "setup3 failed");
214 0 : torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2");
215 :
216 0 : status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc);
217 0 : torture_assert_ntstatus_ok(tctx, status, "2nd qsecdesc failed");
218 :
219 0 : status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
220 0 : torture_assert_ntstatus_ok(tctx, status, "could not set delete on "
221 : "close");
222 :
223 0 : status = smbcli_close(cli->tree, fnum);
224 0 : torture_assert_ntstatus_ok(tctx, status, "close failed");
225 :
226 0 : return true;
227 : }
228 :
229 9 : static bool test_session_expire1(struct torture_context *tctx)
230 : {
231 0 : NTSTATUS status;
232 9 : bool ret = false;
233 0 : struct smbcli_options options;
234 0 : struct smbcli_session_options session_options;
235 9 : const char *host = torture_setting_string(tctx, "host", NULL);
236 9 : const char *share = torture_setting_string(tctx, "share", NULL);
237 9 : struct smbcli_state *cli = NULL;
238 0 : enum credentials_use_kerberos use_kerberos;
239 0 : char fname[256];
240 0 : union smb_fileinfo qfinfo;
241 0 : uint16_t vuid;
242 9 : uint16_t fnum = 0;
243 0 : struct smb_composite_sesssetup io_sesssetup;
244 0 : size_t i;
245 :
246 9 : use_kerberos = cli_credentials_get_kerberos_state(
247 : samba_cmdline_get_creds());
248 9 : if (use_kerberos != CRED_USE_KERBEROS_REQUIRED) {
249 7 : torture_warning(tctx,
250 : "smb2.session.expire1 requires "
251 : "--use-kerberos=required!");
252 7 : torture_skip(tctx,
253 : "smb2.session.expire1 requires "
254 : "--use-kerberos=required!");
255 : }
256 :
257 2 : torture_assert_int_equal(tctx,
258 : use_kerberos,
259 : CRED_USE_KERBEROS_REQUIRED,
260 : "please use --use-kerberos=required");
261 :
262 2 : lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
263 :
264 2 : lpcfg_smbcli_options(tctx->lp_ctx, &options);
265 :
266 2 : lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
267 :
268 2 : status = smbcli_full_connection(tctx, &cli,
269 : host,
270 : lpcfg_smb_ports(tctx->lp_ctx),
271 : share, NULL,
272 : lpcfg_socket_options(tctx->lp_ctx),
273 : samba_cmdline_get_creds(),
274 : lpcfg_resolve_context(tctx->lp_ctx),
275 : tctx->ev, &options, &session_options,
276 : lpcfg_gensec_settings(tctx, tctx->lp_ctx));
277 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
278 : "smbcli_full_connection failed");
279 :
280 2 : vuid = cli->session->vuid;
281 :
282 : /* Add some random component to the file name. */
283 2 : snprintf(fname, 256, "session_expire1_%s.dat",
284 : generate_random_str(tctx, 8));
285 :
286 2 : smbcli_unlink(cli->tree, fname);
287 :
288 2 : fnum = smbcli_nt_create_full(cli->tree, fname, 0,
289 : SEC_RIGHTS_FILE_ALL,
290 : FILE_ATTRIBUTE_NORMAL,
291 : NTCREATEX_SHARE_ACCESS_NONE,
292 : NTCREATEX_DISP_OPEN_IF,
293 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE,
294 : 0);
295 2 : torture_assert_ntstatus_ok_goto(tctx, smbcli_nt_error(cli->tree), ret,
296 : done, "create file");
297 2 : torture_assert_goto(tctx, fnum > 0, ret, done, "create file");
298 :
299 : /* get the access information */
300 :
301 2 : ZERO_STRUCT(qfinfo);
302 :
303 2 : qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
304 2 : qfinfo.access_information.in.file.fnum = fnum;
305 :
306 6 : for (i=0; i < 2; i++) {
307 4 : torture_comment(tctx, "query info => OK\n");
308 4 : ZERO_STRUCT(qfinfo.access_information.out);
309 4 : status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
310 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
311 : "raw_fileinfo failed");
312 :
313 4 : torture_comment(tctx, "sleep 10 seconds\n");
314 4 : smb_msleep(10*1000);
315 : }
316 :
317 : /*
318 : * the krb5 library may not handle expired creds
319 : * well, lets start with an empty ccache.
320 : */
321 2 : cli_credentials_invalidate_ccache(samba_cmdline_get_creds(),
322 : CRED_SPECIFIED);
323 :
324 : /*
325 : * now with CAP_DYNAMIC_REAUTH
326 : *
327 : * This should trigger NT_STATUS_NETWORK_SESSION_EXPIRED
328 : */
329 2 : ZERO_STRUCT(io_sesssetup);
330 2 : io_sesssetup.in.sesskey = cli->transport->negotiate.sesskey;
331 2 : io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
332 2 : io_sesssetup.in.capabilities |= CAP_DYNAMIC_REAUTH;
333 2 : io_sesssetup.in.credentials = samba_cmdline_get_creds();
334 2 : io_sesssetup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx);
335 2 : io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(tctx,
336 : tctx->lp_ctx);
337 :
338 2 : torture_comment(tctx, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
339 2 : ZERO_STRUCT(io_sesssetup.out);
340 2 : status = smb_composite_sesssetup(cli->session, &io_sesssetup);
341 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
342 : "reauth failed");
343 2 : torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
344 : ret, done, "reauth");
345 :
346 6 : for (i=0; i < 2; i++) {
347 4 : torture_comment(tctx, "query info => OK\n");
348 4 : ZERO_STRUCT(qfinfo.access_information.out);
349 4 : status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
350 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
351 : "raw_fileinfo failed");
352 :
353 4 : torture_comment(tctx, "sleep 10 seconds\n");
354 4 : smb_msleep(10*1000);
355 :
356 4 : torture_comment(tctx, "query info => EXPIRED\n");
357 4 : ZERO_STRUCT(qfinfo.access_information.out);
358 4 : status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
359 4 : torture_assert_ntstatus_equal_goto(tctx, status,
360 : NT_STATUS_NETWORK_SESSION_EXPIRED,
361 : ret, done, "raw_fileinfo expired");
362 :
363 : /*
364 : * the krb5 library may not handle expired creds
365 : * well, lets start with an empty ccache.
366 : */
367 4 : cli_credentials_invalidate_ccache(
368 : samba_cmdline_get_creds(), CRED_SPECIFIED);
369 :
370 4 : torture_comment(tctx, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
371 4 : ZERO_STRUCT(io_sesssetup.out);
372 4 : status = smb_composite_sesssetup(cli->session, &io_sesssetup);
373 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
374 : "reauth failed");
375 4 : torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
376 : ret, done, "reauth");
377 : }
378 :
379 2 : torture_comment(tctx, "query info => OK\n");
380 2 : ZERO_STRUCT(qfinfo.access_information.out);
381 2 : status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
382 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
383 : "raw_fileinfo failed");
384 :
385 : /*
386 : * the krb5 library may not handle expired creds
387 : * well, lets start with an empty ccache.
388 : */
389 2 : cli_credentials_invalidate_ccache(samba_cmdline_get_creds(),
390 : CRED_SPECIFIED);
391 :
392 : /*
393 : * now without CAP_DYNAMIC_REAUTH
394 : *
395 : * This should not trigger NT_STATUS_NETWORK_SESSION_EXPIRED
396 : */
397 2 : torture_comment(tctx, "reauth without CAP_DYNAMIC_REAUTH => OK\n");
398 2 : io_sesssetup.in.capabilities &= ~CAP_DYNAMIC_REAUTH;
399 :
400 2 : ZERO_STRUCT(io_sesssetup.out);
401 2 : status = smb_composite_sesssetup(cli->session, &io_sesssetup);
402 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
403 : "reauth failed");
404 2 : torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
405 : ret, done, "reauth");
406 :
407 6 : for (i=0; i < 2; i++) {
408 4 : torture_comment(tctx, "query info => OK\n");
409 :
410 4 : ZERO_STRUCT(qfinfo.access_information.out);
411 4 : status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
412 4 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
413 : "raw_fileinfo failed");
414 :
415 4 : torture_comment(tctx, "sleep 5 seconds\n");
416 4 : smb_msleep(5*1000);
417 : }
418 :
419 2 : torture_comment(tctx, "query info => OK\n");
420 2 : ZERO_STRUCT(qfinfo.access_information.out);
421 2 : status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
422 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
423 : "raw_fileinfo failed");
424 :
425 2 : ret = true;
426 2 : done:
427 2 : if (fnum > 0) {
428 2 : smbcli_close(cli->tree, fnum);
429 : }
430 :
431 2 : talloc_free(cli);
432 2 : lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
433 2 : return ret;
434 : }
435 :
436 2354 : struct torture_suite *torture_raw_session(TALLOC_CTX *mem_ctx)
437 : {
438 2354 : struct torture_suite *suite = torture_suite_create(mem_ctx, "session");
439 2354 : suite->description = talloc_strdup(suite, "RAW-SESSION tests");
440 :
441 2354 : torture_suite_add_1smb_test(suite, "reauth1", test_session_reauth1);
442 2354 : torture_suite_add_1smb_test(suite, "reauth2", test_session_reauth2);
443 2354 : torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
444 :
445 2354 : return suite;
446 : }
|