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