r3806: added support to smb_server and pvfs for the NTTRANS Create call. This
authorAndrew Tridgell <tridge@samba.org>
Wed, 17 Nov 2004 12:36:14 +0000 (12:36 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:05:56 +0000 (13:05 -0500)
call has an optional sec_desc and ea_list.

source/include/smb_interfaces.h
source/libcli/raw/raweas.c
source/librpc/idl/xattr.idl
source/ntvfs/posix/pvfs_open.c
source/ntvfs/posix/pvfs_qfileinfo.c
source/ntvfs/posix/pvfs_setfileinfo.c
source/ntvfs/posix/pvfs_streams.c
source/smb_server/nttrans.c
source/smb_server/reply.c

index 43cb8af5a76911369d15923aa3cf4d7ba3a3af4d..1f0912a1490a93914ea6a0fc8ad1682da22f74f4 100644 (file)
@@ -433,7 +433,7 @@ union smb_fileinfo {
                enum smb_fileinfo_level level;
                union smb_fileinfo_in in;
 
-               struct smb_all_eas {
+               struct smb_ea_list {
                        /* the ea_size is implied by the list */
                        uint_t num_eas;
                        struct ea_struct *eas;
@@ -1037,7 +1037,8 @@ enum smb_open_level {
                 RAW_OPEN_OPEN, RAW_OPEN_OPENX, 
                 RAW_OPEN_MKNEW, RAW_OPEN_CREATE, 
                 RAW_OPEN_CTEMP, RAW_OPEN_SPLOPEN,
-                RAW_OPEN_NTCREATEX, RAW_OPEN_T2OPEN};
+                RAW_OPEN_NTCREATEX, RAW_OPEN_T2OPEN,
+                RAW_OPEN_NTTRANS_CREATE};
 
 /* the generic interface is defined to be equal to the NTCREATEX interface */
 #define RAW_OPEN_GENERIC RAW_OPEN_NTCREATEX
@@ -1063,6 +1064,11 @@ union smb_open {
                         uint64_t file_id if create_options has the
                         NTCREATEX_OPTIONS_OPEN_BY_FILE_ID flag set */
                        const char *fname;
+
+                       /* these last 2 elements are only used in the
+                          NTTRANS varient of the call */
+                       struct security_descriptor *sec_desc;
+                       struct smb_ea_list *ea_list;
                } in;
 
                struct {
index da079c402b410db467b7205920a434b711d2fecc..52c7832a6cae47e61e920f7e3c5bda543dee0667 100644 (file)
@@ -122,7 +122,7 @@ NTSTATUS ea_pull_list(const DATA_BLOB *blob,
        *num_eas = 0;
        *eas = NULL;
 
-       while (ofs < ea_size) {
+       while (ofs+6 < ea_size) {
                uint_t len;
                DATA_BLOB blob2;
 
index b2e13bfbe79487379f8fbeec024fa2f0fc76b898..703fb2325b7202fdb33c330a1e1061c8f016dcb9 100644 (file)
@@ -59,6 +59,8 @@ interface xattr
        /* stream data is stored in attributes with the given prefix */
        const string XATTR_DOSSTREAM_PREFIX = "user.DosStream.";
 
+       const int XATTR_MAX_STREAM_SIZE = 0x4000;
+
        typedef struct {
                uint32     flags;
                uint64     size;
index d8f3342f0d19293ddc0ce283c317e967be6777d5..1b9538d7e224ed0b4947c6bde01253821c7cb38f 100644 (file)
@@ -429,6 +429,20 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
                return status;
        }
 
+       /* setup any EAs that were asked for */
+       if (io->ntcreatex.in.ea_list) {
+               int i;
+               for (i=0;i<io->ntcreatex.in.ea_list->num_eas;i++) {
+                       status = pvfs_setfileinfo_ea_set(pvfs, name, fd, 
+                                                        &io->ntcreatex.in.ea_list->eas[i]);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               idr_remove(pvfs->idtree_fnum, fnum);
+                               close(fd);
+                               return status;
+                       }
+               }
+       }
+
        /* form the lock context used for byte range locking and
           opendb locking */
        status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
@@ -792,7 +806,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
 
        /* use the generic mapping code to avoid implementing all the
           different open calls. */
-       if (io->generic.level != RAW_OPEN_GENERIC) {
+       if (io->generic.level != RAW_OPEN_GENERIC &&
+           io->generic.level != RAW_OPEN_NTTRANS_CREATE) {
                return ntvfs_map_open(req, io, ntvfs);
        }
 
index 3959fbfc163faf231a6e123b1e3c0e00ea778e76..f6e1288b1dd3327b4165506d05284cca6ac34eed 100644 (file)
@@ -28,7 +28,8 @@
   reply to a RAW_FILEINFO_ALL_EAS call
 */
 static NTSTATUS pvfs_query_all_eas(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, 
-                                  struct pvfs_filename *name, int fd, struct smb_all_eas *eas)
+                                  struct pvfs_filename *name, int fd, 
+                                  struct smb_ea_list *eas)
 {
        NTSTATUS status;
        int i;
index 37d8a290b8625b36683f556a102b873e08295c96..d31bcac337088d128424109d25d1820c5c6c8de6 100644 (file)
@@ -113,9 +113,9 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
 /*
   add a single DOS EA
 */
-static NTSTATUS pvfs_setfileinfo_ea_set(struct pvfs_state *pvfs, 
-                                       struct pvfs_filename *name,
-                                       int fd, struct ea_struct *ea)
+NTSTATUS pvfs_setfileinfo_ea_set(struct pvfs_state *pvfs, 
+                                struct pvfs_filename *name,
+                                int fd, struct ea_struct *ea)
 {
        struct xattr_DosEAs *ealist = talloc_p(pvfs, struct xattr_DosEAs);
        int i;
index 13a4ca1265a81ad0dc058a465db864b913602e1a..12f783e1729c7112642031f261a45edb659bfcc0 100644 (file)
@@ -271,6 +271,11 @@ ssize_t pvfs_stream_write(struct pvfs_state *pvfs,
        if (count == 0) {
                return 0;
        }
+       if (offset > XATTR_MAX_STREAM_SIZE) {
+               errno = ENOSPC;
+               return -1;
+       }
+
        /* we have to load the existing stream, then modify, then save */
        status = pvfs_xattr_load(pvfs, h, h->name->full_name, h->fd, XATTR_DOSSTREAM_PREFIX,
                                 h->name->stream_name, offset+count, &blob);
@@ -320,6 +325,11 @@ NTSTATUS pvfs_stream_truncate(struct pvfs_state *pvfs,
 {
        NTSTATUS status;
        DATA_BLOB blob;
+
+       if (length > XATTR_MAX_STREAM_SIZE) {
+               return NT_STATUS_DISK_FULL;
+       }
+
        /* we have to load the existing stream, then modify, then save */
        status = pvfs_xattr_load(pvfs, name, name->full_name, fd, XATTR_DOSSTREAM_PREFIX,
                                 name->stream_name, length, &blob);
index 0ea92c80a02425992a4156360f005a694f872bcb..b623578514c17f7346638dcbbada6d102b7d6f8f 100644 (file)
@@ -51,19 +51,141 @@ static void nttrans_setup_reply(struct smbsrv_request *req,
 /* parse NTTRANS_CREATE request
  */
 static NTSTATUS nttrans_create(struct smbsrv_request *req, 
-               struct smb_nttrans *trans)
+                              struct smb_nttrans *trans)
 {
-       return NT_STATUS_FOOBAR;
+       union smb_open *io;
+       uint16_t fname_len;
+       uint32_t sd_length, ea_length;
+       NTSTATUS status;
+       uint8_t *params;
+
+       if (trans->in.params.length < 54) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* parse the request */
+       io = talloc_p(req, union smb_open);
+       if (io == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       io->ntcreatex.level = RAW_OPEN_NTTRANS_CREATE;
+
+       params = trans->in.params.data;
+
+       io->ntcreatex.in.flags            = IVAL(params,  0);
+       io->ntcreatex.in.root_fid         = IVAL(params,  4);
+       io->ntcreatex.in.access_mask      = IVAL(params,  8);
+       io->ntcreatex.in.alloc_size       = BVAL(params, 12);
+       io->ntcreatex.in.file_attr        = IVAL(params, 20);
+       io->ntcreatex.in.share_access     = IVAL(params, 24);
+       io->ntcreatex.in.open_disposition = IVAL(params, 28);
+       io->ntcreatex.in.create_options   = IVAL(params, 32);
+       sd_length                         = IVAL(params, 36);
+       ea_length                         = IVAL(params, 40);
+       fname_len                         = IVAL(params, 44);
+       io->ntcreatex.in.impersonation    = IVAL(params, 48);
+       io->ntcreatex.in.security_flags   = CVAL(params, 52);
+       io->ntcreatex.in.sec_desc         = NULL;
+       io->ntcreatex.in.ea_list          = NULL;
+
+       req_pull_string(req, &io->ntcreatex.in.fname, 
+                       params + 54, 
+                       trans->in.params.length - 54,
+                       STR_NO_RANGE_CHECK | STR_TERMINATE);
+       if (!io->ntcreatex.in.fname) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (sd_length > trans->in.data.length ||
+           ea_length > trans->in.data.length ||
+           (sd_length+ea_length) > trans->in.data.length) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* this call has an optional security descriptor */
+       if (sd_length != 0) {
+               DATA_BLOB blob;
+               blob.data = trans->in.data.data;
+               blob.length = sd_length;
+               io->ntcreatex.in.sec_desc = talloc_p(io, struct security_descriptor);
+               if (io->ntcreatex.in.sec_desc == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               status = ndr_pull_struct_blob(&blob, io, 
+                                             io->ntcreatex.in.sec_desc, 
+                                             (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+       }
+
+       /* and an optional ea_list */
+       if (ea_length > 4) {
+               DATA_BLOB blob;
+               blob.data = trans->in.data.data + sd_length;
+               blob.length = ea_length;
+               io->ntcreatex.in.ea_list = talloc_p(io, struct smb_ea_list);
+               if (io->ntcreatex.in.ea_list == NULL) {
+                       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);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+       }
+
+       /* call the backend - notice that we do it sync for now, until we support
+          async nttrans requests */    
+       status = ntvfs_openfile(req, io);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       trans->out.setup_count = 0;
+       trans->out.setup       = NULL;
+       trans->out.params      = data_blob_talloc(req, NULL, 69);
+       trans->out.data        = data_blob(NULL, 0);
+
+       params = trans->out.params.data;
+       if (params == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       SSVAL(params,        0, io->ntcreatex.out.oplock_level);
+       SSVAL(params,        2, io->ntcreatex.out.fnum);
+       SIVAL(params,        4, io->ntcreatex.out.create_action);
+       SIVAL(params,        8, 0); /* ea error offset */
+       push_nttime(params, 12, io->ntcreatex.out.create_time);
+       push_nttime(params, 20, io->ntcreatex.out.access_time);
+       push_nttime(params, 28, io->ntcreatex.out.write_time);
+       push_nttime(params, 36, io->ntcreatex.out.change_time);
+       SIVAL(params,       44, io->ntcreatex.out.attrib);
+       SBVAL(params,       48, io->ntcreatex.out.alloc_size);
+       SBVAL(params,       56, io->ntcreatex.out.size);
+       SSVAL(params,       64, io->ntcreatex.out.file_type);
+       SSVAL(params,       66, io->ntcreatex.out.ipc_state);
+       SCVAL(params,       68, io->ntcreatex.out.is_directory);
+
+       return NT_STATUS_OK;
 }
 
 /* parse NTTRANS_RENAME request
  */
 static NTSTATUS nttrans_rename(struct smbsrv_request *req, 
-               struct smb_nttrans *trans)
+                              struct smb_nttrans *trans)
 {
        return NT_STATUS_FOOBAR;
 }
-/* parse NTTRANS_IOCTL request
+
+/* 
+   parse NTTRANS_IOCTL request
  */
 static NTSTATUS nttrans_ioctl(struct smbsrv_request *req, 
                struct smb_nttrans *trans)
@@ -105,13 +227,6 @@ static NTSTATUS nttrans_ioctl(struct smbsrv_request *req,
 static NTSTATUS nttrans_backend(struct smbsrv_request *req, 
                struct smb_nttrans *trans)
 {
-       DEBUG(9,("nttrans_backend: setup_count=%d function=%d\n",
-               trans->in.setup_count, trans->in.function));
-       /* must have at least one setup word */
-       if (trans->in.setup_count < 1) {
-               return NT_STATUS_FOOBAR;
-       }
-       
        /* the nttrans command is in function */
        switch (trans->in.function) {
        case NT_TRANSACT_CREATE:
index 7b33f4334b48d0049f35ebd45da7583c6e72d7fe..31616b9435a53e19b0948c31ca1505b2305f6c1f 100644 (file)
@@ -2294,6 +2294,8 @@ void reply_ntcreate_and_X(struct smbsrv_request *req)
        io->ntcreatex.in.create_options =   IVAL(req->in.vwv, 39);
        io->ntcreatex.in.impersonation =    IVAL(req->in.vwv, 43);
        io->ntcreatex.in.security_flags =   CVAL(req->in.vwv, 47);
+       io->ntcreatex.in.ea_list          = NULL;
+       io->ntcreatex.in.sec_desc         = NULL;
 
        /* we need a neater way to handle this alignment */
        if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&