Remove all uses of the NT_STATUS_NOT_OK_RETURN_AND_FREE macro from the codebase.
[obnox/samba/samba-obnox.git] / source4 / torture / util_smb.c
index 99b00d232939febb7f42dcb967a3e5c16b0727a9..588ac055c7ed458f7b4a8a1140056e863d3744da 100644 (file)
@@ -22,7 +22,7 @@
 #include "lib/cmdline/popt_common.h"
 #include "libcli/raw/libcliraw.h"
 #include "libcli/raw/raw_proto.h"
-#include "libcli/raw/ioctl.h"
+#include "../libcli/smb/smb_constants.h"
 #include "libcli/libcli.h"
 #include "system/filesys.h"
 #include "system/shmem.h"
 #include "system/time.h"
 #include "torture/torture.h"
 #include "../lib/util/dlinklist.h"
-#include "auth/credentials/credentials.h"
 #include "libcli/resolve/resolve.h"
 #include "param/param.h"
-
+#include "libcli/security/security.h"
+#include "libcli/util/clilsa.h"
+#include "torture/util.h"
+#include "libcli/smb/smbXcli_base.h"
 
 /**
   setup a directory ready for a test
@@ -61,12 +63,12 @@ NTSTATUS create_directory_handle(struct smbcli_tree *tree, const char *dname, in
        mem_ctx = talloc_named_const(tree, 0, "create_directory_handle");
 
        io.generic.level = RAW_OPEN_NTCREATEX;
-       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.root_fid.fnum = 0;
        io.ntcreatex.in.flags = 0;
        io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
        io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
        io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
-       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
        io.ntcreatex.in.alloc_size = 0;
        io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
        io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
@@ -128,14 +130,17 @@ _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
                }
        }
 
-       /* make sure all the timestamps aren't the same, and are also 
-          in different DST zones*/
-       setfile.generic.level = RAW_SFILEINFO_SETATTRE;
+       /* make sure all the timestamps aren't the same */
+       ZERO_STRUCT(setfile);
+       setfile.generic.level = RAW_SFILEINFO_BASIC_INFO;
        setfile.generic.in.file.fnum = fnum;
 
-       setfile.setattre.in.create_time = t + 9*30*24*60*60;
-       setfile.setattre.in.access_time = t + 6*30*24*60*60;
-       setfile.setattre.in.write_time  = t + 3*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);
 
        status = smb_raw_setfileinfo(cli->tree, &setfile);
        if (!NT_STATUS_IS_OK(status)) {
@@ -143,7 +148,7 @@ _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
        }
 
        /* make sure all the timestamps aren't the same */
-       fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
+       fileinfo.generic.level = RAW_FILEINFO_BASIC_INFO;
        fileinfo.generic.in.file.fnum = fnum;
 
        status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
@@ -151,13 +156,13 @@ _PUBLIC_ int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
                printf("Failed to query file times - %s\n", nt_errstr(status));
        }
 
-       if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
+       if (setfile.basic_info.in.create_time != fileinfo.basic_info.out.create_time) {
                printf("create_time not setup correctly\n");
        }
-       if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
+       if (setfile.basic_info.in.access_time != fileinfo.basic_info.out.access_time) {
                printf("access_time not setup correctly\n");
        }
-       if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
+       if (setfile.basic_info.in.write_time != fileinfo.basic_info.out.write_time) {
                printf("write_time not setup correctly\n");
        }
 
@@ -205,14 +210,17 @@ int create_complex_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char
                }
        }
 
-       /* make sure all the timestamps aren't the same, and are also 
-          in different DST zones*/
-       setfile.generic.level = RAW_SFILEINFO_SETATTRE;
+       /* make sure all the timestamps aren't the same */
+       ZERO_STRUCT(setfile);
+       setfile.generic.level = RAW_SFILEINFO_BASIC_INFO;
        setfile.generic.in.file.fnum = fnum;
 
-       setfile.setattre.in.create_time = t + 9*30*24*60*60;
-       setfile.setattre.in.access_time = t + 6*30*24*60*60;
-       setfile.setattre.in.write_time  = t + 3*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);
 
        status = smb_raw_setfileinfo(cli->tree, &setfile);
        if (!NT_STATUS_IS_OK(status)) {
@@ -220,7 +228,7 @@ int create_complex_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char
        }
 
        /* make sure all the timestamps aren't the same */
-       fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
+       fileinfo.generic.level = RAW_FILEINFO_BASIC_INFO;
        fileinfo.generic.in.file.fnum = fnum;
 
        status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
@@ -228,76 +236,19 @@ int create_complex_dir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char
                printf("Failed to query file times - %s\n", nt_errstr(status));
        }
 
-       if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
+       if (setfile.basic_info.in.create_time != fileinfo.basic_info.out.create_time) {
                printf("create_time not setup correctly\n");
        }
