r3821: added client side code and test code for NTTRANS_CREATE
authorAndrew Tridgell <tridge@samba.org>
Wed, 17 Nov 2004 20:56:26 +0000 (20:56 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:05:56 +0000 (13:05 -0500)
(This used to be commit 8422789c06c203ea1c4761fecb16f79f99ac479b)

source4/libcli/raw/rawfile.c
source4/torture/raw/open.c

index 4da7ff3a9e189ae5ee43621742138eedc8053092..5fc40bc45a4864ff8378b911e63f5ab32db04271 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "includes.h"
 #include "libcli/raw/libcliraw.h"
+#include "librpc/gen_ndr/ndr_security.h"
 
 #define SETUP_REQUEST(cmd, wct, buflen) do { \
        req = smbcli_request_setup(tree, cmd, wct, buflen); \
@@ -213,6 +214,132 @@ NTSTATUS smb_raw_rmdir(struct smbcli_tree *tree,
 }
 
 
+/*
+ Open a file using TRANSACT2_OPEN - async recv
+*/
+static NTSTATUS smb_raw_nttrans_create_recv(struct smbcli_request *req, 
+                                           TALLOC_CTX *mem_ctx, 
+                                           union smb_open *parms)
+{
+       NTSTATUS status;
+       struct smb_nttrans nt;
+       uint8_t *params;
+
+       status = smb_raw_nttrans_recv(req, mem_ctx, &nt);
+       if (!NT_STATUS_IS_OK(status)) return status;
+
+       if (nt.out.params.length < 69) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       params = nt.out.params.data;
+
+       parms->ntcreatex.out.oplock_level =                 CVAL(params, 0);
+       parms->ntcreatex.out.fnum =                         SVAL(params, 2);
+       parms->ntcreatex.out.create_action =                IVAL(params, 4);
+       parms->ntcreatex.out.create_time =   smbcli_pull_nttime(params, 12);
+       parms->ntcreatex.out.access_time =   smbcli_pull_nttime(params, 20);
+       parms->ntcreatex.out.write_time =    smbcli_pull_nttime(params, 28);
+       parms->ntcreatex.out.change_time =   smbcli_pull_nttime(params, 36);
+       parms->ntcreatex.out.attrib =                      IVAL(params, 44);
+       parms->ntcreatex.out.alloc_size =                  BVAL(params, 48);
+       parms->ntcreatex.out.size =                        BVAL(params, 56);
+       parms->ntcreatex.out.file_type =                   SVAL(params, 64);
+       parms->ntcreatex.out.ipc_state =                   SVAL(params, 66);
+       parms->ntcreatex.out.is_directory =                CVAL(params, 68);
+       
+       return NT_STATUS_OK;
+}
+
+
+/*
+ Open a file using NTTRANS CREATE - async send 
+*/
+static struct smbcli_request *smb_raw_nttrans_create_send(struct smbcli_tree *tree, 
+                                                         union smb_open *parms)
+{
+       struct smb_nttrans nt;
+       uint8_t *params;
+       TALLOC_CTX *mem_ctx = talloc(tree, 0);
+       uint16_t fname_len;
+       DATA_BLOB sd_blob, ea_blob;
+       struct smbcli_request *req;
+       NTSTATUS status;
+
+       nt.in.max_setup = 0;
+       nt.in.max_param = 101;
+       nt.in.max_data  = 0;
+       nt.in.setup_count = 0;
+       nt.in.function = NT_TRANSACT_CREATE;
+       nt.in.setup = NULL;
+
+       sd_blob = data_blob(NULL, 0);
+       ea_blob = data_blob(NULL, 0);
+
+       if (parms->ntcreatex.in.sec_desc) {
+               status = ndr_push_struct_blob(&sd_blob, mem_ctx, 
+                                             parms->ntcreatex.in.sec_desc, 
+                                             (ndr_push_flags_fn_t)ndr_push_security_descriptor);
+               if (!NT_STATUS_IS_OK(status)) {
+                       talloc_free(mem_ctx);
+                       return NULL;
+               }
+       }
+
+       if (parms->ntcreatex.in.ea_list) {
+               uint32_t ea_size = ea_list_size(parms->ntcreatex.in.ea_list->num_eas,
+                                               parms->ntcreatex.in.ea_list->eas);
+               ea_blob = data_blob_talloc(mem_ctx, NULL, ea_size);
+               if (ea_blob.data == NULL) {
+                       return NULL;
+               }
+               ea_put_list(ea_blob.data, 
+                           parms->ntcreatex.in.ea_list->num_eas,
+                           parms->ntcreatex.in.ea_list->eas);
+       }
+
+       nt.in.params = data_blob_talloc(mem_ctx, NULL, 54);
+       if (nt.in.params.data == NULL) {
+               talloc_free(mem_ctx);
+               return NULL;
+       }
+
+       /* build the parameter section */
+       params = nt.in.params.data;
+
+       SIVAL(params,  0, parms->ntcreatex.in.flags);
+       SIVAL(params,  4, parms->ntcreatex.in.root_fid);
+       SIVAL(params,  8, parms->ntcreatex.in.access_mask);
+       SBVAL(params, 12, parms->ntcreatex.in.alloc_size);
+       SIVAL(params, 20, parms->ntcreatex.in.file_attr);
+       SIVAL(params, 24, parms->ntcreatex.in.share_access);
+       SIVAL(params, 28, parms->ntcreatex.in.open_disposition);
+       SIVAL(params, 32, parms->ntcreatex.in.create_options);
+       SIVAL(params, 36, sd_blob.length);
+       SIVAL(params, 40, ea_blob.length);
+       SIVAL(params, 48, parms->ntcreatex.in.impersonation);
+       SCVAL(params, 52, parms->ntcreatex.in.security_flags);
+       SCVAL(params, 53, 0);
+       
+       fname_len = smbcli_blob_append_string(tree->session, mem_ctx, &nt.in.params,
+                                             parms->ntcreatex.in.fname, STR_TERMINATE);
+
+       SIVAL(nt.in.params.data, 44, fname_len);
+
+       /* build the data section */
+       nt.in.data = data_blob_talloc(mem_ctx, NULL, sd_blob.length + ea_blob.length);
+       memcpy(nt.in.data.data, sd_blob.data, sd_blob.length);
+       memcpy(nt.in.data.data+sd_blob.length, ea_blob.data, ea_blob.length);
+
+       /* send the request on its way */
+       req = smb_raw_nttrans_send(tree, &nt);
+
+       talloc_free(mem_ctx);
+       
+       return req;
+}
+
+
 /****************************************************************************
  Open a file using TRANSACT2_OPEN - async send 
 ****************************************************************************/
@@ -377,6 +504,9 @@ struct smbcli_request *smb_raw_open_send(struct smbcli_tree *tree, union smb_ope
                smbcli_req_append_string_len(req, parms->ntcreatex.in.fname, STR_TERMINATE, &len);
                SSVAL(req->out.vwv, 5, len);
                break;
+
+       case RAW_OPEN_NTTRANS_CREATE:
+               return smb_raw_nttrans_create_send(tree, parms);
        }
 
        if (!smbcli_request_send(req)) {
@@ -469,6 +599,9 @@ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, unio
                parms->ntcreatex.out.ipc_state =                SVAL(req->in.vwv, 65);
                parms->ntcreatex.out.is_directory =             CVAL(req->in.vwv, 67);
                break;
+
+       case RAW_OPEN_NTTRANS_CREATE:
+               return smb_raw_nttrans_create_recv(req, mem_ctx, parms);
        }
 
 failed:
index b80f6278c6d4daa8846f59ed8a9bb1d59a2a0cc0..f938c82cfb29566f871601de2c5a403fce7077a3 100644 (file)
@@ -745,6 +745,181 @@ static BOOL test_ntcreatex(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        smbcli_unlink(cli->tree, fname);
        
 
+done:
+       smbcli_close(cli->tree, fnum);
+       smbcli_unlink(cli->tree, fname);
+
+       return ret;
+}
+
+
+/*
+  test RAW_OPEN_NTTRANS_CREATE
+*/
+static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+       union smb_open io;
+       union smb_fileinfo finfo;
+       const char *fname = BASEDIR "\\torture_ntcreatex.txt";
+       const char *dname = BASEDIR "\\torture_ntcreatex.dir";
+       NTSTATUS status;
+       int fnum = -1;
+       BOOL ret = True;
+       int i;
+       struct {
+               uint32_t open_disp;
+               BOOL with_file;
+               NTSTATUS correct_status;
+       } open_funcs[] = {
+               { NTCREATEX_DISP_SUPERSEDE,     True,  NT_STATUS_OK },
+               { NTCREATEX_DISP_SUPERSEDE,     False, NT_STATUS_OK },
+               { NTCREATEX_DISP_OPEN,          True,  NT_STATUS_OK },
+               { NTCREATEX_DISP_OPEN,          False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
+               { NTCREATEX_DISP_CREATE,        True,  NT_STATUS_OBJECT_NAME_COLLISION },
+               { NTCREATEX_DISP_CREATE,        False, NT_STATUS_OK },
+               { NTCREATEX_DISP_OPEN_IF,       True,  NT_STATUS_OK },
+               { NTCREATEX_DISP_OPEN_IF,       False, NT_STATUS_OK },
+               { NTCREATEX_DISP_OVERWRITE,     True,  NT_STATUS_OK },
+               { NTCREATEX_DISP_OVERWRITE,     False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
+               { NTCREATEX_DISP_OVERWRITE_IF,  True,  NT_STATUS_OK },
+               { NTCREATEX_DISP_OVERWRITE_IF,  False, NT_STATUS_OK },
+               { 6,                            True,  NT_STATUS_INVALID_PARAMETER },
+               { 6,                            False, NT_STATUS_INVALID_PARAMETER },
+       };
+
+       printf("Checking RAW_OPEN_NTTRANS_CREATE\n");
+
+       /* reasonable default parameters */
+       io.generic.level = RAW_OPEN_NTTRANS_CREATE;
+       io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
+       io.ntcreatex.in.alloc_size = 1024*1024;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+       io.ntcreatex.in.sec_desc = NULL;
+       io.ntcreatex.in.ea_list = NULL;
+
+       /* test the open disposition */
+       for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
+               if (open_funcs[i].with_file) {
+                       fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
+                       if (fnum == -1) {
+                               d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
+                               ret = False;
+                               goto done;
+                       }
+                       smbcli_close(cli->tree, fnum);
+               }
+               io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
+               status = smb_raw_open(cli->tree, mem_ctx, &io);
+               if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
+                       printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n", 
+                              __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
+                              i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp);
+                       ret = False;
+               }
+               if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
+                       smbcli_close(cli->tree, io.ntcreatex.out.fnum);
+                       smbcli_unlink(cli->tree, fname);
+               }
+       }
+
+       /* basic field testing */
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.fnum;
+
+       CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
+       CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
+       CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
+       CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
+       CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
+       CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
+       CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
+       CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
+       CHECK_ALL_INFO(io.ntcreatex.out.size, size);
+       CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
+       CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
+
+       /* check fields when the file already existed */
+       smbcli_close(cli->tree, fnum);
+       smbcli_unlink(cli->tree, fname);
+       fnum = create_complex_file(cli, mem_ctx, fname);
+       if (fnum == -1) {
+               ret = False;
+               goto done;
+       }
+       smbcli_close(cli->tree, fnum);
+
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.fnum;
+
+       CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
+       CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
+       CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
+       CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
+       CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
+       CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
+       CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
+       CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
+       CHECK_ALL_INFO(io.ntcreatex.out.size, size);
+       CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
+       CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
+       smbcli_close(cli->tree, fnum);
+       smbcli_unlink(cli->tree, fname);
+
+
+       /* create a directory */
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.fname = dname;
+       fname = dname;
+
+       smbcli_rmdir(cli->tree, fname);
+       smbcli_unlink(cli->tree, fname);
+
+       io.ntcreatex.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED;
+       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;
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.fnum;
+
+       CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
+       CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
+       CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
+       CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
+       CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
+       CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
+       CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
+       CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED, 
+                 FILE_ATTRIBUTE_DIRECTORY);
+       CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
+       CHECK_ALL_INFO(io.ntcreatex.out.size, size);
+       CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
+       CHECK_VAL(io.ntcreatex.out.is_directory, 1);
+       CHECK_VAL(io.ntcreatex.out.size, 0);
+       CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
+       CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
+       smbcli_unlink(cli->tree, fname);
+       
+
 done:
        smbcli_close(cli->tree, fnum);
        smbcli_unlink(cli->tree, fname);
@@ -1001,6 +1176,7 @@ BOOL torture_raw_open(void)
        ret &= test_open(cli, mem_ctx);
        ret &= test_openx(cli, mem_ctx);
        ret &= test_ntcreatex(cli, mem_ctx);
+       ret &= test_nttrans_create(cli, mem_ctx);
        ret &= test_t2open(cli, mem_ctx);
        ret &= test_mknew(cli, mem_ctx);
        ret &= test_create(cli, mem_ctx);