r25026: Move param/param.h out of includes.h
[abartlet/samba.git/.git] / source4 / torture / smb2 / util.c
index bb239bdd1b6b428ccde8c54340d90546ac67caa8..caa3a5fd52ae87f89666e67cc37b8dc951c4d1d0 100644 (file)
@@ -7,7 +7,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "libcli/raw/libcliraw.h"
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
 #include "lib/cmdline/popt_common.h"
 #include "lib/events/events.h"
 #include "system/time.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "param/param.h"
 
 
 /*
@@ -37,7 +37,7 @@ NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
        struct smb2_close c;
 
        ZERO_STRUCT(c);
-       c.in.handle = h;
+       c.in.file.handle = h;
 
        return smb2_close(tree, &c);
 }
@@ -60,7 +60,6 @@ NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
                NTCREATEX_SHARE_ACCESS_WRITE;
        io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
        io.in.fname = fname;
-       io.in.blob  = data_blob(NULL, 0);
 
        status = smb2_create(tree, tree, &io);
        if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
@@ -68,7 +67,7 @@ NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
        }
        NT_STATUS_NOT_OK_RETURN(status);
 
-       return smb2_util_close(tree, io.out.handle);
+       return smb2_util_close(tree, io.out.file.handle);
 }
 
 /*
@@ -81,18 +80,20 @@ NTSTATUS smb2_util_write(struct smb2_tree *tree,
        struct smb2_write w;
 
        ZERO_STRUCT(w);
+       w.in.file.handle = handle;
        w.in.offset      = offset;
-       w.in.handle      = handle;
        w.in.data        = data_blob_const(buf, size);
 
        return smb2_write(tree, &w);
 }
 
 /*
-  create a complex file using the SMB2 protocol
+  create a complex file/dir using the SMB2 protocol
 */
-NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname, struct smb2_handle *handle)
+static NTSTATUS smb2_create_complex(struct smb2_tree *tree, const char *fname, 
+                                        struct smb2_handle *handle, BOOL dir)
 {
+       TALLOC_CTX *tmp_ctx = talloc_new(tree);
        char buf[7] = "abc";
        struct smb2_create io;
        union smb_setfileinfo setfile;
@@ -100,8 +101,9 @@ NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname, str
        time_t t = (time(NULL) & ~1);
        NTSTATUS status;
 
+       smb2_util_unlink(tree, fname);
        ZERO_STRUCT(io);
-       io.in.access_mask = SEC_RIGHTS_FILE_ALL;
+       io.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        io.in.file_attr   = FILE_ATTRIBUTE_NORMAL;
        io.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
        io.in.share_access = 
@@ -110,72 +112,100 @@ NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname, str
                NTCREATEX_SHARE_ACCESS_WRITE;
        io.in.create_options = 0;
        io.in.fname = fname;
-       io.in.blob  = data_blob(NULL, 0);
-
-       status = smb2_create(tree, tree, &io);
-       NT_STATUS_NOT_OK_RETURN(status);
+       if (dir) {
+               io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+               io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
+               io.in.file_attr   = FILE_ATTRIBUTE_DIRECTORY;
+               io.in.open_disposition = NTCREATEX_DISP_CREATE;
+       }
 
-       *handle = io.out.handle;
+       if (strchr(fname, ':') == NULL) {
+               /* setup some EAs */
+               io.in.eas.num_eas = 2;
+               io.in.eas.eas = talloc_array(tmp_ctx, struct ea_struct, 2);
+               io.in.eas.eas[0].flags = 0;
+               io.in.eas.eas[0].name.s = "EAONE";
+               io.in.eas.eas[0].value = data_blob_talloc(tmp_ctx, "VALUE1", 6);
+               io.in.eas.eas[1].flags = 0;
+               io.in.eas.eas[1].name.s = "SECONDEA";
+               io.in.eas.eas[1].value = data_blob_talloc(tmp_ctx, "ValueTwo", 8);
+       }
 
-       status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf));
+       status = smb2_create(tree, tmp_ctx, &io);
+       talloc_free(tmp_ctx);
        NT_STATUS_NOT_OK_RETURN(status);
 
