s4:torture/raw: add raw.session.expire1
[ddiss/samba.git] / source4 / torture / raw / session.c
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 "smb_cli.h"
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"
30
31
32 static bool test_session_reauth1(struct torture_context *tctx,
33                                  struct smbcli_state *cli)
34 {
35         NTSTATUS status;
36         struct smb_composite_sesssetup io;
37         int fnum, num;
38         const int dlen = 255;
39         char *data;
40         char fname[256];
41         char buf[dlen+1];
42         bool ok = true;
43         uint16_t vuid1 = cli->session->vuid;
44
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);
48
49         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         torture_assert_ntstatus_ok_goto(tctx, smbcli_nt_error(cli->tree), ok,
57                                         done, "create file");
58         torture_assert_goto(tctx, fnum > 0, ok, done, "create file");
59
60         num = smbcli_smbwrite(cli->tree, fnum, data, 0, dlen);
61         torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "write file");
62
63         ZERO_STRUCT(io);
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");
72
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");
76
77 done:
78         talloc_free(data);
79
80         if (fnum > 0) {
81                 status = smbcli_close(cli->tree, fnum);
82                 torture_assert_ntstatus_ok(tctx, status, "close");
83         }
84         return ok;
85 }
86
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)
90 {
91         return true;
92 }
93
94 static bool test_session_reauth2(struct torture_context *tctx,
95                                  struct smbcli_state *cli)
96 {
97         char *random_string;
98         char *fname;
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;
104         NTSTATUS status;
105         uint16_t fnum;
106         ssize_t nwritten;
107         uint16_t vuid1 = cli->session->vuid;
108
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",
113                                 random_string);
114         talloc_free(random_string);
115         torture_assert(tctx, (fname != NULL), "memory allocation failed");
116
117         smbcli_unlink(cli->tree, fname);
118         smbcli_oplock_handler(cli->transport,
119                               test_session_reauth2_oplock_timeout,
120                               cli->tree);
121
122         /*
123           base ntcreatex parms
124         */
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;
139
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;
144
145         status = smb_raw_open(cli->tree, tctx, &io_open);
146         torture_assert_ntstatus_ok(tctx, status, "smb_raw_open failed");
147
148         fnum = io_open.ntcreatex.out.file.fnum;
149         torture_assert(
150                 tctx,
151                 (io_open.ntcreatex.out.oplock_level == BATCH_OPLOCK_RETURN),
152                 "did not get batch oplock");
153
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");
157
158         /*
159          * Make sure the open went through
160          */
161         status = smbcli_chkpath(cli->tree, "\\");
162         torture_assert_ntstatus_ok(tctx, status, "smb_chkpath failed");
163
164         status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
165         torture_assert_ntstatus_ok(tctx, status, "could not set delete on "
166                                    "close");
167
168         anon_creds = cli_credentials_init_anon(tctx);
169         torture_assert(tctx, (anon_creds != NULL), "memory allocation failed");
170
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(
177                 tctx, tctx->lp_ctx);
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");
181
182         status = smbcli_close(cli->tree, fnum);
183         torture_assert_ntstatus_ok(tctx, status, "close failed");
184
185         status = smb_raw_open_recv(req, tctx, &io_open);
186         torture_assert_ntstatus_ok(tctx, status, "2nd open failed");
187
188         fnum = io_open.ntcreatex.out.file.fnum;
189
190         nwritten = smbcli_write(cli->tree, fnum, 0, fname, 0, strlen(fname));
191         torture_assert(tctx, (nwritten == strlen(fname)),
192                        "smbcli_write failed");
193
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");
202
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(
209                 tctx, tctx->lp_ctx);
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");
213
214         status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc);
215         torture_assert_ntstatus_ok(tctx, status, "2nd qsecdesc failed");
216
217         status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
218         torture_assert_ntstatus_ok(tctx, status, "could not set delete on "
219                                    "close");
220
221         status = smbcli_close(cli->tree, fnum);
222         torture_assert_ntstatus_ok(tctx, status, "close failed");
223
224         return true;
225 }
226
227 static bool test_session_expire1(struct torture_context *tctx)
228 {
229         NTSTATUS status;
230         bool ret = false;
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;
238         char fname[256];
239         union smb_fileinfo qfinfo;
240         uint16_t vuid;
241         uint16_t fnum;
242         struct smb_composite_sesssetup io_sesssetup;
243         size_t i;
244
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!");
249         }
250
251         torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
252                                  "please use -k yes");
253
254         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
255
256         lpcfg_smbcli_options(tctx->lp_ctx, &options);
257
258         lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
259
260         status = smbcli_full_connection(tctx, &cli,
261                                         host,
262                                         lpcfg_smb_ports(tctx->lp_ctx),
263                                         share, NULL,
264                                         lpcfg_socket_options(tctx->lp_ctx),
265                                         credentials,
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");
271
272         vuid = cli->session->vuid;
273
274         /* Add some random component to the file name. */
275         snprintf(fname, 256, "session_expire1_%s.dat",
276                  generate_random_str(tctx, 8));
277
278         smbcli_unlink(cli->tree, fname);
279
280         fnum = smbcli_nt_create_full(cli->tree, fname, 0,
281                                      SEC_RIGHTS_FILE_ALL,
282                                      FILE_ATTRIBUTE_NORMAL,
283                                      NTCREATEX_SHARE_ACCESS_NONE,
284                                      NTCREATEX_DISP_OPEN_IF,
285                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE,
286                                      0);
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");
290
291         /* get the access information */
292
293         ZERO_STRUCT(qfinfo);
294
295         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
296         qfinfo.access_information.in.file.fnum = fnum;
297
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");
304
305                 torture_comment(tctx, "sleep 5 seconds\n");
306                 smb_msleep(5*1000);
307         }
308
309         /*
310          * the krb5 library may not handle expired creds
311          * well, lets start with an empty ccache.
312          */
313         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
314
315         /*
316          * now with CAP_DYNAMIC_REAUTH
317          *
318          * This should trigger NT_STATUS_NETWORK_SESSION_EXPIRED
319          */
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,
327                                                         tctx->lp_ctx);
328
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,
333                                         "reauth failed");
334         torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
335                                       ret, done, "reauth");
336
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");
343
344                 torture_comment(tctx, "sleep 5 seconds\n");
345                 smb_msleep(5*1000);
346
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");
353
354                 /*
355                  * the krb5 library may not handle expired creds
356                  * well, lets start with an empty ccache.
357                  */
358                 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
359
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,
364                                                 "reauth failed");
365                 torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
366                                               ret, done, "reauth");
367         }
368
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");
374
375         /*
376          * the krb5 library may not handle expired creds
377          * well, lets start with an empty ccache.
378          */
379         cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
380
381         /*
382          * now without CAP_DYNAMIC_REAUTH
383          *
384          * This should not trigger NT_STATUS_NETWORK_SESSION_EXPIRED
385          */
386         torture_comment(tctx, "reauth without CAP_DYNAMIC_REAUTH => OK\n");
387         io_sesssetup.in.capabilities &= ~CAP_DYNAMIC_REAUTH;
388
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,
392                                         "reauth failed");
393         torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
394                                       ret, done, "reauth");
395
396         for (i=0; i < 2; i++) {
397                 torture_comment(tctx, "query info => OK\n");
398
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");
403
404                 torture_comment(tctx, "sleep 5 seconds\n");
405                 smb_msleep(5*1000);
406         }
407
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");
413
414         ret = true;
415 done:
416         if (fnum > 0) {
417                 smbcli_close(cli->tree, fnum);
418         }
419
420         talloc_free(cli);
421         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
422         return ret;
423 }
424
425 struct torture_suite *torture_raw_session(TALLOC_CTX *mem_ctx)
426 {
427         struct torture_suite *suite = torture_suite_create(mem_ctx, "session");
428         suite->description = talloc_strdup(suite, "RAW-SESSION tests");
429
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);
433
434         return suite;
435 }