LCOV - code coverage report
Current view: top level - source4/smb_server/smb2 - fileinfo.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 151 195 77.4 %
Date: 2024-05-31 13:13:24 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB2 implementation.
       3             :    
       4             :    Copyright (C) Stefan Metzmacher      2006
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "libcli/smb2/smb2.h"
      22             : #include "libcli/smb2/smb2_calls.h"
      23             : #include "smb_server/smb_server.h"
      24             : #include "smb_server/smb2/smb2_server.h"
      25             : #include "ntvfs/ntvfs.h"
      26             : #include "librpc/gen_ndr/ndr_security.h"
      27             : 
      28             : struct smb2srv_getinfo_op {
      29             :         struct smb2srv_request *req;
      30             :         struct smb2_getinfo *info;
      31             :         void *io_ptr;
      32             :         NTSTATUS (*send_fn)(struct smb2srv_getinfo_op *op);
      33             : };
      34             : 
      35         980 : static void smb2srv_getinfo_send(struct ntvfs_request *ntvfs)
      36             : {
      37           0 :         struct smb2srv_getinfo_op *op;
      38           0 :         struct smb2srv_request *req;
      39             : 
      40             :         /*
      41             :          * SMB2 uses NT_STATUS_INVALID_INFO_CLASS
      42             :          * so we need to translated it here
      43             :          */
      44         980 :         if (NT_STATUS_EQUAL(NT_STATUS_INVALID_LEVEL, ntvfs->async_states->status)) {
      45           0 :                 ntvfs->async_states->status = NT_STATUS_INVALID_INFO_CLASS;
      46             :         }
      47             : 
      48         980 :         SMB2SRV_CHECK_ASYNC_STATUS(op, struct smb2srv_getinfo_op);
      49             : 
      50         975 :         ZERO_STRUCT(op->info->out);
      51         975 :         if (op->send_fn) {
      52         975 :                 SMB2SRV_CHECK(op->send_fn(op));
      53             :         }
      54             : 
      55         975 :         if (op->info->in.output_buffer_length < op->info->out.blob.length) {
      56         267 :                 smb2srv_send_error(req,  NT_STATUS_INFO_LENGTH_MISMATCH);
      57         267 :                 return;
      58             :         }
      59             : 
      60         708 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, op->info->out.blob.length));
      61             : 
      62         708 :         SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, op->info->out.blob));
      63         708 :         SSVAL(req->out.body, 0x06,   0);
      64             : 
      65         708 :         smb2srv_send_reply(req);
      66             : }
      67             : 
      68         775 : static NTSTATUS smb2srv_getinfo_file_send(struct smb2srv_getinfo_op *op)
      69             : {
      70         775 :         union smb_fileinfo *io = talloc_get_type(op->io_ptr, union smb_fileinfo);
      71           0 :         NTSTATUS status;
      72             : 
      73         775 :         status = smbsrv_push_passthru_fileinfo(op->req,
      74         775 :                                                &op->info->out.blob,
      75             :                                                io->generic.level, io,
      76             :                                                STR_UNICODE);
      77         775 :         NT_STATUS_NOT_OK_RETURN(status);
      78             : 
      79         775 :         return NT_STATUS_OK;
      80             : }
      81             : 
      82         779 : static NTSTATUS smb2srv_getinfo_file(struct smb2srv_getinfo_op *op, uint8_t smb2_level)
      83             : {
      84           0 :         union smb_fileinfo *io;
      85           0 :         uint16_t level;
      86             : 
      87         779 :         io = talloc(op, union smb_fileinfo);
      88         779 :         NT_STATUS_HAVE_NO_MEMORY(io);
      89             : 
      90         779 :         level = op->info->in.info_type | (op->info->in.info_class << 8);
      91         779 :         switch (level) {
      92           6 :         case RAW_FILEINFO_SMB2_ALL_EAS:
      93           6 :                 io->all_eas.level            = level;
      94           6 :                 io->all_eas.in.file.ntvfs    = op->info->in.file.ntvfs;
      95           6 :                 io->all_eas.in.continue_flags        = op->info->in.getinfo_flags;
      96           6 :                 break;
      97             : 
      98         618 :         case RAW_FILEINFO_SMB2_ALL_INFORMATION:
      99         618 :                 io->all_info2.level          = level;
     100         618 :                 io->all_info2.in.file.ntvfs  = op->info->in.file.ntvfs;
     101         618 :                 break;
     102             : 
     103         155 :         default:
     104             :                 /* the rest directly maps to the passthru levels */
     105         155 :                 io->generic.level            = smb2_level + 1000;
     106         155 :                 io->generic.in.file.ntvfs    = op->info->in.file.ntvfs;
     107         155 :                 break;
     108             :         }
     109             : 
     110         779 :         op->io_ptr   = io;
     111         779 :         op->send_fn  = smb2srv_getinfo_file_send;
     112             : 
     113         779 :         return ntvfs_qfileinfo(op->req->ntvfs, io);
     114             : }
     115             : 
     116         132 : static NTSTATUS smb2srv_getinfo_fs_send(struct smb2srv_getinfo_op *op)
     117             : {
     118         132 :         union smb_fsinfo *io = talloc_get_type(op->io_ptr, union smb_fsinfo);
     119           0 :         NTSTATUS status;
     120             : 
     121         132 :         status = smbsrv_push_passthru_fsinfo(op->req,
     122         132 :                                              &op->info->out.blob,
     123             :                                              io->generic.level, io,
     124             :                                              STR_UNICODE);
     125         132 :         NT_STATUS_NOT_OK_RETURN(status);
     126             : 
     127         132 :         return NT_STATUS_OK;
     128             : }
     129             : 
     130         132 : static NTSTATUS smb2srv_getinfo_fs(struct smb2srv_getinfo_op *op, uint8_t smb2_level)
     131             : {
     132           0 :         union smb_fsinfo *io;
     133             : 
     134         132 :         io = talloc(op, union smb_fsinfo);
     135         132 :         NT_STATUS_HAVE_NO_MEMORY(io);
     136             : 
     137             :         /* the rest directly maps to the passthru levels */
     138         132 :         io->generic.level    = smb2_level + 1000;
     139             : 
     140             :         /* TODO: allow qfsinfo only the share root directory handle */
     141             : 
     142         132 :         op->io_ptr   = io;
     143         132 :         op->send_fn  = smb2srv_getinfo_fs_send;
     144             : 
     145         132 :         return ntvfs_fsinfo(op->req->ntvfs, io);
     146             : }
     147             : 
     148          68 : static NTSTATUS smb2srv_getinfo_security_send(struct smb2srv_getinfo_op *op)
     149             : {
     150          68 :         union smb_fileinfo *io = talloc_get_type(op->io_ptr, union smb_fileinfo);
     151           0 :         enum ndr_err_code ndr_err;
     152             : 
     153          68 :         ndr_err = ndr_push_struct_blob(&op->info->out.blob, op->req, 
     154          68 :                                        io->query_secdesc.out.sd,
     155             :                                        (ndr_push_flags_fn_t)ndr_push_security_descriptor);
     156          68 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     157           0 :                 return ndr_map_error2ntstatus(ndr_err);
     158             :         }
     159             : 
     160          68 :         return NT_STATUS_OK;
     161             : }
     162             : 
     163          68 : static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, uint8_t smb2_level)
     164             : {
     165           0 :         union smb_fileinfo *io;
     166             : 
     167          68 :         switch (smb2_level) {
     168          68 :         case 0x00:
     169          68 :                 io = talloc(op, union smb_fileinfo);
     170          68 :                 NT_STATUS_HAVE_NO_MEMORY(io);
     171             : 
     172          68 :                 io->query_secdesc.level                      = RAW_FILEINFO_SEC_DESC;
     173          68 :                 io->query_secdesc.in.file.ntvfs              = op->info->in.file.ntvfs;
     174          68 :                 io->query_secdesc.in.secinfo_flags   = op->info->in.additional_information;
     175             : 
     176          68 :                 op->io_ptr   = io;
     177          68 :                 op->send_fn  = smb2srv_getinfo_security_send;
     178             : 
     179          68 :                 return ntvfs_qfileinfo(op->req->ntvfs, io);
     180             :         }
     181             : 
     182           0 :         return NT_STATUS_INVALID_PARAMETER;
     183             : }
     184             : 
     185         980 : static NTSTATUS smb2srv_getinfo_backend(struct smb2srv_getinfo_op *op)
     186             : {
     187         980 :         switch (op->info->in.info_type) {
     188         779 :         case SMB2_0_INFO_FILE:
     189         779 :                 return smb2srv_getinfo_file(op, op->info->in.info_class);
     190             : 
     191         132 :         case SMB2_0_INFO_FILESYSTEM:
     192         132 :                 return smb2srv_getinfo_fs(op, op->info->in.info_class);
     193             : 
     194          68 :         case SMB2_0_INFO_SECURITY:
     195          68 :                 return smb2srv_getinfo_security(op, op->info->in.info_class);
     196             : 
     197           1 :         case SMB2_0_INFO_QUOTA:
     198           1 :                 return NT_STATUS_NOT_SUPPORTED;
     199             :         }
     200             : 
     201           0 :         return NT_STATUS_INVALID_PARAMETER;
     202             : }
     203             : 
     204         981 : void smb2srv_getinfo_recv(struct smb2srv_request *req)
     205             : {
     206           0 :         struct smb2_getinfo *info;
     207           0 :         struct smb2srv_getinfo_op *op;
     208             : 
     209         981 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x28, true);
     210         981 :         SMB2SRV_TALLOC_IO_PTR(info, struct smb2_getinfo);
     211             :         /* this overwrites req->io_ptr !*/
     212         981 :         SMB2SRV_TALLOC_IO_PTR(op, struct smb2srv_getinfo_op);
     213         981 :         op->req              = req;
     214         981 :         op->info     = info;
     215         981 :         op->io_ptr   = NULL;
     216         981 :         op->send_fn  = NULL;
     217         981 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_getinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     218             : 
     219         981 :         info->in.info_type           = CVAL(req->in.body, 0x02);
     220         981 :         info->in.info_class          = CVAL(req->in.body, 0x03);
     221         981 :         info->in.output_buffer_length        = IVAL(req->in.body, 0x04);
     222         981 :         info->in.reserved            = IVAL(req->in.body, 0x0C);
     223         981 :         info->in.additional_information      = IVAL(req->in.body, 0x10);
     224         981 :         info->in.getinfo_flags               = IVAL(req->in.body, 0x14);
     225         981 :         info->in.file.ntvfs          = smb2srv_pull_handle(req, req->in.body, 0x18);
     226         981 :         SMB2SRV_CHECK(smb2_pull_o16As32_blob(&req->in, op, 
     227             :                                             req->in.body+0x08, &info->in.input_buffer));
     228             : 
     229         981 :         SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
     230         980 :         SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_getinfo_backend(op));
     231             : }
     232             : 
     233             : struct smb2srv_setinfo_op {
     234             :         struct smb2srv_request *req;
     235             :         struct smb2_setinfo *info;
     236             : };
     237             : 
     238         458 : static void smb2srv_setinfo_send(struct ntvfs_request *ntvfs)
     239             : {
     240           0 :         struct smb2srv_setinfo_op *op;
     241           0 :         struct smb2srv_request *req;
     242             : 
     243             :         /*
     244             :          * SMB2 uses NT_STATUS_INVALID_INFO_CLASS
     245             :          * so we need to translated it here
     246             :          */
     247         458 :         if (NT_STATUS_EQUAL(NT_STATUS_INVALID_LEVEL, ntvfs->async_states->status)) {
     248           0 :                 ntvfs->async_states->status = NT_STATUS_INVALID_INFO_CLASS;
     249             :         }
     250             : 
     251         458 :         SMB2SRV_CHECK_ASYNC_STATUS(op, struct smb2srv_setinfo_op);
     252             : 
     253         450 :         SMB2SRV_CHECK(smb2srv_setup_reply(op->req, 0x02, false, 0));
     254             : 
     255         450 :         smb2srv_send_reply(req);
     256             : }
     257             : 
     258         360 : static NTSTATUS smb2srv_setinfo_file(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
     259             : {
     260           0 :         union smb_setfileinfo *io;
     261           0 :         NTSTATUS status;
     262             : 
     263         360 :         io = talloc(op, union smb_setfileinfo);
     264         360 :         NT_STATUS_HAVE_NO_MEMORY(io);
     265             : 
     266             :         /* the levels directly map to the passthru levels */
     267         360 :         io->generic.level            = smb2_level + 1000;
     268         360 :         io->generic.in.file.ntvfs    = op->info->in.file.ntvfs;
     269             : 
     270             :         /* handle cases that don't map directly */
     271         360 :         if (io->generic.level == RAW_SFILEINFO_RENAME_INFORMATION) {
     272           8 :                 io->generic.level = RAW_SFILEINFO_RENAME_INFORMATION_SMB2;
     273             :         }
     274             : 
     275         360 :         status = smbsrv_pull_passthru_sfileinfo(io, io->generic.level, io,
     276         360 :                                                 &op->info->in.blob,
     277         360 :                                                 STR_UNICODE, &op->req->in.bufinfo);
     278         360 :         NT_STATUS_NOT_OK_RETURN(status);
     279             : 
     280         360 :         return ntvfs_setfileinfo(op->req->ntvfs, io);
     281             : }
     282             : 
     283           0 : static NTSTATUS smb2srv_setinfo_fs(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
     284             : {
     285           0 :         switch (smb2_level) {
     286           0 :         case 0x02:
     287           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     288             : 
     289           0 :         case 0x06:
     290           0 :                 return NT_STATUS_ACCESS_DENIED;
     291             : 
     292           0 :         case 0x08:
     293           0 :                 return NT_STATUS_ACCESS_DENIED;
     294             : 
     295           0 :         case 0x0A:
     296           0 :                 return NT_STATUS_ACCESS_DENIED;
     297             :         }
     298             : 
     299           0 :         return NT_STATUS_INVALID_INFO_CLASS;
     300             : }
     301             : 
     302          98 : static NTSTATUS smb2srv_setinfo_security(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
     303             : {
     304           0 :         union smb_setfileinfo *io;
     305           0 :         enum ndr_err_code ndr_err;
     306             : 
     307          98 :         switch (smb2_level) {
     308          98 :         case 0x00:
     309          98 :                 io = talloc(op, union smb_setfileinfo);
     310          98 :                 NT_STATUS_HAVE_NO_MEMORY(io);
     311             : 
     312          98 :                 io->set_secdesc.level            = RAW_SFILEINFO_SEC_DESC;
     313          98 :                 io->set_secdesc.in.file.ntvfs    = op->info->in.file.ntvfs;
     314          98 :                 io->set_secdesc.in.secinfo_flags = op->info->in.flags;
     315             : 
     316          98 :                 io->set_secdesc.in.sd = talloc(io, struct security_descriptor);
     317          98 :                 NT_STATUS_HAVE_NO_MEMORY(io->set_secdesc.in.sd);
     318             : 
     319          98 :                 ndr_err = ndr_pull_struct_blob(&op->info->in.blob, io, 
     320          98 :                                                io->set_secdesc.in.sd,
     321             :                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     322          98 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     323           0 :                         return ndr_map_error2ntstatus(ndr_err);
     324             :                 }
     325             : 
     326          98 :                 return ntvfs_setfileinfo(op->req->ntvfs, io);
     327             :         }
     328             : 
     329           0 :         return NT_STATUS_INVALID_INFO_CLASS;
     330             : }
     331             : 
     332         458 : static NTSTATUS smb2srv_setinfo_backend(struct smb2srv_setinfo_op *op)
     333             : {
     334           0 :         uint8_t smb2_class;
     335           0 :         uint8_t smb2_level;
     336             : 
     337         458 :         smb2_class = 0xFF & op->info->in.level;
     338         458 :         smb2_level = 0xFF & (op->info->in.level>>8);
     339             : 
     340         458 :         switch (smb2_class) {
     341         360 :         case SMB2_0_INFO_FILE:
     342         360 :                 return smb2srv_setinfo_file(op, smb2_level);
     343             : 
     344           0 :         case SMB2_0_INFO_FILESYSTEM:
     345           0 :                 return smb2srv_setinfo_fs(op, smb2_level);
     346             : 
     347          98 :         case SMB2_0_INFO_SECURITY:
     348          98 :                 return smb2srv_setinfo_security(op, smb2_level);
     349             : 
     350           0 :         case SMB2_0_INFO_QUOTA:
     351           0 :                 return NT_STATUS_NOT_SUPPORTED;
     352             :         }
     353             : 
     354           0 :         return NT_STATUS_INVALID_PARAMETER;
     355             : }
     356             : 
     357         458 : void smb2srv_setinfo_recv(struct smb2srv_request *req)
     358             : {
     359           0 :         struct smb2_setinfo *info;
     360           0 :         struct smb2srv_setinfo_op *op;
     361             : 
     362         458 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x20, true);
     363         458 :         SMB2SRV_TALLOC_IO_PTR(info, struct smb2_setinfo);
     364             :         /* this overwrites req->io_ptr !*/
     365         458 :         SMB2SRV_TALLOC_IO_PTR(op, struct smb2srv_setinfo_op);
     366         458 :         op->req              = req;
     367         458 :         op->info     = info;
     368         458 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_setinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     369             : 
     370         458 :         info->in.level                       = SVAL(req->in.body, 0x02);
     371         458 :         SMB2SRV_CHECK(smb2_pull_s32o16_blob(&req->in, info, req->in.body+0x04, &info->in.blob));
     372         458 :         info->in.flags                       = IVAL(req->in.body, 0x0C);
     373         458 :         info->in.file.ntvfs          = smb2srv_pull_handle(req, req->in.body, 0x10);
     374             : 
     375         458 :         SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
     376         458 :         SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_setinfo_backend(op));
     377             : }

Generated by: LCOV version 1.14