-       if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
+       if (setfile.basic_info.in.access_time != fileinfo.basic_info.out.access_time) {
                printf("access_time not setup correctly\n");
        }
-       if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
+       if (setfile.basic_info.in.write_time != fileinfo.basic_info.out.write_time) {
                printf("write_time not setup correctly\n");
        }
 
        return fnum;
 }
 
-
-
-/* return a pointer to a anonymous shared memory segment of size "size"
-   which will persist across fork() but will disappear when all processes
-   exit 
-
-   The memory is not zeroed 
-
-   This function uses system5 shared memory. It takes advantage of a property
-   that the memory is not destroyed if it is attached when the id is removed
-   */
-void *shm_setup(int size)
-{
-       int shmid;
-       void *ret;
-
-#ifdef __QNXNTO__
-       shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-       if (shmid == -1) {
-               printf("can't get shared memory\n");
-               exit(1);
-       }
-       shm_unlink("private");
-       if (ftruncate(shmid, size) == -1) {
-               printf("can't set shared memory size\n");
-               exit(1);
-       }
-       ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
-       if (ret == MAP_FAILED) {
-               printf("can't map shared memory\n");
-               exit(1);
-       }
-#else
-       shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
-       if (shmid == -1) {
-               printf("can't get shared memory\n");
-               exit(1);
-       }
-       ret = (void *)shmat(shmid, 0, 0);
-       if (!ret || ret == (void *)-1) {
-               printf("can't attach to shared memory\n");
-               return NULL;
-       }
-       /* the following releases the ipc, but note that this process
-          and all its children will still have access to the memory, its
-          just that the shmid is no longer valid for other shm calls. This
-          means we don't leave behind lots of shm segments after we exit 
-
-          See Stevens "advanced programming in unix env" for details
-          */
-       shmctl(shmid, IPC_RMID, 0);
-#endif
-       
-       return ret;
-}
-
-
 /**
   check that a wire string matches the flags specified 
   not 100% accurate, but close enough for testing
@@ -495,21 +446,20 @@ _PUBLIC_ bool torture_open_connection_share(TALLOC_CTX *mem_ctx,
        struct smbcli_options options;
        struct smbcli_session_options session_options;
 
-       lp_smbcli_options(tctx->lp_ctx, &options);
-       lp_smbcli_session_options(tctx->lp_ctx, &session_options);
+       lpcfg_smbcli_options(tctx->lp_ctx, &options);
+       lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
 
        options.use_oplocks = torture_setting_bool(tctx, "use_oplocks", true);
        options.use_level2_oplocks = torture_setting_bool(tctx, "use_level2_oplocks", true);
 
        status = smbcli_full_connection(mem_ctx, c, hostname, 
-                                       lp_smb_ports(tctx->lp_ctx),
+                                       lpcfg_smb_ports(tctx->lp_ctx),
                                        sharename, NULL,
-                                       lp_socket_options(tctx->lp_ctx),
+                                       lpcfg_socket_options(tctx->lp_ctx),
                                        cmdline_credentials, 
-                                       lp_resolve_context(tctx->lp_ctx),
+                                       lpcfg_resolve_context(tctx->lp_ctx),
                                        ev, &options, &session_options,
-                                       lp_iconv_convenience(tctx->lp_ctx),
-                                       lp_gensec_settings(tctx, tctx->lp_ctx));
+                                       lpcfg_gensec_settings(tctx, tctx->lp_ctx));
        if (!NT_STATUS_IS_OK(status)) {
                printf("Failed to open connection - %s\n", nt_errstr(status));
                return false;
@@ -541,8 +491,11 @@ _PUBLIC_ bool torture_get_conn_index(int conn_index,
                return false;
        }
 
-       if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
-                             mem_ctx, host, share)) {
+       p = unc_list[conn_index % num_unc_names];
+       if (p[0] != '/' && p[0] != '\\') {
+               /* allow UNC lists of hosts */
+               (*host) = talloc_strdup(mem_ctx, p);
+       } else if (!smbcli_parse_unc(p, mem_ctx, host, share)) {
                DEBUG(0, ("Failed to parse UNC name %s\n",
                          unc_list[conn_index % num_unc_names]));
                return false;
@@ -647,13 +600,13 @@ double torture_create_procs(struct torture_context *tctx,
 
        signal(SIGCONT, sigcont);
 
-       child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
+       child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
        if (!child_status) {
                printf("Failed to setup shared memory\n");
                return -1;
        }
 
-       child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs);
+       child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
        if (!child_status_out) {
                printf("Failed to setup result status shared memory\n");
                return -1;
@@ -678,7 +631,7 @@ double torture_create_procs(struct torture_context *tctx,
                                printf("asprintf failed\n");
                                return -1;
                        }
-                       lp_set_cmdline(tctx->lp_ctx, "netbios name", myname);
+                       lpcfg_set_cmdline(tctx->lp_ctx, "netbios name", myname);
                        free(myname);
 
 
@@ -690,7 +643,7 @@ double torture_create_procs(struct torture_context *tctx,
                                        printf("pid %d failed to start\n", (int)getpid());
                                        _exit(1);
                                }
-                               msleep(100);    
+                               smb_msleep(100);        
                        }
 
                        child_status[i] = getpid();
@@ -714,11 +667,19 @@ double torture_create_procs(struct torture_context *tctx,
                        if (child_status[i]) synccount++;
                }
                if (synccount == torture_nprocs) break;
-               msleep(100);
+               smb_msleep(100);
        } while (timeval_elapsed(&tv) < start_time_limit);
 
        if (synccount != torture_nprocs) {
                printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
+
+               /* cleanup child processes */
+               for (i = 0; i < torture_nprocs; i++) {
+                       if (child_status[i]) {
+                               kill(child_status[i], SIGTERM);
+                       }
+               }
+
                *result = false;
                return timeval_elapsed(&tv);
        }
