r23792: convert Samba4 to GPLv3
[kai/samba-autobuild/.git] / source4 / smb_server / smb2 / fileinfo.c
index 2bb0f838ead9c69fdb3201977617d27baaefc44e..4f4b7907020097362726a810b8640a5a4741b35c 100644 (file)
@@ -5,7 +5,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -54,7 +53,7 @@ static void smb2srv_getinfo_send(struct ntvfs_request *ntvfs)
                SMB2SRV_CHECK(op->send_fn(op));
        }
 
-       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, True, 0));
+       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, True, op->info->out.blob.length));
 
        /* TODO: this is maybe a o16s32_blob */
        SMB2SRV_CHECK(smb2_push_o16s16_blob(&req->out, 0x02, op->info->out.blob));
@@ -173,7 +172,7 @@ static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, uint8_t
                return ntvfs_qfileinfo(op->req->ntvfs, io);
        }
 
-       return NT_STATUS_INVALID_INFO_CLASS;
+       return NT_STATUS_INVALID_PARAMETER;
 }
 
 static NTSTATUS smb2srv_getinfo_backend(struct smb2srv_getinfo_op *op)
@@ -193,9 +192,12 @@ static NTSTATUS smb2srv_getinfo_backend(struct smb2srv_getinfo_op *op)
 
        case SMB2_GETINFO_SECURITY:
                return smb2srv_getinfo_security(op, smb2_level);
+
+       case 0x04:
+               return NT_STATUS_NOT_SUPPORTED;
        }
 
-       return NT_STATUS_FOOBAR;
+       return NT_STATUS_INVALID_PARAMETER;
 }
 
 void smb2srv_getinfo_recv(struct smb2srv_request *req)
@@ -225,7 +227,141 @@ void smb2srv_getinfo_recv(struct smb2srv_request *req)
        SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_getinfo_backend(op));
 }
 
+struct smb2srv_setinfo_op {
+       struct smb2srv_request *req;
+       struct smb2_setinfo *info;
+};
+
+static void smb2srv_setinfo_send(struct ntvfs_request *ntvfs)
+{
+       struct smb2srv_setinfo_op *op;
+       struct smb2srv_request *req;
+
+       /*
+        * 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_setinfo_op);
+
+       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x02, False, 0));
+
+       smb2srv_send_reply(req);
+}
+
+static NTSTATUS smb2srv_setinfo_file(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
+{
+       union smb_setfileinfo *io;
+       NTSTATUS status;
+
+       io = talloc(op, union smb_setfileinfo);
+       NT_STATUS_HAVE_NO_MEMORY(io);
+
+       /* the levels directly map to the passthru levels */
+       io->generic.level               = smb2_level + 1000;
+       io->generic.in.file.ntvfs       = op->info->in.file.ntvfs;
+
+       status = smbsrv_pull_passthru_sfileinfo(io, io->generic.level, io,
+                                               &op->info->in.blob,
+                                               STR_UNICODE, NULL);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       return ntvfs_setfileinfo(op->req->ntvfs, io);
+}
+
+static NTSTATUS smb2srv_setinfo_fs(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
+{
+       switch (smb2_level) {
+       case 0x02:
+               return NT_STATUS_NOT_IMPLEMENTED;
+
+       case 0x06:
+               return NT_STATUS_ACCESS_DENIED;
+
+       case 0x08:
+               return NT_STATUS_ACCESS_DENIED;
+
+       case 0x0A:
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_INVALID_INFO_CLASS;
+}
+
+static NTSTATUS smb2srv_setinfo_security(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
+{
+       union smb_setfileinfo *io;
+       NTSTATUS status;
+
+       switch (smb2_level) {
+       case 0x00:
+               io = talloc(op, union smb_setfileinfo);
+               NT_STATUS_HAVE_NO_MEMORY(io);
+
+               io->set_secdesc.level            = RAW_SFILEINFO_SEC_DESC;
+               io->set_secdesc.in.file.ntvfs    = op->info->in.file.ntvfs;
+               io->set_secdesc.in.secinfo_flags = op->info->in.flags;
+
+               io->set_secdesc.in.sd = talloc(io, struct security_descriptor);
+               NT_STATUS_HAVE_NO_MEMORY(io->set_secdesc.in.sd);
+
+               status = ndr_pull_struct_blob(&op->info->in.blob, io, 
+                                             io->set_secdesc.in.sd, 
+                                             (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+               NT_STATUS_NOT_OK_RETURN(status);
+
+               return ntvfs_setfileinfo(op->req->ntvfs, io);
+       }
+
+       return NT_STATUS_INVALID_INFO_CLASS;
+}
+
+static NTSTATUS smb2srv_setinfo_backend(struct smb2srv_setinfo_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_setinfo_file(op, smb2_level);
+
+       case SMB2_GETINFO_FS:
+               return smb2srv_setinfo_fs(op, smb2_level);
+
+       case SMB2_GETINFO_SECURITY:
+               return smb2srv_setinfo_security(op, smb2_level);
+
+       case 0x04:
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+
+       return NT_STATUS_INVALID_PARAMETER;
+}
+
 void smb2srv_setinfo_recv(struct smb2srv_request *req)
 {
-       smb2srv_send_error(req, NT_STATUS_NOT_IMPLEMENTED);
+       struct smb2_setinfo *info;
+       struct smb2srv_setinfo_op *op;
+
+       SMB2SRV_CHECK_BODY_SIZE(req, 0x20, True);
+       SMB2SRV_TALLOC_IO_PTR(info, struct smb2_setinfo);
+       /* this overwrites req->io_ptr !*/
+       SMB2SRV_TALLOC_IO_PTR(op, struct smb2srv_setinfo_op);
+       op->req         = req;
+       op->info        = info;
+       SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_setinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
+
+       info->in.level                  = SVAL(req->in.body, 0x02);
+       SMB2SRV_CHECK(smb2_pull_s32o32_blob(&req->in, info, req->in.body+0x04, &info->in.blob));
+       info->in.flags                  = IVAL(req->in.body, 0x0C);
+       info->in.file.ntvfs             = smb2srv_pull_handle(req, req->in.body, 0x10);
+
+       SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
+       SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_setinfo_backend(op));
 }