]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
implement the documented SMB2 create blobs in the server
authorAndrew Tridgell <tridge@samba.org>
Wed, 28 May 2008 06:28:37 +0000 (16:28 +1000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 28 May 2008 06:28:37 +0000 (16:28 +1000)
Not all of them are honoured yet, but they are all parsed and the ones
that have SMB equivalents are honoured

source/ntvfs/ipc/vfs_ipc.c
source/ntvfs/ntvfs_generic.c
source/ntvfs/posix/pvfs_open.c
source/smb_server/smb2/fileio.c

index ea7b54ae6ac29a4228119df81d3db141b057bb7f..8ac7ac7d03486bc2194c283b3a3e89cbe797eff0 100644 (file)
@@ -321,6 +321,7 @@ static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
        status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
        NT_STATUS_NOT_OK_RETURN(status);
 
+       ZERO_STRUCT(oi->smb2.out);
        oi->smb2.out.file.ntvfs         = p->handle;
        oi->smb2.out.oplock_level       = oi->smb2.in.oplock_level;
        oi->smb2.out.create_action      = NTCREATEX_ACTION_EXISTED;
@@ -332,7 +333,6 @@ static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
        oi->smb2.out.size               = 0;
        oi->smb2.out.file_attr          = FILE_ATTRIBUTE_NORMAL;
        oi->smb2.out.reserved2          = 0;
-       oi->smb2.out.blob               = data_blob(NULL, 0);
 
        return status;
 }
index 06d89a717bead710e83c62398a815f81b0839df8..9227295696bd3c3e1cef70636244178b551838cd 100644 (file)
@@ -207,6 +207,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
                break;
 
        case RAW_OPEN_SMB2:
+               ZERO_STRUCT(io->smb2.out);
                io->smb2.out.file.ntvfs         = io2->generic.out.file.ntvfs;
                switch (io2->generic.out.oplock_level) {
                case BATCH_OPLOCK_RETURN:
@@ -232,7 +233,6 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
                io->smb2.out.size               = io2->generic.out.size;
                io->smb2.out.file_attr          = io2->generic.out.attrib;
                io->smb2.out.reserved2          = 0;
-               io->smb2.out.blob               = data_blob(NULL, 0);
                break;
 
        default:
@@ -512,7 +512,7 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
                }
                io2->generic.in.root_fid        = 0;
                io2->generic.in.access_mask     = io->smb2.in.desired_access;
-               io2->generic.in.alloc_size      = 0;
+               io2->generic.in.alloc_size      = io->smb2.in.alloc_size;
                io2->generic.in.file_attr       = io->smb2.in.file_attributes;
                io2->generic.in.share_access    = io->smb2.in.share_access;
                io2->generic.in.open_disposition= io->smb2.in.create_disposition;
@@ -520,8 +520,14 @@ NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
                io2->generic.in.impersonation   = io->smb2.in.impersonation_level;
                io2->generic.in.security_flags  = 0;
                io2->generic.in.fname           = io->smb2.in.fname;
-               io2->generic.in.sec_desc        = NULL;
-               io2->generic.in.ea_list         = NULL;
+               io2->generic.in.sec_desc        = io->smb2.in.sec_desc;
+               io2->generic.in.ea_list         = &io->smb2.in.eas;
+
+               /* we don't support timewarp yet */
+               if (io->smb2.in.timewarp != 0) {
+                       status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+                       break;
+               }
 
                /* we need to check these bits before we check the private mask */
                if (io2->generic.in.create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) {
index 49710806c7e4a058f44223e68228405b1dcf2d22..0f08136a79b190e06e4a4766fe4777272e0eccb2 100644 (file)
@@ -634,6 +634,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
                return status;
        }
 
+       /* support initial alloc sizes */
+       name->dos.alloc_size = io->ntcreatex.in.alloc_size;
        name->dos.attrib = attrib;
        status = pvfs_dosattrib_save(pvfs, name, fd);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1464,6 +1466,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                        talloc_free(lck);
                        return pvfs_map_errno(pvfs, errno);
                }
+               name->dos.alloc_size = io->ntcreatex.in.alloc_size;
                name->dos.attrib = attrib;
                status = pvfs_dosattrib_save(pvfs, name, fd);
                if (!NT_STATUS_IS_OK(status)) {
index 5ab217bbfd687b036aa5c994f26099c605c391ac..086ddc690eb1947165b2eba8dcb12232cebdd20a 100644 (file)
 #include "smb_server/smb2/smb2_server.h"
 #include "ntvfs/ntvfs.h"
 #include "param/param.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "librpc/gen_ndr/ndr_security.h"
 
 static void smb2srv_create_send(struct ntvfs_request *ntvfs)
 {
        struct smb2srv_request *req;
        union smb_open *io;
+       DATA_BLOB blob;
 
        SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open);
-       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, io->smb2.out.blob.length));
+       SMB2SRV_CHECK(smb2_create_blob_push(req, &blob, io->smb2.out.blobs));
+       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, blob.length));
 
        SCVAL(req->out.body,    0x02,   io->smb2.out.oplock_level);
        SCVAL(req->out.body,    0x03,   io->smb2.out.reserved);
