s4-torture: remove an CHECK_STATUS macro in the util code.
[metze/samba/wip.git] / source4 / torture / smb2 / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    helper functions for SMB2 test suite
5
6    Copyright (C) Andrew Tridgell 2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/security/security_descriptor.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "../libcli/smb/smbXcli_base.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "system/time.h"
29 #include "librpc/gen_ndr/ndr_security.h"
30 #include "param/param.h"
31 #include "libcli/resolve/resolve.h"
32 #include "lib/util/tevent_ntstatus.h"
33
34 #include "torture/torture.h"
35 #include "torture/smb2/proto.h"
36 #include "source4/torture/util.h"
37
38
39 /*
40   write to a file on SMB2
41 */
42 NTSTATUS smb2_util_write(struct smb2_tree *tree,
43                          struct smb2_handle handle, 
44                          const void *buf, off_t offset, size_t size)
45 {
46         struct smb2_write w;
47
48         ZERO_STRUCT(w);
49         w.in.file.handle = handle;
50         w.in.offset      = offset;
51         w.in.data        = data_blob_const(buf, size);
52
53         return smb2_write(tree, &w);
54 }
55
56 /*
57   create a complex file/dir using the SMB2 protocol
58 */
59 static NTSTATUS smb2_create_complex(struct torture_context *tctx,
60                                     struct smb2_tree *tree,
61                                     const char *fname,
62                                     struct smb2_handle *handle,
63                                     bool dir)
64 {
65         TALLOC_CTX *tmp_ctx = talloc_new(tree);
66         char buf[7] = "abc";
67         struct smb2_create io;
68         union smb_setfileinfo setfile;
69         union smb_fileinfo fileinfo;
70         time_t t = (time(NULL) & ~1);
71         NTSTATUS status;
72
73         smb2_util_unlink(tree, fname);
74         ZERO_STRUCT(io);
75         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
76         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
77         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
78         io.in.share_access = 
79                 NTCREATEX_SHARE_ACCESS_DELETE|
80                 NTCREATEX_SHARE_ACCESS_READ|
81                 NTCREATEX_SHARE_ACCESS_WRITE;
82         io.in.create_options = 0;
83         io.in.fname = fname;
84         if (dir) {
85                 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
86                 io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
87                 io.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
88                 io.in.create_disposition = NTCREATEX_DISP_CREATE;
89         }
90
91         /* it seems vista is now fussier about alignment? */
92         if (strchr(fname, ':') == NULL) {
93                 /* setup some EAs */
94                 io.in.eas.num_eas = 2;
95                 io.in.eas.eas = talloc_array(tmp_ctx, struct ea_struct, 2);
96                 io.in.eas.eas[0].flags = 0;
97                 io.in.eas.eas[0].name.s = "EAONE";
98                 io.in.eas.eas[0].value = data_blob_talloc(tmp_ctx, "VALUE1", 6);
99                 io.in.eas.eas[1].flags = 0;
100                 io.in.eas.eas[1].name.s = "SECONDEA";
101                 io.in.eas.eas[1].value = data_blob_talloc(tmp_ctx, "ValueTwo", 8);
102         }
103
104         status = smb2_create(tree, tmp_ctx, &io);
105         if (NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)) {
106                 torture_comment(
107                         tctx, "EAs not supported, creating: %s\n", fname);
108                 io.in.eas.num_eas = 0;
109                 status = smb2_create(tree, tmp_ctx, &io);
110         }
111
112         talloc_free(tmp_ctx);
113         NT_STATUS_NOT_OK_RETURN(status);
114
115         *handle = io.out.file.handle;
116
117         if (!dir) {
118                 status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf));
119                 NT_STATUS_NOT_OK_RETURN(status);
120         }
121
122         /* make sure all the timestamps aren't the same, and are also 
123            in different DST zones*/
124         setfile.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
125         setfile.generic.in.file.handle = *handle;
126
127         unix_to_nt_time(&setfile.basic_info.in.create_time, t + 9*30*24*60*60);
128         unix_to_nt_time(&setfile.basic_info.in.access_time, t + 6*30*24*60*60);
129         unix_to_nt_time(&setfile.basic_info.in.write_time,  t + 3*30*24*60*60);
130         unix_to_nt_time(&setfile.basic_info.in.change_time, t + 1*30*24*60*60);
131         setfile.basic_info.in.attrib      = FILE_ATTRIBUTE_NORMAL;
132
133         status = smb2_setinfo_file(tree, &setfile);
134         if (!NT_STATUS_IS_OK(status)) {
135                 torture_comment(tctx, "Failed to setup file times - %s\n", nt_errstr(status));
136                 return status;
137         }
138
139         /* make sure all the timestamps aren't the same */
140         fileinfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
141         fileinfo.generic.in.file.handle = *handle;
142
143         status = smb2_getinfo_file(tree, tree, &fileinfo);
144         if (!NT_STATUS_IS_OK(status)) {
145                 torture_comment(tctx, "Failed to query file times - %s\n", nt_errstr(status));
146                 return status;
147                 
148         }
149
150 #define CHECK_TIME(field) do {\
151         if (setfile.basic_info.in.field != fileinfo.all_info2.out.field) { \
152                 torture_comment(tctx, "(%s) " #field " not setup correctly: %s(%llu) => %s(%llu)\n", \
153                         __location__, \
154                         nt_time_string(tree, setfile.basic_info.in.field), \
155                         (unsigned long long)setfile.basic_info.in.field, \
156                         nt_time_string(tree, fileinfo.basic_info.out.field), \
157                         (unsigned long long)fileinfo.basic_info.out.field); \
158                 status = NT_STATUS_INVALID_PARAMETER; \
159         } \
160 } while (0)
161
162         CHECK_TIME(create_time);
163         CHECK_TIME(access_time);
164         CHECK_TIME(write_time);
165         CHECK_TIME(change_time);
166
167         return status;
168 }
169
170 /*
171   create a complex file using the SMB2 protocol
172 */
173 NTSTATUS smb2_create_complex_file(struct torture_context *tctx,
174                                   struct smb2_tree *tree, const char *fname,
175                                   struct smb2_handle *handle)
176 {
177         return smb2_create_complex(tctx, tree, fname, handle, false);
178 }
179
180 /*
181   create a complex dir using the SMB2 protocol
182 */
183 NTSTATUS smb2_create_complex_dir(struct torture_context *tctx,
184                                  struct smb2_tree *tree, const char *fname,
185                                  struct smb2_handle *handle)
186 {
187         return smb2_create_complex(tctx, tree, fname, handle, true);
188 }
189
190 /*
191   show lots of information about a file
192 */
193 void torture_smb2_all_info(struct torture_context *tctx,
194                            struct smb2_tree *tree, struct smb2_handle handle)
195 {
196         NTSTATUS status;
197         TALLOC_CTX *tmp_ctx = talloc_new(tree);
198         union smb_fileinfo io;
199
200         io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
201         io.generic.in.file.handle = handle;
202
203         status = smb2_getinfo_file(tree, tmp_ctx, &io);
204         if (!NT_STATUS_IS_OK(status)) {
205                 DEBUG(0,("getinfo failed - %s\n", nt_errstr(status)));
206                 talloc_free(tmp_ctx);
207                 return;
208         }
209
210         torture_comment(tctx, "all_info for '%s'\n", io.all_info2.out.fname.s);
211         torture_comment(tctx, "\tcreate_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.create_time));
212         torture_comment(tctx, "\taccess_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.access_time));
213         torture_comment(tctx, "\twrite_time:     %s\n", nt_time_string(tmp_ctx, io.all_info2.out.write_time));
214         torture_comment(tctx, "\tchange_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.change_time));
215         torture_comment(tctx, "\tattrib:         0x%x\n", io.all_info2.out.attrib);
216         torture_comment(tctx, "\tunknown1:       0x%x\n", io.all_info2.out.unknown1);
217         torture_comment(tctx, "\talloc_size:     %llu\n", (long long)io.all_info2.out.alloc_size);
218         torture_comment(tctx, "\tsize:           %llu\n", (long long)io.all_info2.out.size);
219         torture_comment(tctx, "\tnlink:          %u\n", io.all_info2.out.nlink);
220         torture_comment(tctx, "\tdelete_pending: %u\n", io.all_info2.out.delete_pending);
221         torture_comment(tctx, "\tdirectory:      %u\n", io.all_info2.out.directory);
222         torture_comment(tctx, "\tfile_id:        %llu\n", (long long)io.all_info2.out.file_id);
223         torture_comment(tctx, "\tea_size:        %u\n", io.all_info2.out.ea_size);
224         torture_comment(tctx, "\taccess_mask:    0x%08x\n", io.all_info2.out.access_mask);
225         torture_comment(tctx, "\tposition:       0x%llx\n", (long long)io.all_info2.out.position);
226         torture_comment(tctx, "\tmode:           0x%llx\n", (long long)io.all_info2.out.mode);
227
228         /* short name, if any */
229         io.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
230         status = smb2_getinfo_file(tree, tmp_ctx, &io);
231         if (NT_STATUS_IS_OK(status)) {
232                 torture_comment(tctx, "\tshort name:     '%s'\n", io.alt_name_info.out.fname.s);
233         }
234
235         /* the EAs, if any */
236         io.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
237         status = smb2_getinfo_file(tree, tmp_ctx, &io);
238         if (NT_STATUS_IS_OK(status)) {
239                 int i;
240                 for (i=0;i<io.all_eas.out.num_eas;i++) {
241                         torture_comment(tctx, "\tEA[%d] flags=%d len=%d '%s'\n", i,
242                                  io.all_eas.out.eas[i].flags,
243                                  (int)io.all_eas.out.eas[i].value.length,
244                                  io.all_eas.out.eas[i].name.s);
245                 }
246         }
247
248         /* streams, if available */
249         io.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
250         status = smb2_getinfo_file(tree, tmp_ctx, &io);
251         if (NT_STATUS_IS_OK(status)) {
252                 int i;
253                 for (i=0;i<io.stream_info.out.num_streams;i++) {
254                         torture_comment(tctx, "\tstream %d:\n", i);
255                         torture_comment(tctx, "\t\tsize       %ld\n",
256                                  (long)io.stream_info.out.streams[i].size);
257                         torture_comment(tctx, "\t\talloc size %ld\n",
258                                  (long)io.stream_info.out.streams[i].alloc_size);
259                         torture_comment(tctx, "\t\tname       %s\n", io.stream_info.out.streams[i].stream_name.s);
260                 }
261         }       
262
263         if (DEBUGLVL(1)) {
264                 /* the security descriptor */
265                 io.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
266                 io.query_secdesc.in.secinfo_flags = 
267                         SECINFO_OWNER|SECINFO_GROUP|
268                         SECINFO_DACL;
269                 status = smb2_getinfo_file(tree, tmp_ctx, &io);
270                 if (NT_STATUS_IS_OK(status)) {
271                         NDR_PRINT_DEBUG(security_descriptor, io.query_secdesc.out.sd);
272                 }
273         }
274
275         talloc_free(tmp_ctx);   
276 }
277
278 /*
279   get granted access of a file handle
280 */
281 NTSTATUS torture_smb2_get_allinfo_access(struct smb2_tree *tree,
282                                          struct smb2_handle handle,
283                                          uint32_t *granted_access)
284 {
285         NTSTATUS status;
286         TALLOC_CTX *tmp_ctx = talloc_new(tree);
287         union smb_fileinfo io;
288
289         io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
290         io.generic.in.file.handle = handle;
291
292         status = smb2_getinfo_file(tree, tmp_ctx, &io);
293         if (!NT_STATUS_IS_OK(status)) {
294                 DEBUG(0, ("getinfo failed - %s\n", nt_errstr(status)));
295                 goto out;
296         }
297
298         *granted_access = io.all_info2.out.access_mask;
299
300 out:
301         talloc_free(tmp_ctx);
302         return status;
303 }
304
305 /**
306  * open a smb2 tree connect
307  */
308 bool torture_smb2_tree_connect(struct torture_context *tctx,
309                                struct smb2_session *session,
310                                TALLOC_CTX *mem_ctx,
311                                struct smb2_tree **_tree)
312 {
313         NTSTATUS status;
314         const char *host = torture_setting_string(tctx, "host", NULL);
315         const char *share = torture_setting_string(tctx, "share", NULL);
316         const char *unc;
317         struct smb2_tree *tree;
318         struct tevent_req *subreq;
319         uint32_t timeout_msec;
320
321         unc = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
322         torture_assert(tctx, unc != NULL, "talloc_asprintf");
323
324         tree = smb2_tree_init(session, mem_ctx, false);
325         torture_assert(tctx, tree != NULL, "smb2_tree_init");
326
327         timeout_msec = session->transport->options.request_timeout * 1000;
328
329         subreq = smb2cli_tcon_send(tree, tctx->ev,
330                                    session->transport->conn,
331                                    timeout_msec,
332                                    session->smbXcli,
333                                    tree->smbXcli,
334                                    0, /* flags */
335                                    unc);
336         torture_assert(tctx, subreq != NULL, "smb2cli_tcon_send");
337
338         torture_assert(tctx,
339                        tevent_req_poll_ntstatus(subreq, tctx->ev, &status),
340                        "tevent_req_poll_ntstatus");
341
342         status = smb2cli_tcon_recv(subreq);
343         TALLOC_FREE(subreq);
344         torture_assert_ntstatus_ok(tctx, status, "smb2cli_tcon_recv");
345
346         *_tree = tree;
347
348         return true;
349 }
350
351 /**
352  * do a smb2 session setup (without a tree connect)
353  */
354 bool torture_smb2_session_setup(struct torture_context *tctx,
355                                 struct smb2_transport *transport,
356                                 uint64_t previous_session_id,
357                                 TALLOC_CTX *mem_ctx,
358                                 struct smb2_session **_session)
359 {
360         NTSTATUS status;
361         struct smb2_session *session;
362
363         session = smb2_session_init(transport,
364                                     lpcfg_gensec_settings(tctx, tctx->lp_ctx),
365                                     mem_ctx);
366
367         if (session == NULL) {
368                 return false;
369         }
370
371         status = smb2_session_setup_spnego(session,
372                                            popt_get_cmdline_credentials(),
373                                            previous_session_id);
374         if (!NT_STATUS_IS_OK(status)) {
375                 torture_comment(tctx, "session setup failed: %s\n", nt_errstr(status));
376                 talloc_free(session);
377                 return false;
378         }
379
380         *_session = session;
381
382         return true;
383 }
384
385 /*
386   open a smb2 connection
387 */
388 bool torture_smb2_connection_ext(struct torture_context *tctx,
389                                  uint64_t previous_session_id,
390                                  const struct smbcli_options *options,
391                                  struct smb2_tree **tree)
392 {
393         NTSTATUS status;
394         const char *host = torture_setting_string(tctx, "host", NULL);
395         const char *share = torture_setting_string(tctx, "share", NULL);
396         const char *p = torture_setting_string(tctx, "unclist", NULL);
397         TALLOC_CTX *mem_ctx = NULL;
398         bool ok;
399
400         if (p != NULL) {
401                 char *host2 = NULL;
402                 char *share2 = NULL;
403
404                 mem_ctx = talloc_new(tctx);
405                 if (mem_ctx == NULL) {
406                         return false;
407                 }
408
409                 ok = torture_get_conn_index(tctx->conn_index++, mem_ctx, tctx,
410                                             &host2, &share2);
411                 if (!ok) {
412                         TALLOC_FREE(mem_ctx);
413                         return false;
414                 }
415
416                 host = host2;
417                 share = share2;
418         }
419
420         status = smb2_connect_ext(tctx,
421                                   host,
422                                   lpcfg_smb_ports(tctx->lp_ctx),
423                                   share,
424                                   lpcfg_resolve_context(tctx->lp_ctx),
425                                   popt_get_cmdline_credentials(),
426                                   previous_session_id,
427                                   tree,
428                                   tctx->ev,
429                                   options,
430                                   lpcfg_socket_options(tctx->lp_ctx),
431                                   lpcfg_gensec_settings(tctx, tctx->lp_ctx)
432                                   );
433         if (!NT_STATUS_IS_OK(status)) {
434                 torture_comment(tctx, "Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
435                        host, share, nt_errstr(status));
436                 TALLOC_FREE(mem_ctx);
437                 return false;
438         }
439
440         TALLOC_FREE(mem_ctx);
441         return true;
442 }
443
444 bool torture_smb2_connection(struct torture_context *tctx, struct smb2_tree **tree)
445 {
446         bool ret;
447         struct smbcli_options options;
448
449         lpcfg_smbcli_options(tctx->lp_ctx, &options);
450
451         ret = torture_smb2_connection_ext(tctx, 0, &options, tree);
452
453         return ret;
454 }
455
456 /**
457  * SMB2 connect with share from soption
458  **/
459 bool torture_smb2_con_sopt(struct torture_context *tctx,
460                            const char *soption,
461                            struct smb2_tree **tree)
462 {
463         struct smbcli_options options;
464         NTSTATUS status;
465         const char *host = torture_setting_string(tctx, "host", NULL);
466         const char *share = torture_setting_string(tctx, soption, NULL);
467
468         lpcfg_smbcli_options(tctx->lp_ctx, &options);
469
470         if (share == NULL) {
471                 torture_comment(tctx, "No share for option %s\n", soption);
472                 return false;
473         }
474
475         status = smb2_connect_ext(tctx,
476                                   host,
477                                   lpcfg_smb_ports(tctx->lp_ctx),
478                                   share,
479                                   lpcfg_resolve_context(tctx->lp_ctx),
480                                   popt_get_cmdline_credentials(),
481                                   0,
482                                   tree,
483                                   tctx->ev,
484                                   &options,
485                                   lpcfg_socket_options(tctx->lp_ctx),
486                                   lpcfg_gensec_settings(tctx, tctx->lp_ctx)
487                                   );
488         if (!NT_STATUS_IS_OK(status)) {
489                 torture_comment(tctx, "Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
490                        host, share, nt_errstr(status));
491                 return false;
492         }
493         return true;
494 }
495
496 /*
497   create and return a handle to a test file
498   with a specific access mask
499 */
500 NTSTATUS torture_smb2_testfile_access(struct smb2_tree *tree, const char *fname,
501                                       struct smb2_handle *handle,
502                                       uint32_t desired_access)
503 {
504         struct smb2_create io;
505         NTSTATUS status;
506
507         ZERO_STRUCT(io);
508         io.in.oplock_level = 0;
509         io.in.desired_access = desired_access;
510         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
511         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
512         io.in.share_access = 
513                 NTCREATEX_SHARE_ACCESS_DELETE|
514                 NTCREATEX_SHARE_ACCESS_READ|
515                 NTCREATEX_SHARE_ACCESS_WRITE;
516         io.in.create_options = 0;
517         io.in.fname = fname;
518
519         status = smb2_create(tree, tree, &io);
520         NT_STATUS_NOT_OK_RETURN(status);
521
522         *handle = io.out.file.handle;
523
524         return NT_STATUS_OK;
525 }
526
527 /*
528   create and return a handle to a test file
529 */
530 NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname,
531                                struct smb2_handle *handle)
532 {
533         return torture_smb2_testfile_access(tree, fname, handle,
534                                             SEC_RIGHTS_FILE_ALL);
535 }
536
537 /*
538   create and return a handle to a test file
539   with a specific access mask
540 */
541 NTSTATUS torture_smb2_open(struct smb2_tree *tree,
542                            const char *fname,
543                            uint32_t desired_access,
544                            struct smb2_handle *handle)
545 {
546         struct smb2_create io;
547         NTSTATUS status;
548
549         io = (struct smb2_create) {
550                 .in.fname = fname,
551                 .in.desired_access = desired_access,
552                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
553                 .in.create_disposition = NTCREATEX_DISP_OPEN,
554                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
555         };
556
557         status = smb2_create(tree, tree, &io);
558         if (!NT_STATUS_IS_OK(status)) {
559                 return status;
560         }
561
562         *handle = io.out.file.handle;
563
564         return NT_STATUS_OK;
565 }
566
567 /*
568   create and return a handle to a test directory
569   with specific desired access
570 */
571 NTSTATUS torture_smb2_testdir_access(struct smb2_tree *tree, const char *fname,
572                                      struct smb2_handle *handle,
573                                      uint32_t desired_access)
574 {
575         struct smb2_create io;
576         NTSTATUS status;
577
578         ZERO_STRUCT(io);
579         io.in.oplock_level = 0;
580         io.in.desired_access = desired_access;
581         io.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
582         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
583         io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
584         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
585         io.in.fname = fname;
586
587         status = smb2_create(tree, tree, &io);
588         NT_STATUS_NOT_OK_RETURN(status);
589
590         *handle = io.out.file.handle;
591
592         return NT_STATUS_OK;
593 }
594
595 /*
596   create and return a handle to a test directory
597 */
598 NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
599                               struct smb2_handle *handle)
600 {
601         return torture_smb2_testdir_access(tree, fname, handle,
602                                            SEC_RIGHTS_DIR_ALL);
603 }
604
605 /*
606   create a simple file using the SMB2 protocol
607 */
608 NTSTATUS smb2_create_simple_file(struct torture_context *tctx,
609                                  struct smb2_tree *tree, const char *fname,
610                                  struct smb2_handle *handle)
611 {
612         char buf[7] = "abc";
613         NTSTATUS status;
614
615         smb2_util_unlink(tree, fname);
616         status = torture_smb2_testfile_access(tree,
617                                               fname, handle,
618                                               SEC_FLAG_MAXIMUM_ALLOWED);
619         NT_STATUS_NOT_OK_RETURN(status);
620
621         status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf));
622         NT_STATUS_NOT_OK_RETURN(status);
623
624         return NT_STATUS_OK;
625 }
626
627 /*
628   create a simple file using SMB2.
629 */
630 NTSTATUS torture_setup_simple_file(struct torture_context *tctx,
631                                    struct smb2_tree *tree, const char *fname)
632 {
633         struct smb2_handle handle;
634         NTSTATUS status = smb2_create_simple_file(tctx, tree, fname, &handle);
635         NT_STATUS_NOT_OK_RETURN(status);
636         return smb2_util_close(tree, handle);
637 }
638
639 /*
640   create a complex file using SMB2, to make it easier to
641   find fields in SMB2 getinfo levels
642 */
643 NTSTATUS torture_setup_complex_file(struct torture_context *tctx,
644                                     struct smb2_tree *tree, const char *fname)
645 {
646         struct smb2_handle handle;
647         NTSTATUS status = smb2_create_complex_file(tctx, tree, fname, &handle);
648         NT_STATUS_NOT_OK_RETURN(status);
649         return smb2_util_close(tree, handle);
650 }
651
652
653 /*
654   create a complex dir using SMB2, to make it easier to
655   find fields in SMB2 getinfo levels
656 */
657 NTSTATUS torture_setup_complex_dir(struct torture_context *tctx,
658                                    struct smb2_tree *tree, const char *fname)
659 {
660         struct smb2_handle handle;
661         NTSTATUS status = smb2_create_complex_dir(tctx, tree, fname, &handle);
662         NT_STATUS_NOT_OK_RETURN(status);
663         return smb2_util_close(tree, handle);
664 }
665
666
667 /*
668   return a handle to the root of the share
669 */
670 NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle)
671 {
672         struct smb2_create io;
673         NTSTATUS status;
674
675         ZERO_STRUCT(io);
676         io.in.oplock_level = 0;
677         io.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
678         io.in.file_attributes   = 0;
679         io.in.create_disposition = NTCREATEX_DISP_OPEN;
680         io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
681         io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
682         io.in.fname = "";
683
684         status = smb2_create(tree, tree, &io);
685         NT_STATUS_NOT_OK_RETURN(status);
686
687         *handle = io.out.file.handle;
688
689         return NT_STATUS_OK;
690 }
691
692 /* Comparable to torture_setup_dir, but for SMB2. */
693 bool smb2_util_setup_dir(struct torture_context *tctx, struct smb2_tree *tree,
694     const char *dname)
695 {
696         NTSTATUS status;
697
698         /* XXX: smb_raw_exit equivalent?
699         smb_raw_exit(cli->session); */
700         if (smb2_deltree(tree, dname) == -1) {
701                 torture_result(tctx, TORTURE_ERROR, "Unable to deltree when setting up %s.\n", dname);
702                 return false;
703         }
704
705         status = smb2_util_mkdir(tree, dname);
706         if (NT_STATUS_IS_ERR(status)) {
707                 torture_result(tctx, TORTURE_ERROR, "Unable to mkdir when setting up %s - %s\n", dname,
708                     nt_errstr(status));
709                 return false;
710         }
711
712         return true;
713 }
714
715 /*
716  * Helper function to verify a security descriptor, by querying
717  * and comparing against the passed in sd.
718  */
719 bool smb2_util_verify_sd(TALLOC_CTX *tctx, struct smb2_tree *tree,
720     struct smb2_handle handle, struct security_descriptor *sd)
721 {
722         NTSTATUS status;
723         bool ret = true;
724         union smb_fileinfo q = {};
725
726         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
727         q.query_secdesc.in.file.handle = handle;
728         q.query_secdesc.in.secinfo_flags =
729             SECINFO_OWNER |
730             SECINFO_GROUP |
731             SECINFO_DACL;
732         status = smb2_getinfo_file(tree, tctx, &q);
733         torture_assert_ntstatus_ok(tctx, status, "");
734
735         if (!security_acl_equal(
736             q.query_secdesc.out.sd->dacl, sd->dacl)) {
737                 torture_warning(tctx, "%s: security descriptors don't match!\n",
738                     __location__);
739                 torture_warning(tctx, "got:\n");
740                 NDR_PRINT_DEBUG(security_descriptor,
741                     q.query_secdesc.out.sd);
742                 torture_warning(tctx, "expected:\n");
743                 NDR_PRINT_DEBUG(security_descriptor, sd);
744                 ret = false;
745         }
746
747         return ret;
748 }
749
750 /*
751  * Helper function to verify attributes, by querying
752  * and comparing against the passed in attrib.
753  */
754 bool smb2_util_verify_attrib(TALLOC_CTX *tctx, struct smb2_tree *tree,
755     struct smb2_handle handle, uint32_t attrib)
756 {
757         NTSTATUS status;
758         bool ret = true;
759         union smb_fileinfo q = {};
760
761         q.standard.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
762         q.standard.in.file.handle = handle;
763         status = smb2_getinfo_file(tree, tctx, &q);
764         torture_assert_ntstatus_ok(tctx, status, "");
765
766         q.all_info2.out.attrib &= ~(FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NONINDEXED);
767
768         if (q.all_info2.out.attrib != attrib) {
769                 torture_warning(tctx, "%s: attributes don't match! "
770                     "got %x, expected %x\n", __location__,
771                     (uint32_t)q.standard.out.attrib,
772                     (uint32_t)attrib);
773                 ret = false;
774         }
775
776         return ret;
777 }
778
779
780 uint32_t smb2_util_lease_state(const char *ls)
781 {
782         uint32_t val = 0;
783         int i;
784
785         for (i = 0; i < strlen(ls); i++) {
786                 switch (ls[i]) {
787                 case 'R':
788                         val |= SMB2_LEASE_READ;
789                         break;
790                 case 'H':
791                         val |= SMB2_LEASE_HANDLE;
792                         break;
793                 case 'W':
794                         val |= SMB2_LEASE_WRITE;
795                         break;
796                 }
797         }
798
799         return val;
800 }
801
802
803 uint32_t smb2_util_share_access(const char *sharemode)
804 {
805         uint32_t val = NTCREATEX_SHARE_ACCESS_NONE; /* 0 */
806         int i;
807
808         for (i = 0; i < strlen(sharemode); i++) {
809                 switch(sharemode[i]) {
810                 case 'R':
811                         val |= NTCREATEX_SHARE_ACCESS_READ;
812                         break;
813                 case 'W':
814                         val |= NTCREATEX_SHARE_ACCESS_WRITE;
815                         break;
816                 case 'D':
817                         val |= NTCREATEX_SHARE_ACCESS_DELETE;
818                         break;
819                 }
820         }
821
822         return val;
823 }
824
825 uint8_t smb2_util_oplock_level(const char *op)
826 {
827         uint8_t val = SMB2_OPLOCK_LEVEL_NONE;
828         int i;
829
830         for (i = 0; i < strlen(op); i++) {
831                 switch (op[i]) {
832                 case 's':
833                         return SMB2_OPLOCK_LEVEL_II;
834                 case 'x':
835                         return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
836                 case 'b':
837                         return SMB2_OPLOCK_LEVEL_BATCH;
838                 default:
839                         continue;
840                 }
841         }
842
843         return val;
844 }
845
846 /**
847  * Helper functions to fill a smb2_create struct for several
848  * open scenarios.
849  */
850 void smb2_generic_create_share(struct smb2_create *io, struct smb2_lease *ls,
851                                bool dir, const char *name, uint32_t disposition,
852                                uint32_t share_access,
853                                uint8_t oplock, uint64_t leasekey,
854                                uint32_t leasestate)
855 {
856         ZERO_STRUCT(*io);
857         io->in.security_flags           = 0x00;
858         io->in.oplock_level             = oplock;
859         io->in.impersonation_level      = NTCREATEX_IMPERSONATION_IMPERSONATION;
860         io->in.create_flags             = 0x00000000;
861         io->in.reserved                 = 0x00000000;
862         io->in.desired_access           = SEC_RIGHTS_FILE_ALL;
863         io->in.file_attributes          = FILE_ATTRIBUTE_NORMAL;
864         io->in.share_access             = share_access;
865         io->in.create_disposition       = disposition;
866         io->in.create_options           = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
867                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
868                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
869                                           0x00200000;
870         io->in.fname                    = name;
871
872         if (dir) {
873                 io->in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
874                 io->in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
875                 io->in.create_disposition = NTCREATEX_DISP_CREATE;
876         }
877
878         if (ls) {
879                 ZERO_STRUCTPN(ls);
880                 ls->lease_key.data[0] = leasekey;
881                 ls->lease_key.data[1] = ~leasekey;
882                 ls->lease_state = leasestate;
883                 io->in.lease_request = ls;
884         }
885 }
886
887 void smb2_generic_create(struct smb2_create *io, struct smb2_lease *ls,
888                          bool dir, const char *name, uint32_t disposition,
889                          uint8_t oplock, uint64_t leasekey,
890                          uint32_t leasestate)
891 {
892         smb2_generic_create_share(io, ls, dir, name, disposition,
893                                   smb2_util_share_access("RWD"),
894                                   oplock,
895                                   leasekey, leasestate);
896 }
897
898 void smb2_lease_create_share(struct smb2_create *io, struct smb2_lease *ls,
899                              bool dir, const char *name, uint32_t share_access,
900                              uint64_t leasekey, uint32_t leasestate)
901 {
902         smb2_generic_create_share(io, ls, dir, name, NTCREATEX_DISP_OPEN_IF,
903                                   share_access, SMB2_OPLOCK_LEVEL_LEASE,
904                                   leasekey, leasestate);
905 }
906
907 void smb2_lease_create(struct smb2_create *io, struct smb2_lease *ls,
908                        bool dir, const char *name, uint64_t leasekey,
909                        uint32_t leasestate)
910 {
911         smb2_lease_create_share(io, ls, dir, name,
912                                 smb2_util_share_access("RWD"),
913                                 leasekey, leasestate);
914 }
915
916 void smb2_lease_v2_create_share(struct smb2_create *io,
917                                 struct smb2_lease *ls,
918                                 bool dir,
919                                 const char *name,
920                                 uint32_t share_access,
921                                 uint64_t leasekey,
922                                 const uint64_t *parentleasekey,
923                                 uint32_t leasestate,
924                                 uint16_t lease_epoch)
925 {
926         smb2_generic_create_share(io, NULL, dir, name, NTCREATEX_DISP_OPEN_IF,
927                                   share_access, SMB2_OPLOCK_LEVEL_LEASE, 0, 0);
928
929         if (ls) {
930                 ZERO_STRUCT(*ls);
931                 ls->lease_key.data[0] = leasekey;
932                 ls->lease_key.data[1] = ~leasekey;
933                 ls->lease_state = leasestate;
934                 if (parentleasekey != NULL) {
935                         ls->lease_flags |= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET;
936                         ls->parent_lease_key.data[0] = *parentleasekey;
937                         ls->parent_lease_key.data[1] = ~(*parentleasekey);
938                 }
939                 ls->lease_epoch = lease_epoch;
940                 io->in.lease_request_v2 = ls;
941         }
942 }
943
944 void smb2_lease_v2_create(struct smb2_create *io,
945                           struct smb2_lease *ls,
946                           bool dir,
947                           const char *name,
948                           uint64_t leasekey,
949                           const uint64_t *parentleasekey,
950                           uint32_t leasestate,
951                           uint16_t lease_epoch)
952 {
953         smb2_lease_v2_create_share(io, ls, dir, name,
954                                    smb2_util_share_access("RWD"),
955                                    leasekey, parentleasekey,
956                                    leasestate, lease_epoch);
957 }
958
959
960 void smb2_oplock_create_share(struct smb2_create *io, const char *name,
961                               uint32_t share_access, uint8_t oplock)
962 {
963         smb2_generic_create_share(io, NULL, false, name, NTCREATEX_DISP_OPEN_IF,
964                                   share_access, oplock, 0, 0);
965 }
966 void smb2_oplock_create(struct smb2_create *io, const char *name, uint8_t oplock)
967 {
968         smb2_oplock_create_share(io, name, smb2_util_share_access("RWD"),
969                                  oplock);
970 }
971