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