-#if 0
-       if (strchr(fname, ':') == NULL) {
-               /* setup some EAs */
-               setfile.generic.level = RAW_SFILEINFO_EA_SET;
-               setfile.generic.file.fnum = fnum;
-               setfile.ea_set.in.num_eas = 2;  
-               setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2);
-               setfile.ea_set.in.eas[0].flags = 0;
-               setfile.ea_set.in.eas[0].name.s = "EAONE";
-               setfile.ea_set.in.eas[0].value = data_blob_talloc(mem_ctx, "VALUE1", 6);
-               setfile.ea_set.in.eas[1].flags = 0;
-               setfile.ea_set.in.eas[1].name.s = "SECONDEA";
-               setfile.ea_set.in.eas[1].value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
-               status = smb_raw_setfileinfo(cli->tree, &setfile);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("Failed to setup EAs\n");
-               }
+       *handle = io.out.file.handle;
+
+       if (!dir) {
+               status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf));
+               NT_STATUS_NOT_OK_RETURN(status);
        }
-#endif
 
        /* make sure all the timestamps aren't the same, and are also 
           in different DST zones*/
        setfile.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
-       setfile.generic.file.handle = *handle;
+       setfile.generic.in.file.handle = *handle;
 
-       setfile.basic_info.in.create_time = t +  9*30*24*60*60;
-       setfile.basic_info.in.access_time = t +  6*30*24*60*60;
-       setfile.basic_info.in.write_time  = t +  3*30*24*60*60;
-       setfile.basic_info.in.change_time = t +  1*30*24*60*60;
+       unix_to_nt_time(&setfile.basic_info.in.create_time, t + 9*30*24*60*60);
+       unix_to_nt_time(&setfile.basic_info.in.access_time, t + 6*30*24*60*60);
+       unix_to_nt_time(&setfile.basic_info.in.write_time,  t + 3*30*24*60*60);
+       unix_to_nt_time(&setfile.basic_info.in.change_time, t + 1*30*24*60*60);
        setfile.basic_info.in.attrib      = FILE_ATTRIBUTE_NORMAL;
 
        status = smb2_setinfo_file(tree, &setfile);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Failed to setup file times - %s\n", nt_errstr(status));
+               return status;
        }
 
        /* make sure all the timestamps aren't the same */
-       fileinfo.generic.level = RAW_FILEINFO_BASIC_INFORMATION;
-       fileinfo.generic.in.handle = *handle;
+       fileinfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+       fileinfo.generic.in.file.handle = *handle;
 
        status = smb2_getinfo_file(tree, tree, &fileinfo);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Failed to query file times - %s\n", nt_errstr(status));
+               return status;
+               
        }
 
