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