r3826: - added testing of ea lists in NTTRANS CREATE
authorAndrew Tridgell <tridge@samba.org>
Wed, 17 Nov 2004 22:00:15 +0000 (22:00 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:05:57 +0000 (13:05 -0500)
- fixed push/pull of chained ea lists

- fixed a bug in the nttrans wire encoding

source/include/nterr.h
source/libcli/raw/raweas.c
source/libcli/raw/rawfile.c
source/libcli/raw/rawtrans.c
source/libcli/util/nterr.c
source/smb_server/nttrans.c
source/torture/raw/eas.c

index c5133d1a76b43b417c7cc4a3a8c0629f65efedcc..14c76144a6a6d325e640e830243326613b92d042 100644 (file)
@@ -29,6 +29,7 @@
 #define STATUS_BUFFER_OVERFLOW            NT_STATUS(0x80000005)
 #define STATUS_NO_MORE_FILES              NT_STATUS(0x80000006)
 #define NT_STATUS_NO_MORE_ENTRIES         NT_STATUS(0x8000001a)
+#define STATUS_EA_LIST_INCONSISTENT       NT_STATUS(0x80000014)
 
 #define STATUS_MORE_ENTRIES               NT_STATUS(0x0105)
 #define STATUS_SOME_UNMAPPED              NT_STATUS(0x0107)
index 52c7832a6cae47e61e920f7e3c5bda543dee0667..5bd90766aa7c7b7d28e3b46ff6e90aaf59696fe6 100644 (file)
@@ -36,6 +36,23 @@ uint_t ea_list_size(uint_t num_eas, struct ea_struct *eas)
        return total;
 }
 
+/*
+  work out how many bytes on the wire a chained ea list will consume.
+  This assumes the names are strict ascii, which should be a
+  reasonable assumption
+*/
+uint_t ea_list_size_chained(uint_t num_eas, struct ea_struct *eas)
+{
+       uint_t total = 0;
+       int i;
+       for (i=0;i<num_eas;i++) {
+               uint_t len = 8 + strlen(eas[i].name.s)+1 + eas[i].value.length;
+               len = (len + 3) & ~3;
+               total += len;
+       }
+       return total;
+}
+
 /*
   put a ea_list into a pre-allocated buffer - buffer must be at least
   of size ea_list_size()
@@ -62,6 +79,34 @@ void ea_put_list(char *data, uint_t num_eas, struct ea_struct *eas)
 }
 
 
+/*
+  put a chained ea_list into a pre-allocated buffer - buffer must be
+  at least of size ea_list_size()
+*/
+void ea_put_list_chained(char *data, uint_t num_eas, struct ea_struct *eas)
+{
+       int i;
+
+       for (i=0;i<num_eas;i++) {
+               uint_t nlen = strlen(eas[i].name.s);
+               uint32_t len = 8+nlen+1+eas[i].value.length;
+               uint_t pad = ((len + 3) & ~3) - len;
+               if (i == num_eas-1) {
+                       SIVAL(data, 0, 0);
+               } else {
+                       SIVAL(data, 0, len+pad);
+               }
+               SCVAL(data, 4, eas[i].flags);
+               SCVAL(data, 5, nlen);
+               SSVAL(data, 6, eas[i].value.length);
+               memcpy(data+8, eas[i].name.s, nlen+1);
+               memcpy(data+8+nlen+1, eas[i].value.data, eas[i].value.length);
+               memset(data+len, 0, pad);
+               data += len + pad;
+       }
+}
+
+
 /*
   pull a ea_struct from a buffer. Return the number of bytes consumed
 */
