Finish removal of iconv_convenience in public API's.
[samba.git] / source4 / smb_server / smb2 / fileinfo.c
index f5cc6d73ee36b071c5d27143e58ec216c855bdf3..5e4f35e02b71d57169c84c7add4d1b5c16ff9b65 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,
    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"
 #include "libcli/smb2/smb2.h"
 #include "libcli/smb2/smb2_calls.h"
 #include "smb_server/smb_server.h"
-#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"
@@ -54,10 +52,14 @@ static void smb2srv_getinfo_send(struct ntvfs_request *ntvfs)
                SMB2SRV_CHECK(op->send_fn(op));
        }
 
-       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, True, op->info->out.blob.length));
+       if (op->info->in.output_buffer_length < op->info->out.blob.length) {
+               smb2srv_send_error(req,  NT_STATUS_INFO_LENGTH_MISMATCH);
+               return;
+       }
+
+       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));
+       SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, op->info->out.blob));
        SSVAL(req->out.body,    0x06,   0);
 
        smb2srv_send_reply(req);
@@ -80,19 +82,21 @@ static NTSTATUS smb2srv_getinfo_file_send(struct smb2srv_getinfo_op *op)
 static NTSTATUS smb2srv_getinfo_file(struct smb2srv_getinfo_op *op, uint8_t smb2_level)
 {
        union smb_fileinfo *io;
+       uint16_t level;
 
        io = talloc(op, union smb_fileinfo);
        NT_STATUS_HAVE_NO_MEMORY(io);
 
-       switch (op->info->in.level) {
+       level = op->info->in.info_type | (op->info->in.info_class << 8);
+       switch (level) {
        case RAW_FILEINFO_SMB2_ALL_EAS:
-               io->all_eas.level               = op->info->in.level;
+               io->all_eas.level               = level;
                io->all_eas.in.file.ntvfs       = op->info->in.file.ntvfs;
-               io->all_eas.in.continue_flags   = op->info->in.flags2;
+               io->all_eas.in.continue_flags   = op->info->in.getinfo_flags;
                break;
 
        case RAW_FILEINFO_SMB2_ALL_INFORMATION:
-               io->all_info2.level             = op->info->in.level;
+               io->all_info2.level             = level;
                io->all_info2.in.file.ntvfs     = op->info->in.file.ntvfs;
                break;
 
@@ -144,12 +148,14 @@ static NTSTATUS smb2srv_getinfo_fs(struct smb2srv_getinfo_op *op, uint8_t smb2_l
 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;
+       enum ndr_err_code ndr_err;
 
-       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);
+       ndr_err = ndr_push_struct_blob(&op->info->out.blob, op->req, 
+                                      io->query_secdesc.out.sd,
+                                      (ndr_push_flags_fn_t)ndr_push_security_descriptor);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return ndr_map_error2ntstatus(ndr_err);
+       }
 
        return NT_STATUS_OK;
 }
@@ -165,7 +171,7 @@ static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, uint8_t
 
                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;
+               io->query_secdesc.in.secinfo_flags      = op->info->in.additional_information;
 
                op->io_ptr      = io;
                op->send_fn     = smb2srv_getinfo_security_send;
@@ -178,23 +184,17 @@ static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, uint8_t
 
 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) {
+       switch (op->info->in.info_type) {
        case SMB2_GETINFO_FILE:
-               return smb2srv_getinfo_file(op, smb2_level);
+               return smb2srv_getinfo_file(op, op->info->in.info_class);
 
        case SMB2_GETINFO_FS:
-               return smb2srv_getinfo_fs(op, smb2_level);
+               return smb2srv_getinfo_fs(op, op->info->in.info_class);
 
        case SMB2_GETINFO_SECURITY:
-               return smb2srv_getinfo_security(op, smb2_level);
+               return smb2srv_getinfo_security(op, op->info->in.info_class);
 
-       case 0x04:
+       case SMB2_GETINFO_QUOTA:
                return NT_STATUS_NOT_SUPPORTED;
        }
 
@@ -206,7 +206,7 @@ void smb2srv_getinfo_recv(struct smb2srv_request *req)
        struct smb2_getinfo *info;
        struct smb2srv_getinfo_op *op;
 
-       SMB2SRV_CHECK_BODY_SIZE(req, 0x28, 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);
@@ -216,13 +216,15 @@ void smb2srv_getinfo_recv(struct smb2srv_request *req)
        op->send_fn     = NULL;
        SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_getinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
 
-       info->in.level                  = SVAL(req->in.body, 0x02);
-       info->in.max_response_size      = IVAL(req->in.body, 0x04);
-       info->in.unknown1               = IVAL(req->in.body, 0x08);
-       info->in.unknown2               = IVAL(req->in.body, 0x0C);
-       info->in.flags                  = IVAL(req->in.body, 0x10);
-       info->in.flags2                 = IVAL(req->in.body, 0x14);
+       info->in.info_type              = CVAL(req->in.body, 0x02);
+       info->in.info_class             = CVAL(req->in.body, 0x03);
+       info->in.output_buffer_length   = IVAL(req->in.body, 0x04);
+       info->in.reserved               = IVAL(req->in.body, 0x0C);
+       info->in.additional_information = IVAL(req->in.body, 0x10);
+       info->in.getinfo_flags          = IVAL(req->in.body, 0x14);
        info->in.file.ntvfs             = smb2srv_pull_handle(req, req->in.body, 0x18);
+       SMB2SRV_CHECK(smb2_pull_o16As32_blob(&req->in, op, 
+                                           req->in.body+0x08, &info->in.blob));
 
        SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
        SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_getinfo_backend(op));
