Author: metze
Date: 2006-06-22 17:35:04 +0000 (Thu, 22 Jun 2006)
New Revision: 16467

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=16467

Log:
implement SMB2 GetInfo server code

metze
Modified:
   branches/SAMBA_4_0/source/smb_server/smb2/fileinfo.c


Changeset:
Modified: branches/SAMBA_4_0/source/smb_server/smb2/fileinfo.c
===================================================================
--- branches/SAMBA_4_0/source/smb_server/smb2/fileinfo.c        2006-06-22 
17:33:56 UTC (rev 16466)
+++ branches/SAMBA_4_0/source/smb_server/smb2/fileinfo.c        2006-06-22 
17:35:04 UTC (rev 16467)
@@ -25,33 +25,192 @@
 #include "smb_server/service_smb_proto.h"
 #include "smb_server/smb2/smb2_server.h"
 #include "ntvfs/ntvfs.h"
+#include "librpc/gen_ndr/ndr_security.h"
 
+struct smb2srv_getinfo_op {
+       struct smb2srv_request *req;
+       struct smb2_getinfo *info;
+       void *io_ptr;
+       NTSTATUS (*send_fn)(struct smb2srv_getinfo_op *op);
+};
+
 static void smb2srv_getinfo_send(struct ntvfs_request *ntvfs)
 {
+       struct smb2srv_getinfo_op *op;
        struct smb2srv_request *req;
-       struct smb2_getinfo *info;
 
-       SMB2SRV_CHECK_ASYNC_STATUS(info, struct smb2_getinfo);
+       /*
+        * SMB2 uses NT_STATUS_INVALID_INFO_CLASS
+        * so we need to translated it here
+        */
+       if (NT_STATUS_EQUAL(NT_STATUS_INVALID_LEVEL, 
ntvfs->async_states->status)) {
+               ntvfs->async_states->status = NT_STATUS_INVALID_INFO_CLASS;
+       }
+
+       SMB2SRV_CHECK_ASYNC_STATUS(op, struct smb2srv_getinfo_op);
+
+       ZERO_STRUCT(op->info->out);
+       if (op->send_fn) {
+               SMB2SRV_CHECK(op->send_fn(op));
+       }
+
        SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, True, 0));
 
        /* TODO: this is maybe a o16s32_blob */
-       SMB2SRV_CHECK(smb2_push_o16s16_blob(&req->out, 0x02, info->out.blob));
+       SMB2SRV_CHECK(smb2_push_o16s16_blob(&req->out, 0x02, 
op->info->out.blob));
        SSVAL(req->out.body,    0x06,   0);
 
        smb2srv_send_reply(req);
 }
 
-static NTSTATUS smb2srv_getinfo_backend(struct ntvfs_request *ntvfs, struct 
smb2_getinfo *info)
+static NTSTATUS smb2srv_getinfo_file_send(struct smb2srv_getinfo_op *op)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       union smb_fileinfo *io = talloc_get_type(op->io_ptr, union 
smb_fileinfo);
+       NTSTATUS status;
+
+       status = smbsrv_push_passthru_fileinfo(op->req,
+                                              &op->info->out.blob,
+                                              io->generic.level, io,
+                                              STR_UNICODE);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       return NT_STATUS_OK;
 }
 