@@ -46,7 +51,7 @@ static void smb2srv_create_send(struct ntvfs_request *ntvfs)
        SIVAL(req->out.body,    0x38,   io->smb2.out.file_attr);
        SIVAL(req->out.body,    0x3C,   io->smb2.out.reserved2);
        smb2srv_push_handle(req->out.body, 0x40, io->smb2.out.file.ntvfs);
-       SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x50, io->smb2.out.blob));
+       SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x50, blob));
 
        /* also setup the chained file handle */
        req->chained_file_handle = req->_chained_file_handle;
@@ -59,11 +64,13 @@ void smb2srv_create_recv(struct smb2srv_request *req)
 {
        union smb_open *io;
        DATA_BLOB blob;
+       int i;
 
        SMB2SRV_CHECK_BODY_SIZE(req, 0x38, true);
        SMB2SRV_TALLOC_IO_PTR(io, union smb_open);
        SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_create_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
 
+       ZERO_STRUCT(io->smb2.in);
        io->smb2.level                  = RAW_OPEN_SMB2;
        io->smb2.in.security_flags      = CVAL(req->in.body, 0x02);
        io->smb2.in.oplock_level        = CVAL(req->in.body, 0x03);
@@ -77,10 +84,67 @@ void smb2srv_create_recv(struct smb2srv_request *req)
        io->smb2.in.create_options      = IVAL(req->in.body, 0x28);
        SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, io, req->in.body+0x2C, &io->smb2.in.fname));
        SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x30, &blob));
-       /* TODO: parse the blob */
-       ZERO_STRUCT(io->smb2.in.eas);
-       ZERO_STRUCT(io->smb2.in.blobs);
-
+       SMB2SRV_CHECK(smb2_create_blob_parse(io, blob, &io->smb2.in.blobs));
+
+       /* interpret the parsed tags that a server needs to respond to */
+       for (i=0;i<io->smb2.in.blobs.num_blobs;i++) {
+               if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_EXTA) == 0) {
+                       SMB2SRV_CHECK(ea_pull_list_chained(&io->smb2.in.blobs.blobs[i].data, io, 
+                                                          &io->smb2.in.eas.num_eas,
+                                                          &io->smb2.in.eas.eas));
+               }
+               if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_SECD) == 0) {
+                       enum ndr_err_code ndr_err;
+                       io->smb2.in.sec_desc = talloc(io, struct security_descriptor);
+                       if (io->smb2.in.sec_desc == NULL) {
+                               smb2srv_send_error(req,  NT_STATUS_NO_MEMORY);
+                               return;
+                       }
+                       ndr_err = ndr_pull_struct_blob(&io->smb2.in.blobs.blobs[i].data, io, NULL,
+                                                      io->smb2.in.sec_desc,
+                                                      (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               smb2srv_send_error(req,  ndr_map_error2ntstatus(ndr_err));
+                               return;
+                       }
+               }
+               if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNQ) == 0) {
+                       io->smb2.in.durable_open = true;
+               }
+               if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNC) == 0) {
+                       if (io->smb2.in.blobs.blobs[i].data.length != 16) {
+                               smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
+                               return;                         
+                       }
+                       io->smb2.in.durable_handle = talloc(io, struct smb2_handle);
+                       if (io->smb2.in.durable_handle == NULL) {
+                               smb2srv_send_error(req,  NT_STATUS_NO_MEMORY);
+                               return;
+                       }
+                       smb2_pull_handle(io->smb2.in.blobs.blobs[i].data.data, io->smb2.in.durable_handle);
+               }
+               if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_ALSI) == 0) {
+                       if (io->smb2.in.blobs.blobs[i].data.length != 8) {
+                               smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
+                               return;                         
+                       }
+                       io->smb2.in.alloc_size = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);
+               }
+               if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
+                       io->smb2.in.query_maximal_access = true;
+               }
+               if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_TWRP) == 0) {
+                       if (io->smb2.in.blobs.blobs[i].data.length != 8) {
+                               smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
+                               return;                         
+                       }
+                       io->smb2.in.timewarp = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);                   
+               }
+               if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
+                       io->smb2.in.query_on_disk_id = true;
+               }
+       }
+               
        /* the VFS backend does not yet handle NULL filenames */
        if (io->smb2.in.fname == NULL) {
                io->smb2.in.fname = "";