-       if (setfile.basic_info.in.create_time != fileinfo.basic_info.out.create_time) {
-               printf("create_time not setup correctly\n");
-       }
-       if (setfile.basic_info.in.access_time != fileinfo.basic_info.out.access_time) {
-               printf("access_time not setup correctly\n");
-       }
-       if (setfile.basic_info.in.write_time != fileinfo.basic_info.out.write_time) {
-               printf("write_time not setup correctly\n");
-       }
-       
-       return NT_STATUS_OK;
+#define CHECK_TIME(field) do {\
+       if (setfile.basic_info.in.field != fileinfo.all_info2.out.field) { \
+               printf("(%s) " #field " not setup correctly: %s(%llu) => %s(%llu)\n", \
+                       __location__, \
+                       nt_time_string(tree, setfile.basic_info.in.field), \
+                       (unsigned long long)setfile.basic_info.in.field, \
+                       nt_time_string(tree, fileinfo.basic_info.out.field), \
+                       (unsigned long long)fileinfo.basic_info.out.field); \
+               status = NT_STATUS_INVALID_PARAMETER; \
+       } \
+} while (0)
+
+       CHECK_TIME(create_time);
+       CHECK_TIME(access_time);
+       CHECK_TIME(write_time);
+       CHECK_TIME(change_time);
+
+       return status;
+}
+
+/*
+  create a complex file using the SMB2 protocol
+*/
+NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname, 
+                                        struct smb2_handle *handle)
+{
+       return smb2_create_complex(tree, fname, handle, False);
+}
+
+/*
+  create a complex dir using the SMB2 protocol
+*/
+NTSTATUS smb2_create_complex_dir(struct smb2_tree *tree, const char *fname, 
+                                struct smb2_handle *handle)
+{
+       return smb2_create_complex(tree, fname, handle, True);
 }
 
 /*
@@ -188,7 +218,7 @@ void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
        union smb_fileinfo io;
 
        io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
-       io.generic.in.handle = handle;
+       io.generic.in.file.handle = handle;
 
        status = smb2_getinfo_file(tree, tmp_ctx, &io);
        if (!NT_STATUS_IS_OK(status)) {
@@ -197,23 +227,23 @@ void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
                return;
        }
 
+       d_printf("all_info for '%s'\n", io.all_info2.out.fname.s);
        d_printf("\tcreate_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.create_time));
        d_printf("\taccess_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.access_time));
        d_printf("\twrite_time:     %s\n", nt_time_string(tmp_ctx, io.all_info2.out.write_time));
        d_printf("\tchange_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.change_time));
        d_printf("\tattrib:         0x%x\n", io.all_info2.out.attrib);
        d_printf("\tunknown1:       0x%x\n", io.all_info2.out.unknown1);
-       d_printf("\talloc_size:     %llu\n", (uint64_t)io.all_info2.out.alloc_size);
-       d_printf("\tsize:           %llu\n", (uint64_t)io.all_info2.out.size);
+       d_printf("\talloc_size:     %llu\n", (long long)io.all_info2.out.alloc_size);
+       d_printf("\tsize:           %llu\n", (long long)io.all_info2.out.size);
        d_printf("\tnlink:          %u\n", io.all_info2.out.nlink);
        d_printf("\tdelete_pending: %u\n", io.all_info2.out.delete_pending);
        d_printf("\tdirectory:      %u\n", io.all_info2.out.directory);
-       d_printf("\tfile_id:        %llu\n", io.all_info2.out.file_id);
+       d_printf("\tfile_id:        %llu\n", (long long)io.all_info2.out.file_id);
        d_printf("\tea_size:        %u\n", io.all_info2.out.ea_size);
        d_printf("\taccess_mask:    0x%08x\n", io.all_info2.out.access_mask);
-       d_printf("\tunknown2:       0x%llx\n", io.all_info2.out.unknown2);
-       d_printf("\tunknown3:       0x%llx\n", io.all_info2.out.unknown3);
-       d_printf("\tfname:          '%s'\n", io.all_info2.out.fname.s);
+       d_printf("\tposition:       0x%llx\n", (long long)io.all_info2.out.position);
+       d_printf("\tmode:           0x%llx\n", (long long)io.all_info2.out.mode);
 
        /* short name, if any */
        io.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
@@ -250,6 +280,18 @@ void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
                }
        }       
 
+       if (DEBUGLVL(1)) {
+               /* the security descriptor */
+               io.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
+               io.query_secdesc.in.secinfo_flags = 
+                       SECINFO_OWNER|SECINFO_GROUP|
+                       SECINFO_DACL;
+               status = smb2_getinfo_file(tree, tmp_ctx, &io);
+               if (NT_STATUS_IS_OK(status)) {
+                       NDR_PRINT_DEBUG(security_descriptor, io.query_secdesc.out.sd);
+               }
+       }
+
        talloc_free(tmp_ctx);   
 }
 
