LCOV - code coverage report
Current view: top level - source4/libcli/smb2 - getinfo.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 87 96 90.6 %
Date: 2024-04-13 12:30:31 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    SMB2 client getinfo calls
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2005
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libcli/raw/libcliraw.h"
      24             : #include "libcli/raw/raw_proto.h"
      25             : #include "libcli/smb2/smb2.h"
      26             : #include "libcli/smb2/smb2_calls.h"
      27             : 
      28             : /*
      29             :   send a getinfo request
      30             : */
      31       13711 : struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getinfo *io)
      32             : {
      33         324 :         struct smb2_request *req;
      34         324 :         NTSTATUS status;
      35         324 :         size_t max_payload;
      36             : 
      37       14035 :         req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, true, 
      38       13711 :                                      io->in.input_buffer.length);
      39       13711 :         if (req == NULL) return NULL;
      40             : 
      41       13711 :         SCVAL(req->out.body, 0x02, io->in.info_type);
      42       13711 :         SCVAL(req->out.body, 0x03, io->in.info_class);
      43       13711 :         SIVAL(req->out.body, 0x04, io->in.output_buffer_length);
      44             :         /*
      45             :          * uint16_t input_buffer_offset
      46             :          * uint16_t reserved
      47             :          * uint32_t input_buffer_length
      48             :          *
      49             :          * We use smb2_push_o32s32_blob() which would
      50             :          * expect uint32_t offset, uint32_t length.
      51             :          *
      52             :          * Everything is little endian, we can just
      53             :          * overwrite the reserved field later.
      54             :          */
      55       13711 :         SIVAL(req->out.body, 0x10, io->in.additional_information);
      56       13711 :         SIVAL(req->out.body, 0x14, io->in.getinfo_flags);
      57       13711 :         smb2_push_handle(req->out.body+0x18, &io->in.file.handle);
      58             : 
      59             :         /* this blob is used for quota queries */
      60       13711 :         status = smb2_push_o32s32_blob(&req->out, 0x08, io->in.input_buffer);
      61       13711 :         if (!NT_STATUS_IS_OK(status)) {
      62           0 :                 talloc_free(req);
      63           0 :                 return NULL;
      64             :         }
      65       13711 :         SSVAL(req->out.body, 0x0C, io->in.reserved);
      66             : 
      67       13711 :         max_payload = MAX(io->in.output_buffer_length, io->in.input_buffer.length);
      68       13711 :         req->credit_charge = (MAX(max_payload, 1) - 1)/ 65536 + 1;
      69             : 
      70       13711 :         smb2_transport_send(req);
      71             : 
      72       13711 :         return req;
      73             : }
      74             : 
      75             : 
      76             : /*
      77             :   recv a getinfo reply
      78             : */
      79       13705 : NTSTATUS smb2_getinfo_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
      80             :                            struct smb2_getinfo *io)
      81             : {
      82         324 :         NTSTATUS status;
      83             : 
      84       27401 :         if (!smb2_request_receive(req) || 
      85       13696 :             smb2_request_is_error(req)) {
      86        2148 :                 return smb2_request_destroy(req);
      87             :         }
      88             : 
      89       11557 :         SMB2_CHECK_PACKET_RECV(req, 0x08, true);
      90             : 
      91       11557 :         status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x02, &io->out.blob);
      92       11557 :         if (!NT_STATUS_IS_OK(status)) {
      93           0 :                 return status;
      94             :         }
      95             : 
      96       11557 :         return smb2_request_destroy(req);
      97             : }
      98             : 
      99             : /*
     100             :   sync getinfo request
     101             : */
     102        2297 : NTSTATUS smb2_getinfo(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
     103             :                       struct smb2_getinfo *io)
     104             : {
     105        2297 :         struct smb2_request *req = smb2_getinfo_send(tree, io);
     106        2297 :         return smb2_getinfo_recv(req, mem_ctx, io);
     107             : }
     108             : 
     109             : 
     110             : /*
     111             :   map a generic info level to a SMB2 info level
     112             : */
     113       17955 : uint16_t smb2_getinfo_map_level(uint16_t level, uint8_t info_class)
     114             : {
     115       17955 :         if (info_class == SMB2_0_INFO_FILE &&
     116         328 :             level == RAW_FILEINFO_SEC_DESC) {
     117        8678 :                 return SMB2_0_INFO_SECURITY;
     118             :         }
     119        9263 :         if ((level & 0xFF) == info_class) {
     120        1626 :                 return level;
     121        7636 :         } else if (level > 1000) {
     122        7636 :                 return ((level-1000)<<8) | info_class;
     123             :         }
     124           0 :         DEBUG(0,("Unable to map SMB2 info level 0x%04x of class %d\n",
     125             :                  level, info_class));
     126           0 :         return 0;       
     127             : }
     128             : 
     129             : /*
     130             :   level specific getinfo call - async send
     131             : */
     132       10968 : struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fileinfo *io)
     133             : {
     134         324 :         struct smb2_getinfo b;
     135       11292 :         uint16_t smb2_level = smb2_getinfo_map_level(
     136       10968 :                 io->generic.level, SMB2_0_INFO_FILE);
     137             :         
     138       10968 :         if (smb2_level == 0) {
     139           0 :                 return NULL;
     140             :         }
     141             : 
     142       10968 :         ZERO_STRUCT(b);
     143       10968 :         b.in.info_type            = smb2_level & 0xFF;
     144       10968 :         b.in.info_class           = smb2_level >> 8;
     145       10968 :         b.in.output_buffer_length = 0x10000;
     146       10968 :         b.in.input_buffer         = data_blob_null;
     147       10968 :         b.in.file.handle          = io->generic.in.file.handle;
     148             : 
     149       10968 :         if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
     150        4072 :                 b.in.additional_information = io->query_secdesc.in.secinfo_flags;
     151             :         }
     152       10968 :         if (io->generic.level == RAW_FILEINFO_SMB2_ALL_EAS) {
     153          36 :                 b.in.getinfo_flags = io->all_eas.in.continue_flags;
     154             :         }
     155             : 
     156       10968 :         return smb2_getinfo_send(tree, &b);
     157             : }
     158             : 
     159             : /*
     160             :   recv a getinfo reply and parse the level info
     161             : */
     162       10968 : NTSTATUS smb2_getinfo_file_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
     163             :                                 union smb_fileinfo *io)
     164             : {
     165         324 :         struct smb2_getinfo b;
     166         324 :         NTSTATUS status;
     167             : 
     168       10968 :         status = smb2_getinfo_recv(req, mem_ctx, &b);
     169       10968 :         NT_STATUS_NOT_OK_RETURN(status);
     170             : 
     171       10763 :         status = smb_raw_fileinfo_passthru_parse(&b.out.blob, mem_ctx, io->generic.level, io);
     172       10763 :         data_blob_free(&b.out.blob);
     173             : 
     174       10763 :         return status;
     175             : }
     176             : 
     177             : /*
     178             :   level specific getinfo call
     179             : */
     180       10968 : NTSTATUS smb2_getinfo_file(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, 
     181             :                            union smb_fileinfo *io)
     182             : {
     183       10968 :         struct smb2_request *req = smb2_getinfo_file_send(tree, io);
     184       10968 :         return smb2_getinfo_file_recv(req, mem_ctx, io);
     185             : }
     186             : 
     187             : 
     188             : /*
     189             :   level specific getinfo call - async send
     190             : */
     191         434 : struct smb2_request *smb2_getinfo_fs_send(struct smb2_tree *tree, union smb_fsinfo *io)
     192             : {
     193           0 :         struct smb2_getinfo b;
     194         434 :         uint16_t smb2_level = smb2_getinfo_map_level(
     195         434 :                 io->generic.level, SMB2_0_INFO_FILESYSTEM);
     196             :         
     197         434 :         if (smb2_level == 0) {
     198           0 :                 return NULL;
     199             :         }
     200             :         
     201         434 :         ZERO_STRUCT(b);
     202         434 :         b.in.output_buffer_length = 0x10000;
     203         434 :         b.in.file.handle          = io->generic.handle;
     204         434 :         b.in.info_type            = smb2_level & 0xFF;
     205         434 :         b.in.info_class           = smb2_level >> 8;
     206             : 
     207         434 :         return smb2_getinfo_send(tree, &b);
     208             : }
     209             : 
     210             : /*
     211             :   recv a getinfo reply and parse the level info
     212             : */
     213         434 : NTSTATUS smb2_getinfo_fs_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
     214             :                                 union smb_fsinfo *io)
     215             : {
     216         434 :         struct smb2_getinfo b = {
     217             :                 .in = {0},
     218             :         };
     219           0 :         NTSTATUS status;
     220             : 
     221         434 :         status = smb2_getinfo_recv(req, mem_ctx, &b);
     222         434 :         NT_STATUS_NOT_OK_RETURN(status);
     223             : 
     224         430 :         status = smb_raw_fsinfo_passthru_parse(b.out.blob, mem_ctx, io->generic.level, io);
     225         430 :         data_blob_free(&b.out.blob);
     226             : 
     227         430 :         return status;
     228             : }
     229             : 
     230             : /*
     231             :   level specific getinfo call
     232             : */
     233         434 : NTSTATUS smb2_getinfo_fs(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, 
     234             :                            union smb_fsinfo *io)
     235             : {
     236         434 :         struct smb2_request *req = smb2_getinfo_fs_send(tree, io);
     237         434 :         return smb2_getinfo_fs_recv(req, mem_ctx, io);
     238             : }
     239             : 

Generated by: LCOV version 1.14