s3:utils: let smbstatus report anonymous signing/encryption explicitly
[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 "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 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     = samba_cmdline_get_creds();
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  = samba_cmdline_get_creds();
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 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         uint16_t fnum = 0;
243         struct smb_composite_sesssetup io_sesssetup;
244         size_t i;
245
246         use_kerberos = cli_credentials_get_kerberos_state(
247                                 samba_cmdline_get_creds());
248         if (use_kerberos != CRED_USE_KERBEROS_REQUIRED) {
249                 torture_warning(tctx,
250                                 "smb2.session.expire1 requires "
251                                 "--use-kerberos=required!");
252                 torture_skip(tctx,
253                              "smb2.session.expire1 requires "
254                              "--use-kerberos=required!");
255         }
256
257         torture_assert_int_equal(tctx,
258                                  use_kerberos,
259                                  CRED_USE_KERBEROS_REQUIRED,
260                                  "please use --use-kerberos=required");
261
262         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");
263
264         lpcfg_smbcli_options(tctx->lp_ctx, &options);
265
266         lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
267
268         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         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
278                                         "smbcli_full_connection failed");
279
280         vuid = cli->session->vuid;
281
282         /* Add some random component to the file name. */
283         snprintf(fname, 256, "session_expire1_%s.dat",
284                  generate_random_str(tctx, 8));
285
286         smbcli_unlink(cli->tree, fname);
287
288         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         torture_assert_ntstatus_ok_goto(tctx, smbcli_nt_error(cli->tree), ret,
296                                         done, "create file");
297         torture_assert_goto(tctx, fnum > 0, ret, done, "create file");
298
299         /* get the access information */
300
301         ZERO_STRUCT(qfinfo);
302
303         qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
304         qfinfo.access_information.in.file.fnum = fnum;
305
306         for (i=0; i < 2; i++) {
307                 torture_comment(tctx, "query info => OK\n");
308                 ZERO_STRUCT(qfinfo.access_information.out);
309                 status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
310                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
311                                                 "raw_fileinfo failed");
312
313                 torture_comment(tctx, "sleep 10 seconds\n");
314                 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         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         ZERO_STRUCT(io_sesssetup);
330         io_sesssetup.in.sesskey      = cli->transport->negotiate.sesskey;
331         io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
332         io_sesssetup.in.capabilities |= CAP_DYNAMIC_REAUTH;
333         io_sesssetup.in.credentials  = samba_cmdline_get_creds();
334         io_sesssetup.in.workgroup    = lpcfg_workgroup(tctx->lp_ctx);
335         io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(tctx,
336                                                         tctx->lp_ctx);
337
338         torture_comment(tctx, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
339         ZERO_STRUCT(io_sesssetup.out);
340         status = smb_composite_sesssetup(cli->session, &io_sesssetup);
341         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
342                                         "reauth failed");
343         torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
344                                       ret, done, "reauth");
345
346         for (i=0; i < 2; i++) {
347                 torture_comment(tctx, "query info => OK\n");
348                 ZERO_STRUCT(qfinfo.access_information.out);
349                 status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
350                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
351                                                 "raw_fileinfo failed");
352
353                 torture_comment(tctx, "sleep 10 seconds\n");
354                 smb_msleep(10*1000);
355
356                 torture_comment(tctx, "query info => EXPIRED\n");
357                 ZERO_STRUCT(qfinfo.access_information.out);
358                 status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
359                 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                 cli_credentials_invalidate_ccache(
368                         samba_cmdline_get_creds(), CRED_SPECIFIED);
369
370                 torture_comment(tctx, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
371                 ZERO_STRUCT(io_sesssetup.out);
372                 status = smb_composite_sesssetup(cli->session, &io_sesssetup);
373                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
374                                                 "reauth failed");
375                 torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
376                                               ret, done, "reauth");
377         }
378
379         torture_comment(tctx, "query info => OK\n");
380         ZERO_STRUCT(qfinfo.access_information.out);
381         status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
382         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         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         torture_comment(tctx, "reauth without CAP_DYNAMIC_REAUTH => OK\n");
398         io_sesssetup.in.capabilities &= ~CAP_DYNAMIC_REAUTH;
399
400         ZERO_STRUCT(io_sesssetup.out);
401         status = smb_composite_sesssetup(cli->session, &io_sesssetup);
402         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
403                                         "reauth failed");
404         torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
405                                       ret, done, "reauth");
406
407         for (i=0; i < 2; i++) {
408                 torture_comment(tctx, "query info => OK\n");
409
410                 ZERO_STRUCT(qfinfo.access_information.out);
411                 status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
412                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
413                                                 "raw_fileinfo failed");
414
415                 torture_comment(tctx, "sleep 5 seconds\n");
416                 smb_msleep(5*1000);
417         }
418
419         torture_comment(tctx, "query info => OK\n");
420         ZERO_STRUCT(qfinfo.access_information.out);
421         status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
422         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
423                                         "raw_fileinfo failed");
424
425         ret = true;
426 done:
427         if (fnum > 0) {
428                 smbcli_close(cli->tree, fnum);
429         }
430
431         talloc_free(cli);
432         lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
433         return ret;
434 }
435
436 struct torture_suite *torture_raw_session(TALLOC_CTX *mem_ctx)
437 {
438         struct torture_suite *suite = torture_suite_create(mem_ctx, "session");
439         suite->description = talloc_strdup(suite, "RAW-SESSION tests");
440
441         torture_suite_add_1smb_test(suite, "reauth1", test_session_reauth1);
442         torture_suite_add_1smb_test(suite, "reauth2", test_session_reauth2);
443         torture_suite_add_simple_test(suite, "expire1", test_session_expire1);
444
445         return suite;
446 }