@@ -248,7 +250,7 @@ static void smb2srv_setinfo_send(struct ntvfs_request *ntvfs)
 
        SMB2SRV_CHECK_ASYNC_STATUS(op, struct smb2srv_setinfo_op);
 
-       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x02, False, 0));
+       SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x02, false, 0));
 
        smb2srv_send_reply(req);
 }
@@ -265,9 +267,14 @@ static NTSTATUS smb2srv_setinfo_file(struct smb2srv_setinfo_op *op, uint8_t smb2
        io->generic.level               = smb2_level + 1000;
        io->generic.in.file.ntvfs       = op->info->in.file.ntvfs;
 
+       /* handle cases that don't map directly */
+       if (io->generic.level == RAW_SFILEINFO_RENAME_INFORMATION) {
+               io->generic.level = RAW_SFILEINFO_RENAME_INFORMATION_SMB2;
+       }
+
        status = smbsrv_pull_passthru_sfileinfo(io, io->generic.level, io,
                                                &op->info->in.blob,
-                                               STR_UNICODE, NULL);
+                                               STR_UNICODE, &op->req->in.bufinfo);
        NT_STATUS_NOT_OK_RETURN(status);
 
        return ntvfs_setfileinfo(op->req->ntvfs, io);
@@ -295,7 +302,7 @@ static NTSTATUS smb2srv_setinfo_fs(struct smb2srv_setinfo_op *op, uint8_t smb2_l
 static NTSTATUS smb2srv_setinfo_security(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
 {
        union smb_setfileinfo *io;
-       NTSTATUS status;
+       enum ndr_err_code ndr_err;
 
        switch (smb2_level) {
        case 0x00:
@@ -309,10 +316,12 @@ static NTSTATUS smb2srv_setinfo_security(struct smb2srv_setinfo_op *op, uint8_t
                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);
+               ndr_err = ndr_pull_struct_blob(&op->info->in.blob, io, 
+                                              io->set_secdesc.in.sd,
+                                              (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       return ndr_map_error2ntstatus(ndr_err);
+               }
 
                return ntvfs_setfileinfo(op->req->ntvfs, io);
        }
@@ -350,7 +359,7 @@ void smb2srv_setinfo_recv(struct smb2srv_request *req)
        struct smb2_setinfo *info;
        struct smb2srv_setinfo_op *op;
 
-       SMB2SRV_CHECK_BODY_SIZE(req, 0x20, True);
+       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);
@@ -359,7 +368,7 @@ void smb2srv_setinfo_recv(struct smb2srv_request *req)
        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));
+       SMB2SRV_CHECK(smb2_pull_s32o16_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);