LCOV - code coverage report
Current view: top level - source4/libcli/raw - rawfsinfo.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 184 215 85.6 %
Date: 2024-02-28 12:06:22 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    RAW_QFS_* operations
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       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 "librpc/gen_ndr/ndr_misc.h"
      26             : 
      27             : /****************************************************************************
      28             :  Query FS Info - SMBdskattr call (async send)
      29             : ****************************************************************************/
      30           1 : static struct smbcli_request *smb_raw_dskattr_send(struct smbcli_tree *tree,
      31             :                                                 union smb_fsinfo *fsinfo)
      32             : {
      33           0 :         struct smbcli_request *req;
      34             : 
      35           1 :         req = smbcli_request_setup(tree, SMBdskattr, 0, 0);
      36           1 :         if (req == NULL) {
      37           0 :                 return NULL;
      38             :         }
      39             : 
      40           1 :         if (!smbcli_request_send(req)) {
      41           0 :                 smbcli_request_destroy(req);
      42           0 :                 return NULL;
      43             :         }
      44             : 
      45           1 :         return req;
      46             : }
      47             : 
      48             : /****************************************************************************
      49             :  Query FS Info - SMBdskattr call (async recv)
      50             : ****************************************************************************/
      51           1 : static NTSTATUS smb_raw_dskattr_recv(struct smbcli_request *req,
      52             :                                      union smb_fsinfo *fsinfo)
      53             : {
      54           2 :         if (!smbcli_request_receive(req) ||
      55           1 :             smbcli_request_is_error(req)) {
      56           0 :                 goto failed;
      57             :         }
      58             : 
      59           1 :         SMBCLI_CHECK_WCT(req, 5);
      60           1 :         fsinfo->dskattr.out.units_total =     SVAL(req->in.vwv, VWV(0));
      61           1 :         fsinfo->dskattr.out.blocks_per_unit = SVAL(req->in.vwv, VWV(1));
      62           1 :         fsinfo->dskattr.out.block_size =      SVAL(req->in.vwv, VWV(2));
      63           1 :         fsinfo->dskattr.out.units_free =      SVAL(req->in.vwv, VWV(3));
      64             : 
      65           1 : failed:
      66           1 :         return smbcli_request_destroy(req);
      67             : }
      68             : 
      69             : 
      70             : /****************************************************************************
      71             :  RAW_QFS_ trans2 interface via blobs (async send)
      72             : ****************************************************************************/
      73        2110 : static struct smbcli_request *smb_raw_qfsinfo_send(struct smbcli_tree *tree,
      74             :                                                 TALLOC_CTX *mem_ctx,
      75             :                                                 uint16_t info_level)
      76             : {
      77           0 :         struct smb_trans2 tp;
      78        2110 :         uint16_t setup = TRANSACT2_QFSINFO;
      79             : 
      80        2110 :         tp.in.max_setup = 0;
      81        2110 :         tp.in.flags = 0;
      82        2110 :         tp.in.timeout = 0;
      83        2110 :         tp.in.setup_count = 1;
      84        2110 :         tp.in.max_param = 0;
      85        2110 :         tp.in.max_data = 0xFFFF;
      86        2110 :         tp.in.setup = &setup;
      87        2110 :         tp.in.data = data_blob(NULL, 0);
      88        2110 :         tp.in.timeout = 0;
      89             : 
      90        2110 :         tp.in.params = data_blob_talloc(mem_ctx, NULL, 2);
      91        2110 :         if (!tp.in.params.data) {
      92           0 :                 return NULL;
      93             :         }
      94        2110 :         SSVAL(tp.in.params.data, 0, info_level);
      95             : 
      96        2110 :         return smb_raw_trans2_send(tree, &tp);
      97             : }
      98             : 
      99             : /****************************************************************************
     100             :  RAW_QFS_ trans2 interface via blobs (async recv)
     101             : ****************************************************************************/
     102        2114 : static NTSTATUS smb_raw_qfsinfo_blob_recv(struct smbcli_request *req,
     103             :                                           TALLOC_CTX *mem_ctx,
     104             :                                           DATA_BLOB *blob)
     105             : {
     106           0 :         struct smb_trans2 tp;
     107           0 :         NTSTATUS status;
     108             : 
     109        2114 :         status = smb_raw_trans2_recv(req, mem_ctx, &tp);
     110             : 
     111        2114 :         if (NT_STATUS_IS_OK(status)) {
     112         127 :                 (*blob) = tp.out.data;
     113             :         }
     114             : 
     115        2114 :         return status;
     116             : }
     117             : 
     118             : 
     119             : /* local macros to make the code more readable */
     120             : #define QFS_CHECK_MIN_SIZE(size) if (blob.length < (size)) { \
     121             :       DEBUG(1,("Unexpected QFS reply size %d for level %u - expected min of %d\n", \
     122             :                (int)blob.length, fsinfo->generic.level, (size))); \
     123             :       status = NT_STATUS_INFO_LENGTH_MISMATCH; \
     124             :       goto failed; \
     125             : }
     126             : #define QFS_CHECK_SIZE(size) if (blob.length != (size)) { \
     127             :       DEBUG(1,("Unexpected QFS reply size %d for level %u - expected %d\n", \
     128             :                (int)blob.length, fsinfo->generic.level, (size))); \
     129             :       status = NT_STATUS_INFO_LENGTH_MISMATCH; \
     130             :       goto failed; \
     131             : }
     132             : 
     133             : 
     134             : /****************************************************************************
     135             :  Query FSInfo raw interface (async send)
     136             : ****************************************************************************/
     137        2111 : struct smbcli_request *smb_raw_fsinfo_send(struct smbcli_tree *tree,
     138             :                                         TALLOC_CTX *mem_ctx,
     139             :                                         union smb_fsinfo *fsinfo)
     140             : {
     141           0 :         uint16_t info_level;
     142             : 
     143             :         /* handle the only non-trans2 call separately */
     144        2111 :         if (fsinfo->generic.level == RAW_QFS_DSKATTR) {
     145           1 :                 return smb_raw_dskattr_send(tree, fsinfo);
     146             :         }
     147        2110 :         if (fsinfo->generic.level >= RAW_QFS_GENERIC) {
     148           0 :                 return NULL;
     149             :         }
     150             : 
     151             :         /* the headers map the trans2 levels direct to info levels */
     152        2110 :         info_level = (uint16_t)fsinfo->generic.level;
     153             : 
     154        2110 :         return smb_raw_qfsinfo_send(tree, mem_ctx, info_level);
     155             : }
     156             : 
     157             : /*
     158             :   parse the fsinfo 'passthru' level replies
     159             : */
     160         585 : NTSTATUS smb_raw_fsinfo_passthru_parse(DATA_BLOB blob, TALLOC_CTX *mem_ctx,
     161             :                                        enum smb_fsinfo_level level,
     162             :                                        union smb_fsinfo *fsinfo)
     163             : {
     164         585 :         NTSTATUS status = NT_STATUS_OK;
     165           0 :         int i;
     166             : 
     167             :         /* parse the results */
     168         585 :         switch (level) {
     169          13 :         case RAW_QFS_VOLUME_INFORMATION:
     170          13 :                 QFS_CHECK_MIN_SIZE(18);
     171          13 :                 fsinfo->volume_info.out.create_time   = smbcli_pull_nttime(blob.data, 0);
     172          13 :                 fsinfo->volume_info.out.serial_number = IVAL(blob.data, 8);
     173          13 :                 smbcli_blob_pull_string(NULL, mem_ctx, &blob,
     174             :                                         &fsinfo->volume_info.out.volume_name,
     175             :                                         12, 18, STR_UNICODE);
     176         585 :                 break;
     177             : 
     178          25 :         case RAW_QFS_SIZE_INFORMATION:
     179          25 :                 QFS_CHECK_SIZE(24);
     180          25 :                 fsinfo->size_info.out.total_alloc_units = BVAL(blob.data,  0);
     181          25 :                 fsinfo->size_info.out.avail_alloc_units = BVAL(blob.data,  8);
     182          25 :                 fsinfo->size_info.out.sectors_per_unit =  IVAL(blob.data, 16);
     183          25 :                 fsinfo->size_info.out.bytes_per_sector =  IVAL(blob.data, 20);
     184          25 :                 break;
     185             : 
     186          13 :         case RAW_QFS_DEVICE_INFORMATION:
     187          13 :                 QFS_CHECK_SIZE(8);
     188          13 :                 fsinfo->device_info.out.device_type     = IVAL(blob.data,  0);
     189          13 :                 fsinfo->device_info.out.characteristics = IVAL(blob.data,  4);
     190          13 :                 break;
     191             : 
     192         458 :         case RAW_QFS_ATTRIBUTE_INFORMATION:
     193         458 :                 QFS_CHECK_MIN_SIZE(12);
     194         458 :                 fsinfo->attribute_info.out.fs_attr   =                 IVAL(blob.data, 0);
     195         458 :                 fsinfo->attribute_info.out.max_file_component_length = IVAL(blob.data, 4);
     196         458 :                 smbcli_blob_pull_string(NULL, mem_ctx, &blob,
     197             :                                         &fsinfo->attribute_info.out.fs_type,
     198             :                                         8, 12, STR_UNICODE);
     199         458 :                 break;
     200             : 
     201           5 :         case RAW_QFS_QUOTA_INFORMATION:
     202           5 :                 QFS_CHECK_SIZE(48);
     203           5 :                 fsinfo->quota_information.out.unknown[0] =  BVAL(blob.data,  0);
     204           5 :                 fsinfo->quota_information.out.unknown[1] =  BVAL(blob.data,  8);
     205           5 :                 fsinfo->quota_information.out.unknown[2] =  BVAL(blob.data, 16);
     206           5 :                 fsinfo->quota_information.out.quota_soft =  BVAL(blob.data, 24);
     207           5 :                 fsinfo->quota_information.out.quota_hard =  BVAL(blob.data, 32);
     208           5 :                 fsinfo->quota_information.out.quota_flags = BVAL(blob.data, 40);
     209           5 :                 break;
     210             : 
     211           5 :         case RAW_QFS_FULL_SIZE_INFORMATION:
     212           5 :                 QFS_CHECK_SIZE(32);
     213           5 :                 fsinfo->full_size_information.out.total_alloc_units =        BVAL(blob.data,  0);
     214           5 :                 fsinfo->full_size_information.out.call_avail_alloc_units =   BVAL(blob.data,  8);
     215           5 :                 fsinfo->full_size_information.out.actual_avail_alloc_units = BVAL(blob.data, 16);
     216           5 :                 fsinfo->full_size_information.out.sectors_per_unit =         IVAL(blob.data, 24);
     217           5 :                 fsinfo->full_size_information.out.bytes_per_sector =         IVAL(blob.data, 28);
     218           5 :                 break;
     219             : 
     220          54 :         case RAW_QFS_OBJECTID_INFORMATION: {
     221          54 :                 DATA_BLOB b2 = data_blob_const(blob.data, MIN(16, blob.length));
     222          54 :                 QFS_CHECK_SIZE(64);
     223          54 :                 status = GUID_from_ndr_blob(&b2, &fsinfo->objectid_information.out.guid);
     224          54 :                 NT_STATUS_NOT_OK_RETURN(status);
     225         378 :                 for (i=0;i<6;i++) {
     226         324 :                         fsinfo->objectid_information.out.unknown[i] = BVAL(blob.data, 16 + i*8);
     227             :                 }
     228          66 :                 break;
     229             : 
     230          12 :         case RAW_QFS_SECTOR_SIZE_INFORMATION:
     231          12 :                 QFS_CHECK_SIZE(28);
     232           0 :                 fsinfo->sector_size_info.out.logical_bytes_per_sector
     233          12 :                                                         = IVAL(blob.data,  0);
     234           0 :                 fsinfo->sector_size_info.out.phys_bytes_per_sector_atomic
     235          12 :                                                         = IVAL(blob.data,  4);
     236           0 :                 fsinfo->sector_size_info.out.phys_bytes_per_sector_perf
     237          12 :                                                         = IVAL(blob.data,  8);
     238           0 :                 fsinfo->sector_size_info.out.fs_effective_phys_bytes_per_sector_atomic
     239          12 :                                                         = IVAL(blob.data, 12);
     240          12 :                 fsinfo->sector_size_info.out.flags   = IVAL(blob.data, 16);
     241           0 :                 fsinfo->sector_size_info.out.byte_off_sector_align
     242          12 :                                                         = IVAL(blob.data, 20);
     243           0 :                 fsinfo->sector_size_info.out.byte_off_partition_align
     244          12 :                                                         = IVAL(blob.data, 24);
     245          12 :                 break;
     246             :         }
     247             : 
     248           0 :         default:
     249           0 :                 status = NT_STATUS_INVALID_INFO_CLASS;
     250             :         }
     251             : 
     252         585 : failed:
     253         585 :         return status;
     254             : }
     255             : 
     256             : 
     257             : /****************************************************************************
     258             :  Query FSInfo raw interface (async recv)
     259             : ****************************************************************************/
     260        2111 : NTSTATUS smb_raw_fsinfo_recv(struct smbcli_request *req,
     261             :                              TALLOC_CTX *mem_ctx,
     262             :                              union smb_fsinfo *fsinfo)
     263             : {
     264           0 :         DATA_BLOB blob;
     265           0 :         NTSTATUS status;
     266        2111 :         struct smbcli_session *session = req?req->session:NULL;
     267             : 
     268        2111 :         if (fsinfo->generic.level == RAW_QFS_DSKATTR) {
     269           1 :                 return smb_raw_dskattr_recv(req, fsinfo);
     270             :         }
     271             : 
     272        2110 :         status = smb_raw_qfsinfo_blob_recv(req, mem_ctx, &blob);
     273        2110 :         if (!NT_STATUS_IS_OK(status)) {
     274        1987 :                 return status;
     275             :         }
     276             : 
     277             :         /* parse the results */
     278         123 :         switch (fsinfo->generic.level) {
     279           0 :         case RAW_QFS_GENERIC:
     280             :         case RAW_QFS_DSKATTR:
     281             :                 /* handled above */
     282           0 :                 break;
     283             : 
     284           4 :         case RAW_QFS_ALLOCATION:
     285           4 :                 QFS_CHECK_SIZE(18);
     286           4 :                 fsinfo->allocation.out.fs_id =             IVAL(blob.data,  0);
     287           4 :                 fsinfo->allocation.out.sectors_per_unit =  IVAL(blob.data,  4);
     288           4 :                 fsinfo->allocation.out.total_alloc_units = IVAL(blob.data,  8);
     289           4 :                 fsinfo->allocation.out.avail_alloc_units = IVAL(blob.data, 12);
     290           4 :                 fsinfo->allocation.out.bytes_per_sector =  SVAL(blob.data, 16);
     291           4 :                 break;
     292             : 
     293           4 :         case RAW_QFS_VOLUME:
     294           4 :                 QFS_CHECK_MIN_SIZE(5);
     295           4 :                 fsinfo->volume.out.serial_number = IVAL(blob.data, 0);
     296           4 :                 smbcli_blob_pull_string(session, mem_ctx, &blob,
     297             :                                      &fsinfo->volume.out.volume_name,
     298             :                                      4, 5, STR_LEN8BIT | STR_NOALIGN);
     299           4 :                 break;
     300             : 
     301           8 :         case RAW_QFS_VOLUME_INFO:
     302             :         case RAW_QFS_VOLUME_INFORMATION:
     303           8 :                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
     304             :                                                      RAW_QFS_VOLUME_INFORMATION, fsinfo);
     305             : 
     306          18 :         case RAW_QFS_SIZE_INFO:
     307             :         case RAW_QFS_SIZE_INFORMATION:
     308          18 :                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
     309             :                                                      RAW_QFS_SIZE_INFORMATION, fsinfo);
     310             : 
     311           8 :         case RAW_QFS_DEVICE_INFO:
     312             :         case RAW_QFS_DEVICE_INFORMATION:
     313           8 :                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
     314             :                                                      RAW_QFS_DEVICE_INFORMATION, fsinfo);
     315             : 
     316          15 :         case RAW_QFS_ATTRIBUTE_INFO:
     317             :         case RAW_QFS_ATTRIBUTE_INFORMATION:
     318          15 :                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
     319             :                                                      RAW_QFS_ATTRIBUTE_INFORMATION, fsinfo);
     320             : 
     321           4 :         case RAW_QFS_UNIX_INFO:
     322           4 :                 QFS_CHECK_SIZE(12);
     323           4 :                 fsinfo->unix_info.out.major_version = SVAL(blob.data, 0);
     324           4 :                 fsinfo->unix_info.out.minor_version = SVAL(blob.data, 2);
     325           4 :                 fsinfo->unix_info.out.capability    = SVAL(blob.data, 4);
     326           4 :                 break;
     327             : 
     328           4 :         case RAW_QFS_QUOTA_INFORMATION:
     329           4 :                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
     330             :                                                      RAW_QFS_QUOTA_INFORMATION, fsinfo);
     331             : 
     332           4 :         case RAW_QFS_FULL_SIZE_INFORMATION:
     333           4 :                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
     334             :                                                      RAW_QFS_FULL_SIZE_INFORMATION, fsinfo);
     335             : 
     336          53 :         case RAW_QFS_OBJECTID_INFORMATION:
     337          53 :                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
     338             :                                                      RAW_QFS_OBJECTID_INFORMATION, fsinfo);
     339             : 
     340           1 :         case RAW_QFS_SECTOR_SIZE_INFORMATION:
     341           1 :                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
     342             :                                 RAW_QFS_SECTOR_SIZE_INFORMATION, fsinfo);
     343             :         }
     344             : 
     345          12 : failed:
     346          12 :         return status;
     347             : }
     348             : 
     349             : /****************************************************************************
     350             :  Query FSInfo raw interface (sync interface)
     351             : ****************************************************************************/
     352          60 : _PUBLIC_ NTSTATUS smb_raw_fsinfo(struct smbcli_tree *tree,
     353             :                         TALLOC_CTX *mem_ctx,
     354             :                         union smb_fsinfo *fsinfo)
     355             : {
     356          60 :         struct smbcli_request *req = smb_raw_fsinfo_send(tree, mem_ctx, fsinfo);
     357          60 :         return smb_raw_fsinfo_recv(req, mem_ctx, fsinfo);
     358             : }
     359             : 
     360             : /****************************************************************************
     361             :  Set FSInfo raw interface (async recv)
     362             : ****************************************************************************/
     363           4 : static NTSTATUS smb_raw_setfsinfo_recv(struct smbcli_request *req,
     364             :                              TALLOC_CTX *mem_ctx,
     365             :                              union smb_setfsinfo *set_fsinfo)
     366             : {
     367           4 :         DATA_BLOB blob = data_blob_null;
     368           0 :         NTSTATUS status;
     369             : 
     370           4 :         if (set_fsinfo->generic.level != RAW_SETFS_UNIX_INFO) {
     371           0 :                 return NT_STATUS_INVALID_PARAMETER;
     372             :         }
     373             : 
     374           4 :         status = smb_raw_qfsinfo_blob_recv(req, mem_ctx, &blob);
     375           4 :         data_blob_free(&blob);
     376           4 :         return status;
     377             : }
     378             : 
     379             : /****************************************************************************
     380             :  Set FSInfo raw interface (async send)
     381             : ****************************************************************************/
     382           4 : static struct smbcli_request *smb_raw_setfsinfo_send(struct smbcli_tree *tree,
     383             :                                                 TALLOC_CTX *mem_ctx,
     384             :                                                 union smb_setfsinfo *set_fsinfo)
     385             : {
     386           0 :         struct smb_trans2 tp;
     387           0 :         uint16_t info_level;
     388           4 :         uint16_t setup = TRANSACT2_SETFSINFO;
     389             : 
     390           4 :         if (set_fsinfo->generic.level != RAW_SETFS_UNIX_INFO) {
     391           0 :                 return NULL;
     392             :         }
     393           4 :         tp.in.max_setup = 0;
     394           4 :         tp.in.flags = 0;
     395           4 :         tp.in.timeout = 0;
     396           4 :         tp.in.setup_count = 1;
     397           4 :         tp.in.max_param = 0;
     398           4 :         tp.in.max_data = 0xFFFF;
     399           4 :         tp.in.setup = &setup;
     400           4 :         tp.in.timeout = 0;
     401             : 
     402           4 :         tp.in.params = data_blob_talloc(mem_ctx, NULL, 4);
     403           4 :         if (!tp.in.params.data) {
     404           0 :                 return NULL;
     405             :         }
     406           4 :         info_level = (uint16_t)set_fsinfo->generic.level;
     407           4 :         SSVAL(tp.in.params.data, 0, 0);
     408           4 :         SSVAL(tp.in.params.data, 2, info_level);
     409             : 
     410           4 :         tp.in.data = data_blob_talloc(mem_ctx, NULL, 12);
     411           4 :         if (!tp.in.data.data) {
     412           0 :                 return NULL;
     413             :         }
     414             : 
     415           4 :         SSVAL(tp.in.data.data, 0, set_fsinfo->unix_info.in.major_version);
     416           4 :         SSVAL(tp.in.data.data, 2, set_fsinfo->unix_info.in.minor_version);
     417           4 :         SBVAL(tp.in.data.data, 4, set_fsinfo->unix_info.in.capability);
     418             : 
     419           4 :         return smb_raw_trans2_send(tree, &tp);
     420             : }
     421             : 
     422             : /****************************************************************************
     423             :  Set FSInfo raw interface (sync interface)
     424             : ****************************************************************************/
     425           4 : _PUBLIC_ NTSTATUS smb_raw_setfsinfo(struct smbcli_tree *tree,
     426             :                         TALLOC_CTX *mem_ctx,
     427             :                         union smb_setfsinfo *set_fsinfo)
     428             : {
     429           4 :         struct smbcli_request *req = smb_raw_setfsinfo_send(tree, mem_ctx, set_fsinfo);
     430           4 :         return smb_raw_setfsinfo_recv(req, mem_ctx, set_fsinfo);
     431             : }

Generated by: LCOV version 1.14