+static NTSTATUS smb2srv_getinfo_file(struct smb2srv_getinfo_op *op, uint8_t 
smb2_level)
+{
+       union smb_fileinfo *io;
+
+       io = talloc(op, union smb_fileinfo);
+       NT_STATUS_HAVE_NO_MEMORY(io);
+
+       switch (op->info->in.level) {
+       case RAW_FILEINFO_SMB2_ALL_EAS:
+               io->all_eas.level               = op->info->in.level;
+               io->all_eas.in.file.ntvfs       = op->info->in.file.ntvfs;
+               io->all_eas.in.continue_flags   = op->info->in.flags2;
+               break;
+
+       case RAW_FILEINFO_SMB2_ALL_INFORMATION:
+               io->all_info2.level             = op->info->in.level;
+               io->all_info2.in.file.ntvfs     = op->info->in.file.ntvfs;
+               break;
+
+       default:
+               /* the rest directly maps to the passthru levels */
+               io->generic.level               = smb2_level + 1000;
+               io->generic.in.file.ntvfs       = op->info->in.file.ntvfs;
+               break;
+       }
+
+       op->io_ptr      = io;
+       op->send_fn     = smb2srv_getinfo_file_send;
+
+       return ntvfs_qfileinfo(op->req->ntvfs, io);
+}
+
+static NTSTATUS smb2srv_getinfo_fs_send(struct smb2srv_getinfo_op *op)
+{
+       union smb_fsinfo *io = talloc_get_type(op->io_ptr, union smb_fsinfo);
+       NTSTATUS status;
+
+       status = smbsrv_push_passthru_fsinfo(op->req,
+                                            &op->info->out.blob,
+                                            io->generic.level, io,
+                                            STR_UNICODE);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS smb2srv_getinfo_fs(struct smb2srv_getinfo_op *op, uint8_t 
smb2_level)
+{
+       union smb_fsinfo *io;
+
+       io = talloc(op, union smb_fsinfo);
+       NT_STATUS_HAVE_NO_MEMORY(io);
+
+       /* the rest directly maps to the passthru levels */
+       io->generic.level       = smb2_level + 1000;
+
+       /* TODO: allow qfsinfo only the share root directory handle */
+
+       op->io_ptr      = io;
+       op->send_fn     = smb2srv_getinfo_fs_send;
+
+       return ntvfs_fsinfo(op->req->ntvfs, io);
+}
+
+static NTSTATUS smb2srv_getinfo_security_send(struct smb2srv_getinfo_op *op)
+{
+       union smb_fileinfo *io = talloc_get_type(op->io_ptr, union 
smb_fileinfo);
+       NTSTATUS status;
+
+       status = ndr_push_struct_blob(&op->info->out.blob, op->req,
+                                     io->query_secdesc.out.sd,
+                                     
(ndr_push_flags_fn_t)ndr_push_security_descriptor);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, 
uint8_t smb2_level)
+{
+       union smb_fileinfo *io;
+
+       switch (smb2_level) {
+       case 0x00:
+               io = talloc(op, union smb_fileinfo);
+               NT_STATUS_HAVE_NO_MEMORY(io);
+
+               io->query_secdesc.level                 = RAW_FILEINFO_SEC_DESC;
+               io->query_secdesc.in.file.ntvfs         = 
op->info->in.file.ntvfs;
+               io->query_secdesc.in.secinfo_flags      = op->info->in.flags;
+
+               op->io_ptr      = io;
+               op->send_fn     = smb2srv_getinfo_security_send;
+
+               return ntvfs_qfileinfo(op->req->ntvfs, io);
+       }
+
+       return NT_STATUS_INVALID_INFO_CLASS;
+}
+
+static NTSTATUS smb2srv_getinfo_backend(struct smb2srv_getinfo_op *op)
+{
+       uint8_t smb2_class;
+       uint8_t smb2_level;
+
+       smb2_class = 0xFF & op->info->in.level;
+       smb2_level = 0xFF & (op->info->in.level>>8);
+
+       switch (smb2_class) {
+       case SMB2_GETINFO_FILE:
+               return smb2srv_getinfo_file(op, smb2_level);
+
+       case SMB2_GETINFO_FS:
+               return smb2srv_getinfo_fs(op, smb2_level);
+
+       case SMB2_GETINFO_SECURITY:
+               return smb2srv_getinfo_security(op, smb2_level);
+       }
+
+       return NT_STATUS_FOOBAR;
+}
+
 void smb2srv_getinfo_recv(struct smb2srv_request *req)
 {
        struct smb2_getinfo *info;
+       struct smb2srv_getinfo_op *op;
 
-       SMB2SRV_CHECK_BODY_SIZE(req, 0x30, True);
+       SMB2SRV_CHECK_BODY_SIZE(req, 0x28, True);
        SMB2SRV_TALLOC_IO_PTR(info, struct smb2_getinfo);
+       /* this overwrites req->io_ptr !*/
+       SMB2SRV_TALLOC_IO_PTR(op, struct smb2srv_getinfo_op);
+       op->req         = req;
+       op->info        = info;
+       op->io_ptr      = NULL;
+       op->send_fn     = NULL;
        SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_getinfo_send, 
NTVFS_ASYNC_STATE_MAY_ASYNC);
 
        info->in.level                  = SVAL(req->in.body, 0x02);
@@ -63,7 +222,7 @@
        info->in.file.ntvfs             = smb2srv_pull_handle(req, 
req->in.body, 0x18);
 
        SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
-       SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_getinfo_backend(req->ntvfs, info));
+       SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_getinfo_backend(op));
 }
 
 void smb2srv_setinfo_recv(struct smb2srv_request *req)

Reply via email to