@@ -294,19 +336,18 @@ NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname,
                NTCREATEX_SHARE_ACCESS_DELETE|
                NTCREATEX_SHARE_ACCESS_READ|
                NTCREATEX_SHARE_ACCESS_WRITE;
-       io.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+       io.in.create_options = 0;
        io.in.fname = fname;
-       io.in.blob  = data_blob(NULL, 0);
 
        status = smb2_create(tree, tree, &io);
        NT_STATUS_NOT_OK_RETURN(status);
 
-       *handle = io.out.handle;
+       *handle = io.out.file.handle;
 
        ZERO_STRUCT(r);
+       r.in.file.handle = *handle;
        r.in.length      = 5;
        r.in.offset      = 0;
-       r.in.handle      = *handle;
 
        smb2_read(tree, tree, &r);
 
@@ -330,12 +371,11 @@ NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
        io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
        io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
        io.in.fname = fname;
-       io.in.blob  = data_blob(NULL, 0);
 
        status = smb2_create(tree, tree, &io);
        NT_STATUS_NOT_OK_RETURN(status);
 
-       *handle = io.out.handle;
+       *handle = io.out.file.handle;
 
        return NT_STATUS_OK;
 }
@@ -345,44 +385,49 @@ NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
   create a complex file using the old SMB protocol, to make it easier to 
   find fields in SMB2 getinfo levels
 */
-BOOL torture_setup_complex_file(const char *fname)
+NTSTATUS torture_setup_complex_file(struct smb2_tree *tree, const char *fname)
 {
-       struct smbcli_state *cli;
-       int fnum;
-
-       if (!torture_open_connection(&cli)) {
-               return False;
-       }
+       struct smb2_handle handle;
+       NTSTATUS status = smb2_create_complex_file(tree, fname, &handle);
+       NT_STATUS_NOT_OK_RETURN(status);
+       return smb2_util_close(tree, handle);
+}
 
-       fnum = create_complex_file(cli, cli, fname);
 
-       if (DEBUGLVL(1)) {
-               torture_all_info(cli->tree, fname);
-       }
-       
-       talloc_free(cli);
-       return fnum != -1;
+/*
+  create a complex dir using the old SMB protocol, to make it easier to 
+  find fields in SMB2 getinfo levels
+*/
+NTSTATUS torture_setup_complex_dir(struct smb2_tree *tree, const char *fname)
+{
+       struct smb2_handle handle;
+       NTSTATUS status = smb2_create_complex_dir(tree, fname, &handle);
+       NT_STATUS_NOT_OK_RETURN(status);
+       return smb2_util_close(tree, handle);
 }
 
+
 /*
-  create a complex directory using the old SMB protocol, to make it easier to 
-  find fields in SMB2 getinfo levels
+  return a handle to the root of the share
 */
-BOOL torture_setup_complex_dir(const char *dname)
+NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle)
 {
-       struct smbcli_state *cli;
-       int fnum;
+       struct smb2_create io;
+       NTSTATUS status;
 
-       if (!torture_open_connection(&cli)) {
-               return False;
-       }
+       ZERO_STRUCT(io);
+       io.in.oplock_flags = 0;
+       io.in.access_mask = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
+       io.in.file_attr   = 0;
+       io.in.open_disposition = NTCREATEX_DISP_OPEN;
+       io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
+       io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
+       io.in.fname = "";
 
-       fnum = create_complex_dir(cli, cli, dname);
+       status = smb2_create(tree, tree, &io);
+       NT_STATUS_NOT_OK_RETURN(status);
 
-       if (DEBUGLVL(1)) {
-               torture_all_info(cli->tree, dname);
-       }
-       
-       talloc_free(cli);
-       return fnum != -1;
+       *handle = io.out.file.handle;
+
+       return NT_STATUS_OK;
 }