@@ -797,18 +758,17 @@ static bool wrap_simple_2smb_test(struct torture_context *torture_ctx,
 {
        bool (*fn) (struct torture_context *, struct smbcli_state *,
                                struct smbcli_state *);
-       bool ret;
+       bool ret = true;
 
-       struct smbcli_state *cli1, *cli2;
+       struct smbcli_state *cli1 = NULL, *cli2 = NULL;
 
-       if (!torture_open_connection(&cli1, torture_ctx, 0) || 
-               !torture_open_connection(&cli2, torture_ctx, 1))
-               return false;
+       torture_assert_goto(torture_ctx, torture_open_connection(&cli1, torture_ctx, 0), ret, fail, "Failed to open connection");
+       torture_assert_goto(torture_ctx, torture_open_connection(&cli2, torture_ctx, 1), ret, fail, "Failed to open connection");
 
        fn = test->fn;
 
        ret = fn(torture_ctx, cli1, cli2);
-
+fail:
        talloc_free(cli1);
        talloc_free(cli2);
 
@@ -848,17 +808,16 @@ static bool wrap_simple_1smb_test(struct torture_context *torture_ctx,
                                                                        struct torture_test *test)
 {
        bool (*fn) (struct torture_context *, struct smbcli_state *);
-       bool ret;
+       bool ret = true;
 
-       struct smbcli_state *cli1;
+       struct smbcli_state *cli1 = NULL;
 
-       if (!torture_open_connection(&cli1, torture_ctx, 0))
-               return false;
+       torture_assert_goto(torture_ctx, torture_open_connection(&cli1, torture_ctx, 0), ret, fail, "Failed to open connection");
 
        fn = test->fn;
 
        ret = fn(torture_ctx, cli1);
-
+fail:
        talloc_free(cli1);
 
        return ret;
@@ -909,7 +868,8 @@ NTSTATUS torture_second_tcon(TALLOC_CTX *mem_ctx,
        }
 
        tcon.generic.level = RAW_TCON_TCONX;
-       tcon.tconx.in.flags = 0;
+       tcon.tconx.in.flags = TCONX_FLAG_EXTENDED_RESPONSE;
+       tcon.tconx.in.flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
 
        /* Ignore share mode security here */
        tcon.tconx.in.password = data_blob(NULL, 0);
@@ -923,7 +883,49 @@ NTSTATUS torture_second_tcon(TALLOC_CTX *mem_ctx,
        }
 
        result->tid = tcon.tconx.out.tid;
+
+       if (tcon.tconx.out.options & SMB_EXTENDED_SIGNATURES) {
+               smb1cli_session_protect_session_key(result->session->smbXcli);
+       }
+
        *res = talloc_steal(mem_ctx, result);
        talloc_free(tmp_ctx);
        return NT_STATUS_OK;
 }
+
+/* 
+   a wrapper around smblsa_sid_check_privilege, that tries to take
+   account of the fact that the lsa privileges calls don't expand
+   group memberships, using an explicit check for administrator. There
+   must be a better way ...
+ */
+NTSTATUS torture_check_privilege(struct smbcli_state *cli, 
+                                const char *sid_str,
+                                const char *privilege)
+{
+       struct dom_sid *sid;
+       TALLOC_CTX *tmp_ctx = talloc_new(cli);
+       uint32_t rid;
+       NTSTATUS status;
+
+       sid = dom_sid_parse_talloc(tmp_ctx, sid_str);
+       if (sid == NULL) {
+               talloc_free(tmp_ctx);
+               return NT_STATUS_INVALID_SID;
+       }
+
+       status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(tmp_ctx);
+               return status;
+       }
+
+       if (rid == DOMAIN_RID_ADMINISTRATOR) {
+               /* assume the administrator has them all */
+               return NT_STATUS_OK;
+       }
+
+       talloc_free(tmp_ctx);
+
+       return smblsa_sid_check_privilege(cli, sid_str, privilege);
+}