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