LCOV - code coverage report
Current view: top level - source4/smb_server/smb2 - fileinfo.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 151 174 86.8 %
Date: 2024-06-13 04:01:37 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         934 : static void smb2srv_getinfo_send(struct ntvfs_request *ntvfs)
      36             : {
      37             :         struct smb2srv_getinfo_op *op;
      38             :         struct smb2srv_request *req;
      39             : 
      40             :         /*
      41             :          * SMB2 uses NT_STATUS_INVALID_INFO_CLASS
      42             :          * so we need to translated it here
      43             :          */
      44         934 :         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         934 :         SMB2SRV_CHECK_ASYNC_STATUS(op, struct smb2srv_getinfo_op);
      49             : 
      50         929 :         ZERO_STRUCT(op->info->out);
      51         929 :         if (op->send_fn) {
      52         929 :                 SMB2SRV_CHECK(op->send_fn(op));
      53             :         }
      54             : 
      55         929 :         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         662 :         SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, op->info->out.blob.length));
      61             : 
      62         662 :         SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, op->info->out.blob));
      63         662 :         SSVAL(req->out.body, 0x06,   0);
      64             : 
      65         662 :         smb2srv_send_reply(req);
      66             : }
      67             : 
      68         717 : static NTSTATUS smb2srv_getinfo_file_send(struct smb2srv_getinfo_op *op)
      69             : {
      70         717 :         union smb_fileinfo *io = talloc_get_type(op->io_ptr, union smb_fileinfo);
      71             :         NTSTATUS status;
      72             : 
      73        1434 :         status = smbsrv_push_passthru_fileinfo(op->req,
      74         717 :                                                &op->info->out.blob,
      75             :                                                io->generic.level, io,
      76             :                                                STR_UNICODE);
      77         717 :         NT_STATUS_NOT_OK_RETURN(status);
      78             : 
      79         717 :         return NT_STATUS_OK;
      80             : }
      81             : 
      82         721 : static NTSTATUS smb2srv_getinfo_file(struct smb2srv_getinfo_op *op, uint8_t smb2_level)
      83             : {
      84             :         union smb_fileinfo *io;
      85             :         uint16_t level;
      86             : 
      87         721 :         io = talloc(op, union smb_fileinfo);
      88         721 :         NT_STATUS_HAVE_NO_MEMORY(io);
      89             : 
      90         721 :         level = op->info->in.info_type | (op->info->in.info_class << 8);
      91         721 :         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         570 :         case RAW_FILEINFO_SMB2_ALL_INFORMATION:
      99         570 :                 io->all_info2.level          = level;
     100         570 :                 io->all_info2.in.file.ntvfs  = op->info->in.file.ntvfs;
     101         570 :                 break;
     102             : 
     103         145 :         default:
     104             :                 /* the rest directly maps to the passthru levels */
     105         145 :                 io->generic.level            = smb2_level + 1000;
     106         145 :                 io->generic.in.file.ntvfs    = op->info->in.file.ntvfs;
     107         145 :                 break;
     108             :         }
     109             : 
     110         721 :         op->io_ptr   = io;
     111         721 :         op->send_fn  = smb2srv_getinfo_file_send;
     112             : 
     113         721 :         return ntvfs_qfileinfo(op->req->ntvfs, io);
     114             : }
     115             : 
     116         144 : static NTSTATUS smb2srv_getinfo_fs_send(struct smb2srv_getinfo_op *op)
     117             : {
     118         144 :         union smb_fsinfo *io = talloc_get_type(op->io_ptr, union smb_fsinfo);
     119             :         NTSTATUS status;
     120             : 
     121         288 :         status = smbsrv_push_passthru_fsinfo(op->req,
     122         144 :                                              &op->info->out.blob,
     123             :                                              io->generic.level, io,
     124             :                                              STR_UNICODE);
     125         144 :         NT_STATUS_NOT_OK_RETURN(status);
     126             : 
     127         144 :         return NT_STATUS_OK;
     128             : }
     129             : 
     130         144 : static NTSTATUS smb2srv_getinfo_fs(struct smb2srv_getinfo_op *op, uint8_t smb2_level)
     131             : {
     132             :         union smb_fsinfo *io;
     133             : 
     134         144 :         io = talloc(op, union smb_fsinfo);
     135         144 :         NT_STATUS_HAVE_NO_MEMORY(io);
     136             : 
     137             :         /* the rest directly maps to the passthru levels */
     138         144 :         io->generic.level    = smb2_level + 1000;
     139             : 
     140             :         /* TODO: allow qfsinfo only the share root directory handle */
     141             : 
     142         144 :         op->io_ptr   = io;
     143         144 :         op->send_fn  = smb2srv_getinfo_fs_send;
     144             : 
     145         144 :         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             :         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             :         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         934 : static NTSTATUS smb2srv_getinfo_backend(struct smb2srv_getinfo_op *op)
     186             : {
     187         934 :         switch (op->info->in.info_type) {
     188         721 :         case SMB2_0_INFO_FILE:
     189         721 :                 return smb2srv_getinfo_file(op, op->info->in.info_class);
     190             : 
     191         144 :         case SMB2_0_INFO_FILESYSTEM:
     192         144 :                 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         935 : void smb2srv_getinfo_recv(struct smb2srv_request *req)
     205             : {
     206             :         struct smb2_getinfo *info;
     207             :         struct smb2srv_getinfo_op *op;
     208             : 
     209         935 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x28, true);
     210         935 :         SMB2SRV_TALLOC_IO_PTR(info, struct smb2_getinfo);
     211             :         /* this overwrites req->io_ptr !*/
     212         935 :         SMB2SRV_TALLOC_IO_PTR(op, struct smb2srv_getinfo_op);
     213         935 :         op->req              = req;
     214         935 :         op->info     = info;
     215         935 :         op->io_ptr   = NULL;
     216         935 :         op->send_fn  = NULL;
     217         935 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_getinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     218             : 
     219         935 :         info->in.info_type           = CVAL(req->in.body, 0x02);
     220         935 :         info->in.info_class          = CVAL(req->in.body, 0x03);
     221         935 :         info->in.output_buffer_length        = IVAL(req->in.body, 0x04);
     222         935 :         info->in.reserved            = IVAL(req->in.body, 0x0C);
     223         935 :         info->in.additional_information      = IVAL(req->in.body, 0x10);
     224         935 :         info->in.getinfo_flags               = IVAL(req->in.body, 0x14);
     225         935 :         info->in.file.ntvfs          = smb2srv_pull_handle(req, req->in.body, 0x18);
     226         935 :         SMB2SRV_CHECK(smb2_pull_o16As32_blob(&req->in, op, 
     227             :                                             req->in.body+0x08, &info->in.input_buffer));
     228             : 
     229         935 :         SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
     230         934 :         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         413 : static void smb2srv_setinfo_send(struct ntvfs_request *ntvfs)
     239             : {
     240             :         struct smb2srv_setinfo_op *op;
     241             :         struct smb2srv_request *req;
     242             : 
     243             :         /*
     244             :          * SMB2 uses NT_STATUS_INVALID_INFO_CLASS
     245             :          * so we need to translated it here
     246             :          */
     247         413 :         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         413 :         SMB2SRV_CHECK_ASYNC_STATUS(op, struct smb2srv_setinfo_op);
     252             : 
     253         405 :         SMB2SRV_CHECK(smb2srv_setup_reply(op->req, 0x02, false, 0));
     254             : 
     255         405 :         smb2srv_send_reply(req);
     256             : }
     257             : 
     258         353 : static NTSTATUS smb2srv_setinfo_file(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
     259             : {
     260             :         union smb_setfileinfo *io;
     261             :         NTSTATUS status;
     262             : 
     263         353 :         io = talloc(op, union smb_setfileinfo);
     264         353 :         NT_STATUS_HAVE_NO_MEMORY(io);
     265             : 
     266             :         /* the levels directly map to the passthru levels */
     267         353 :         io->generic.level            = smb2_level + 1000;
     268         353 :         io->generic.in.file.ntvfs    = op->info->in.file.ntvfs;
     269             : 
     270             :         /* handle cases that don't map directly */
     271         353 :         if (io->generic.level == RAW_SFILEINFO_RENAME_INFORMATION) {
     272           8 :                 io->generic.level = RAW_SFILEINFO_RENAME_INFORMATION_SMB2;
     273             :         }
     274             : 
     275         706 :         status = smbsrv_pull_passthru_sfileinfo(io, io->generic.level, io,
     276         353 :                                                 &op->info->in.blob,
     277         353 :                                                 STR_UNICODE, &op->req->in.bufinfo);
     278         353 :         NT_STATUS_NOT_OK_RETURN(status);
     279             : 
     280         353 :         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          60 : static NTSTATUS smb2srv_setinfo_security(struct smb2srv_setinfo_op *op, uint8_t smb2_level)
     303             : {
     304             :         union smb_setfileinfo *io;
     305             :         enum ndr_err_code ndr_err;
     306             : 
     307          60 :         switch (smb2_level) {
     308          60 :         case 0x00:
     309          60 :                 io = talloc(op, union smb_setfileinfo);
     310          60 :                 NT_STATUS_HAVE_NO_MEMORY(io);
     311             : 
     312          60 :                 io->set_secdesc.level            = RAW_SFILEINFO_SEC_DESC;
     313          60 :                 io->set_secdesc.in.file.ntvfs    = op->info->in.file.ntvfs;
     314          60 :                 io->set_secdesc.in.secinfo_flags = op->info->in.flags;
     315             : 
     316          60 :                 io->set_secdesc.in.sd = talloc(io, struct security_descriptor);
     317          60 :                 NT_STATUS_HAVE_NO_MEMORY(io->set_secdesc.in.sd);
     318             : 
     319          60 :                 ndr_err = ndr_pull_struct_blob(&op->info->in.blob, io, 
     320          60 :                                                io->set_secdesc.in.sd,
     321             :                                                (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     322          60 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     323           0 :                         return ndr_map_error2ntstatus(ndr_err);
     324             :                 }
     325             : 
     326          60 :                 return ntvfs_setfileinfo(op->req->ntvfs, io);
     327             :         }
     328             : 
     329           0 :         return NT_STATUS_INVALID_INFO_CLASS;
     330             : }
     331             : 
     332         413 : static NTSTATUS smb2srv_setinfo_backend(struct smb2srv_setinfo_op *op)
     333             : {
     334             :         uint8_t smb2_class;
     335             :         uint8_t smb2_level;
     336             : 
     337         413 :         smb2_class = 0xFF & op->info->in.level;
     338         413 :         smb2_level = 0xFF & (op->info->in.level>>8);
     339             : 
     340         413 :         switch (smb2_class) {
     341         353 :         case SMB2_0_INFO_FILE:
     342         353 :                 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          60 :         case SMB2_0_INFO_SECURITY:
     348          60 :                 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         413 : void smb2srv_setinfo_recv(struct smb2srv_request *req)
     358             : {
     359             :         struct smb2_setinfo *info;
     360             :         struct smb2srv_setinfo_op *op;
     361             : 
     362         413 :         SMB2SRV_CHECK_BODY_SIZE(req, 0x20, true);
     363         413 :         SMB2SRV_TALLOC_IO_PTR(info, struct smb2_setinfo);
     364             :         /* this overwrites req->io_ptr !*/
     365         413 :         SMB2SRV_TALLOC_IO_PTR(op, struct smb2srv_setinfo_op);
     366         413 :         op->req              = req;
     367         413 :         op->info     = info;
     368         413 :         SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_setinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
     369             : 
     370         413 :         info->in.level                       = SVAL(req->in.body, 0x02);
     371         413 :         SMB2SRV_CHECK(smb2_pull_s32o16_blob(&req->in, info, req->in.body+0x04, &info->in.blob));
     372         413 :         info->in.flags                       = IVAL(req->in.body, 0x0C);
     373         413 :         info->in.file.ntvfs          = smb2srv_pull_handle(req, req->in.body, 0x10);
     374             : 
     375         413 :         SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
     376         413 :         SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_setinfo_backend(op));
     377             : }

Generated by: LCOV version 1.13