@@ -102,8 +147,8 @@ uint_t ea_pull_struct(const DATA_BLOB *blob,
   pull a ea_list from a buffer
 */
 NTSTATUS ea_pull_list(const DATA_BLOB *blob, 
-                     TALLOC_CTX *mem_ctx,
-                     uint_t *num_eas, struct ea_struct **eas)
+                             TALLOC_CTX *mem_ctx,
+                             uint_t *num_eas, struct ea_struct **eas)
 {
        int n;
        uint32_t ea_size, ofs;
@@ -116,13 +161,13 @@ NTSTATUS ea_pull_list(const DATA_BLOB *blob,
        if (ea_size > blob->length) {
                return NT_STATUS_INVALID_PARAMETER;
        }
-       
-       ofs = 4;        
+
+       ofs = 4;
        n = 0;
        *num_eas = 0;
        *eas = NULL;
 
-       while (ofs+6 < ea_size) {
+       while (ofs < ea_size) {
                uint_t len;
                DATA_BLOB blob2;
 
@@ -146,3 +191,55 @@ NTSTATUS ea_pull_list(const DATA_BLOB *blob,
        return NT_STATUS_OK;
 }
 
+
+/*
+  pull a chained ea_list from a buffer
+*/
+NTSTATUS ea_pull_list_chained(const DATA_BLOB *blob, 
+                             TALLOC_CTX *mem_ctx,
+                             uint_t *num_eas, struct ea_struct **eas)
+{
+       int n;
+       uint32_t ofs;
+
+       if (blob->length < 4) {
+               return NT_STATUS_INFO_LENGTH_MISMATCH;
+       }
+
+       ofs = 0;
+       n = 0;
+       *num_eas = 0;
+       *eas = NULL;
+
+       while (ofs < blob->length) {
+               uint_t len;
+               DATA_BLOB blob2;
+               uint32_t next_ofs = IVAL(blob->data, ofs);
+
+               blob2.data = blob->data + ofs + 4;
+               blob2.length = blob->length - (ofs + 4);
+
+               *eas = talloc_realloc(mem_ctx, *eas, sizeof(**eas) * (n+1));
+               if (! *eas) return NT_STATUS_NO_MEMORY;
+
+               len = ea_pull_struct(&blob2, mem_ctx, &(*eas)[n]);
+               if (len == 0) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               ofs += next_ofs;
+
+               if (ofs+4 > blob->length) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               n++;
+               if (next_ofs == 0) break;
+       }
+
+       *num_eas = n;
+
+       return NT_STATUS_OK;
+}
+
+
+
index 5fc40bc45a4864ff8378b911e63f5ab32db04271..69b8c6a07c4c9c08741f0dfe25e20b3b0c5db407 100644 (file)
@@ -287,15 +287,15 @@ static struct smbcli_request *smb_raw_nttrans_create_send(struct smbcli_tree *tr
        }
 
        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);
+               uint32_t ea_size = ea_list_size_chained(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);
+               ea_put_list_chained(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);
index 111a7ded2a1181ed02153d182bc660a64881e91f..2554a736f5a5c3d52484dd75a78c05156d4c2648 100644 (file)
@@ -505,7 +505,7 @@ struct smbcli_request *smb_raw_nttrans_send(struct smbcli_tree *tree,
                memcpy(outparam, parms->in.params.data, parms->in.params.length);
        }
        if (parms->in.data.length) {
-               memcpy(outparam, parms->in.data.data, parms->in.data.length);
+               memcpy(outdata, parms->in.data.data, parms->in.data.length);
        }
 
        if (!smbcli_request_send(req)) {
index 2adb56122291b8ea260cfdab87d637ab9e79b953..eac7989800fcaf6c40ff78d36d45c6e3a4cbcf6f 100644 (file)
@@ -32,6 +32,7 @@ static const nt_err_code_struct nt_errs[] =
 {
        { "NT_STATUS_OK", NT_STATUS_OK },
        { "STATUS_NO_MORE_FILES", STATUS_NO_MORE_FILES },
+       { "STATUS_EA_LIST_INCONSISTENT", STATUS_EA_LIST_INCONSISTENT },
        { "NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL },
        { "NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED },
        { "NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS },
index 49c41181a8773427f26e74f6d23b0212a530fb26..3b06dc024062f0ac48996942175132a9b9d41398 100644 (file)
@@ -131,12 +131,9 @@ static NTSTATUS nttrans_create(struct smbsrv_request *req,
                        return NT_STATUS_NO_MEMORY;
                }
 
-               /* w2k gets the length of the list wrong on the wire - auto-fix */
-               SIVAL(blob.data, 0, ea_length);
-
-               status = ea_pull_list(&blob, io, 
-                                     &io->ntcreatex.in.ea_list->num_eas,
-                                     &io->ntcreatex.in.ea_list->eas);
+               status = ea_pull_list_chained(&blob, io, 
+                                             &io->ntcreatex.in.ea_list->num_eas,
+                                             &io->ntcreatex.in.ea_list->eas);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
index 63792f92dad535d37f0104dd5b6fa1e8d2be4fc5..c76d8a9f582de7830442a6a943c315d9f9baed0a 100644 (file)
@@ -100,6 +100,8 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        BOOL ret = True;
        int fnum;
 
+       printf("TESTING SETFILEINFO EA_SET\n");
+
        io.generic.level = RAW_OPEN_NTCREATEX;
        io.ntcreatex.in.root_fid = 0;
        io.ntcreatex.in.flags = 0;
@@ -182,7 +184,70 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
 done:
        smbcli_close(cli->tree, fnum);
-       return True;
+       return ret;
+}
+
+
+/*
+  test using NTTRANS CREATE to create a file with an initial EA set
+*/
+static BOOL test_open_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+       NTSTATUS status;
+       union smb_open io;
+       const char *fname = BASEDIR "\\ea2.txt";
+       BOOL ret = True;
+       int fnum = -1;
+       struct ea_struct eas[3];
+       struct smb_ea_list ea_list;
+
+       printf("TESTING NTTRANS CREATE WITH EAS\n");
+
+       io.generic.level = RAW_OPEN_NTTRANS_CREATE;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.flags = 0;
+       io.ntcreatex.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = 
+               NTCREATEX_SHARE_ACCESS_READ | 
+               NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+
+       ea_list.num_eas = 3;
+       ea_list.eas = eas;
+
+       eas[0].flags = 0;
+       eas[0].name.s = "1st EA";
+       eas[0].value = data_blob_string_const("Value One");
+
+       eas[1].flags = 0;
+       eas[1].name.s = "2nd EA";
+       eas[1].value = data_blob_string_const("Second Value");
+
+       eas[2].flags = 0;
+       eas[2].name.s = "and 3rd";
+       eas[2].value = data_blob_string_const("final value");
+
+       io.ntcreatex.in.ea_list = &ea_list;
+       io.ntcreatex.in.sec_desc = NULL;
+
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.fnum;
+       
+       ret &= check_ea(cli, mem_ctx, fname, "EAONE", NULL);
+       ret &= check_ea(cli, mem_ctx, fname, "1st EA", "Value One");
+       ret &= check_ea(cli, mem_ctx, fname, "2nd EA", "Second Value");
+       ret &= check_ea(cli, mem_ctx, fname, "and 3rd", "final value");
+
+done:
+       smbcli_close(cli->tree, fnum);
+       return ret;
 }
 
 /* 
@@ -205,6 +270,7 @@ BOOL torture_raw_eas(void)
        }
 
        ret &= test_eas(cli, mem_ctx);
+       ret &= test_open_eas(cli, mem_ctx);
 
        smb_raw_exit(cli->session);
        smbcli_deltree(cli->tree, BASEDIR);