LCOV - code coverage report
Current view: top level - source3/libsmb - clifsinfo.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 233 369 63.1 %
Date: 2024-02-28 12:06:22 Functions: 17 19 89.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    FS info functions
       4             :    Copyright (C) Stefan (metze) Metzmacher      2003
       5             :    Copyright (C) Jeremy Allison 2007
       6             :    Copyright (C) Andrew Bartlett 2011
       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 "libsmb/libsmb.h"
      24             : #include "../lib/util/tevent_ntstatus.h"
      25             : #include "async_smb.h"
      26             : #include "trans2.h"
      27             : #include "auth_generic.h"
      28             : #include "auth/gensec/gensec.h"
      29             : #include "../libcli/smb/smbXcli_base.h"
      30             : #include "auth/credentials/credentials.h"
      31             : #include "../librpc/gen_ndr/ndr_security.h"
      32             : 
      33             : /****************************************************************************
      34             :  Get UNIX extensions version info.
      35             : ****************************************************************************/
      36             : 
      37             : struct cli_unix_extensions_version_state {
      38             :         struct cli_state *cli;
      39             :         uint16_t setup[1];
      40             :         uint8_t param[2];
      41             :         uint16_t major, minor;
      42             :         uint32_t caplow, caphigh;
      43             : };
      44             : 
      45             : static void cli_unix_extensions_version_done(struct tevent_req *subreq);
      46             : 
      47         956 : struct tevent_req *cli_unix_extensions_version_send(TALLOC_CTX *mem_ctx,
      48             :                                                     struct tevent_context *ev,
      49             :                                                     struct cli_state *cli)
      50             : {
      51           0 :         struct tevent_req *req, *subreq;
      52           0 :         struct cli_unix_extensions_version_state *state;
      53             : 
      54         956 :         req = tevent_req_create(mem_ctx, &state,
      55             :                                 struct cli_unix_extensions_version_state);
      56         956 :         if (req == NULL) {
      57           0 :                 return NULL;
      58             :         }
      59         956 :         state->cli = cli;
      60         956 :         SSVAL(state->setup, 0, TRANSACT2_QFSINFO);
      61         956 :         SSVAL(state->param, 0, SMB_QUERY_CIFS_UNIX_INFO);
      62             : 
      63         956 :         subreq = cli_trans_send(state, ev, cli, 0, SMBtrans2,
      64             :                                 NULL, 0, 0, 0,
      65         956 :                                 state->setup, 1, 0,
      66         956 :                                 state->param, 2, 0,
      67             :                                 NULL, 0, 560);
      68         956 :         if (tevent_req_nomem(subreq, req)) {
      69           0 :                 return tevent_req_post(req, ev);
      70             :         }
      71         956 :         tevent_req_set_callback(subreq, cli_unix_extensions_version_done, req);
      72         956 :         return req;
      73             : }
      74             : 
      75         956 : static void cli_unix_extensions_version_done(struct tevent_req *subreq)
      76             : {
      77         956 :         struct tevent_req *req = tevent_req_callback_data(
      78             :                 subreq, struct tevent_req);
      79         956 :         struct cli_unix_extensions_version_state *state = tevent_req_data(
      80             :                 req, struct cli_unix_extensions_version_state);
      81           0 :         uint8_t *data;
      82           0 :         uint32_t num_data;
      83           0 :         NTSTATUS status;
      84             : 
      85         956 :         status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
      86             :                                 NULL, 0, NULL, &data, 12, &num_data);
      87         956 :         TALLOC_FREE(subreq);
      88         956 :         if (tevent_req_nterror(req, status)) {
      89           0 :                 return;
      90             :         }
      91             : 
      92         956 :         state->major = SVAL(data, 0);
      93         956 :         state->minor = SVAL(data, 2);
      94         956 :         state->caplow = IVAL(data, 4);
      95         956 :         state->caphigh = IVAL(data, 8);
      96         956 :         TALLOC_FREE(data);
      97         956 :         tevent_req_done(req);
      98             : }
      99             : 
     100         956 : NTSTATUS cli_unix_extensions_version_recv(struct tevent_req *req,
     101             :                                           uint16_t *pmajor, uint16_t *pminor,
     102             :                                           uint32_t *pcaplow,
     103             :                                           uint32_t *pcaphigh)
     104             : {
     105         956 :         struct cli_unix_extensions_version_state *state = tevent_req_data(
     106             :                 req, struct cli_unix_extensions_version_state);
     107           0 :         NTSTATUS status;
     108             : 
     109         956 :         if (tevent_req_is_nterror(req, &status)) {
     110           0 :                 return status;
     111             :         }
     112         956 :         *pmajor = state->major;
     113         956 :         *pminor = state->minor;
     114         956 :         *pcaplow = state->caplow;
     115         956 :         *pcaphigh = state->caphigh;
     116         956 :         state->cli->server_posix_capabilities = *pcaplow;
     117         956 :         return NT_STATUS_OK;
     118             : }
     119             : 
     120         942 : NTSTATUS cli_unix_extensions_version(struct cli_state *cli, uint16_t *pmajor,
     121             :                                      uint16_t *pminor, uint32_t *pcaplow,
     122             :                                      uint32_t *pcaphigh)
     123             : {
     124         942 :         TALLOC_CTX *frame = talloc_stackframe();
     125           0 :         struct tevent_context *ev;
     126           0 :         struct tevent_req *req;
     127         942 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     128             : 
     129         942 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     130             :                 /*
     131             :                  * Can't use sync call while an async call is in flight
     132             :                  */
     133           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     134           0 :                 goto fail;
     135             :         }
     136         942 :         ev = samba_tevent_context_init(frame);
     137         942 :         if (ev == NULL) {
     138           0 :                 goto fail;
     139             :         }
     140         942 :         req = cli_unix_extensions_version_send(frame, ev, cli);
     141         942 :         if (req == NULL) {
     142           0 :                 goto fail;
     143             :         }
     144         942 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     145           0 :                 goto fail;
     146             :         }
     147         942 :         status = cli_unix_extensions_version_recv(req, pmajor, pminor, pcaplow,
     148             :                                                   pcaphigh);
     149         942 :  fail:
     150         942 :         TALLOC_FREE(frame);
     151         942 :         return status;
     152             : }
     153             : 
     154             : /****************************************************************************
     155             :  Set UNIX extensions capabilities.
     156             : ****************************************************************************/
     157             : 
     158             : struct cli_set_unix_extensions_capabilities_state {
     159             :         struct cli_state *cli;
     160             :         uint16_t setup[1];
     161             :         uint8_t param[4];
     162             :         uint8_t data[12];
     163             : };
     164             : 
     165             : static void cli_set_unix_extensions_capabilities_done(
     166             :         struct tevent_req *subreq);
     167             : 
     168         464 : struct tevent_req *cli_set_unix_extensions_capabilities_send(
     169             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
     170             :         uint16_t major, uint16_t minor, uint32_t caplow, uint32_t caphigh)
     171             : {
     172           0 :         struct tevent_req *req, *subreq;
     173           0 :         struct cli_set_unix_extensions_capabilities_state *state;
     174             : 
     175         464 :         req = tevent_req_create(
     176             :                 mem_ctx, &state,
     177             :                 struct cli_set_unix_extensions_capabilities_state);
     178         464 :         if (req == NULL) {
     179           0 :                 return NULL;
     180             :         }
     181             : 
     182         464 :         state->cli = cli;
     183         464 :         SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
     184             : 
     185         464 :         SSVAL(state->param, 0, 0);
     186         464 :         SSVAL(state->param, 2, SMB_SET_CIFS_UNIX_INFO);
     187             : 
     188         464 :         SSVAL(state->data, 0, major);
     189         464 :         SSVAL(state->data, 2, minor);
     190         464 :         SIVAL(state->data, 4, caplow);
     191         464 :         SIVAL(state->data, 8, caphigh);
     192             : 
     193         464 :         subreq = cli_trans_send(state, ev, cli, 0, SMBtrans2,
     194             :                                 NULL, 0, 0, 0,
     195         464 :                                 state->setup, 1, 0,
     196         464 :                                 state->param, 4, 0,
     197         464 :                                 state->data, 12, 560);
     198         464 :         if (tevent_req_nomem(subreq, req)) {
     199           0 :                 return tevent_req_post(req, ev);
     200             :         }
     201         464 :         tevent_req_set_callback(
     202             :                 subreq, cli_set_unix_extensions_capabilities_done, req);
     203         464 :         return req;
     204             : }
     205             : 
     206         464 : static void cli_set_unix_extensions_capabilities_done(
     207             :         struct tevent_req *subreq)
     208             : {
     209         464 :         struct tevent_req *req = tevent_req_callback_data(
     210             :                 subreq, struct tevent_req);
     211         464 :         struct cli_set_unix_extensions_capabilities_state *state = tevent_req_data(
     212             :                 req, struct cli_set_unix_extensions_capabilities_state);
     213             : 
     214         464 :         NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     215             :                                          NULL, 0, NULL, NULL, 0, NULL);
     216         464 :         if (NT_STATUS_IS_OK(status)) {
     217         464 :                 state->cli->requested_posix_capabilities = IVAL(state->data, 4);
     218             :         }
     219         464 :         tevent_req_simple_finish_ntstatus(subreq, status);
     220         464 : }
     221             : 
     222         464 : NTSTATUS cli_set_unix_extensions_capabilities_recv(struct tevent_req *req)
     223             : {
     224         464 :         return tevent_req_simple_recv_ntstatus(req);
     225             : }
     226             : 
     227         452 : NTSTATUS cli_set_unix_extensions_capabilities(struct cli_state *cli,
     228             :                                               uint16_t major, uint16_t minor,
     229             :                                               uint32_t caplow, uint32_t caphigh)
     230             : {
     231           0 :         struct tevent_context *ev;
     232           0 :         struct tevent_req *req;
     233         452 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     234             : 
     235         452 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     236           0 :                 return NT_STATUS_INVALID_PARAMETER;
     237             :         }
     238         452 :         ev = samba_tevent_context_init(talloc_tos());
     239         452 :         if (ev == NULL) {
     240           0 :                 goto fail;
     241             :         }
     242         452 :         req = cli_set_unix_extensions_capabilities_send(
     243             :                 ev, ev, cli, major, minor, caplow, caphigh);
     244         452 :         if (req == NULL) {
     245           0 :                 goto fail;
     246             :         }
     247         452 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     248           0 :                 goto fail;
     249             :         }
     250         452 :         status = cli_set_unix_extensions_capabilities_recv(req);
     251         452 : fail:
     252         452 :         TALLOC_FREE(ev);
     253         452 :         return status;
     254             : }
     255             : 
     256             : struct cli_get_fs_attr_info_state {
     257             :         uint16_t setup[1];
     258             :         uint8_t param[2];
     259             :         uint32_t fs_attr;
     260             : };
     261             : 
     262             : static void cli_get_fs_attr_info_done(struct tevent_req *subreq);
     263             : 
     264          24 : struct tevent_req *cli_get_fs_attr_info_send(TALLOC_CTX *mem_ctx,
     265             :                                              struct tevent_context *ev,
     266             :                                              struct cli_state *cli)
     267             : {
     268           0 :         struct tevent_req *subreq, *req;
     269           0 :         struct cli_get_fs_attr_info_state *state;
     270             : 
     271          24 :         req = tevent_req_create(mem_ctx, &state,
     272             :                                 struct cli_get_fs_attr_info_state);
     273          24 :         if (req == NULL) {
     274           0 :                 return NULL;
     275             :         }
     276          24 :         SSVAL(state->setup+0, 0, TRANSACT2_QFSINFO);
     277          24 :         SSVAL(state->param+0, 0, SMB_QUERY_FS_ATTRIBUTE_INFO);
     278             : 
     279          24 :         subreq = cli_trans_send(state, ev, cli, 0, SMBtrans2,
     280             :                                 NULL, 0, 0, 0,
     281          24 :                                 state->setup, 1, 0,
     282          24 :                                 state->param, 2, 0,
     283             :                                 NULL, 0, 560);
     284          24 :         if (tevent_req_nomem(subreq, req)) {
     285           0 :                 return tevent_req_post(req, ev);
     286             :         }
     287          24 :         tevent_req_set_callback(subreq, cli_get_fs_attr_info_done, req);
     288          24 :         return req;
     289             : }
     290             : 
     291          24 : static void cli_get_fs_attr_info_done(struct tevent_req *subreq)
     292             : {
     293          24 :         struct tevent_req *req = tevent_req_callback_data(
     294             :                 subreq, struct tevent_req);
     295          24 :         struct cli_get_fs_attr_info_state *state = tevent_req_data(
     296             :                 req, struct cli_get_fs_attr_info_state);
     297           0 :         uint8_t *data;
     298           0 :         uint32_t num_data;
     299           0 :         NTSTATUS status;
     300             : 
     301          24 :         status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL, 0, NULL,
     302             :                                 NULL, 0, NULL, &data, 12, &num_data);
     303          24 :         TALLOC_FREE(subreq);
     304          24 :         if (tevent_req_nterror(req, status)) {
     305           0 :                 return;
     306             :         }
     307          24 :         state->fs_attr = IVAL(data, 0);
     308          24 :         TALLOC_FREE(data);
     309          24 :         tevent_req_done(req);
     310             : }
     311             : 
     312          24 : NTSTATUS cli_get_fs_attr_info_recv(struct tevent_req *req, uint32_t *fs_attr)
     313             : {
     314          24 :         struct cli_get_fs_attr_info_state *state = tevent_req_data(
     315             :                 req, struct cli_get_fs_attr_info_state);
     316           0 :         NTSTATUS status;
     317             : 
     318          24 :         if (tevent_req_is_nterror(req, &status)) {
     319           0 :                 return status;
     320             :         }
     321          24 :         *fs_attr = state->fs_attr;
     322          24 :         return NT_STATUS_OK;
     323             : }
     324             : 
     325         110 : NTSTATUS cli_get_fs_attr_info(struct cli_state *cli, uint32_t *fs_attr)
     326             : {
     327           0 :         struct tevent_context *ev;
     328           0 :         struct tevent_req *req;
     329         110 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     330             : 
     331         110 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     332          86 :                 return cli_smb2_get_fs_attr_info(cli, fs_attr);
     333             :         }
     334             : 
     335          24 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     336           0 :                 return NT_STATUS_INVALID_PARAMETER;
     337             :         }
     338          24 :         ev = samba_tevent_context_init(talloc_tos());
     339          24 :         if (ev == NULL) {
     340           0 :                 goto fail;
     341             :         }
     342          24 :         req = cli_get_fs_attr_info_send(ev, ev, cli);
     343          24 :         if (req == NULL) {
     344           0 :                 goto fail;
     345             :         }
     346          24 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     347           0 :                 goto fail;
     348             :         }
     349          24 :         status = cli_get_fs_attr_info_recv(req, fs_attr);
     350          24 : fail:
     351          24 :         TALLOC_FREE(ev);
     352          24 :         return status;
     353             : }
     354             : 
     355          23 : NTSTATUS cli_get_fs_volume_info(struct cli_state *cli,
     356             :                                 TALLOC_CTX *mem_ctx,
     357             :                                 char **_volume_name,
     358             :                                 uint32_t *pserial_number,
     359             :                                 time_t *pdate)
     360             : {
     361           0 :         NTSTATUS status;
     362           0 :         uint16_t recv_flags2;
     363           0 :         uint16_t setup[1];
     364           0 :         uint8_t param[2];
     365           0 :         uint8_t *rdata;
     366           0 :         uint32_t rdata_count;
     367           0 :         unsigned int nlen;
     368          23 :         char *volume_name = NULL;
     369             : 
     370          23 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     371          17 :                 return cli_smb2_get_fs_volume_info(cli,
     372             :                                                 mem_ctx,
     373             :                                                 _volume_name,
     374             :                                                 pserial_number,
     375             :                                                 pdate);
     376             :         }
     377             : 
     378           6 :         SSVAL(setup, 0, TRANSACT2_QFSINFO);
     379           6 :         SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO);
     380             : 
     381           6 :         status = cli_trans(talloc_tos(), cli, SMBtrans2,
     382             :                            NULL, 0, 0, 0,
     383             :                            setup, 1, 0,
     384             :                            param, 2, 0,
     385             :                            NULL, 0, 560,
     386             :                            &recv_flags2,
     387             :                            NULL, 0, NULL,
     388             :                            NULL, 0, NULL,
     389             :                            &rdata, 18, &rdata_count);
     390           6 :         if (!NT_STATUS_IS_OK(status)) {
     391           0 :                 return status;
     392             :         }
     393             : 
     394           6 :         if (pdate) {
     395           0 :                 struct timespec ts;
     396           6 :                 ts = interpret_long_date(BVAL(rdata, 0));
     397           6 :                 *pdate = ts.tv_sec;
     398             :         }
     399           6 :         if (pserial_number) {
     400           6 :                 *pserial_number = IVAL(rdata,8);
     401             :         }
     402           6 :         nlen = IVAL(rdata,12);
     403           6 :         if (nlen > (rdata_count - 18)) {
     404           0 :                 TALLOC_FREE(rdata);
     405           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     406             :         }
     407             : 
     408           6 :         pull_string_talloc(mem_ctx,
     409             :                            (const char *)rdata,
     410             :                            recv_flags2,
     411             :                            &volume_name,
     412           6 :                            rdata + 18,
     413             :                            nlen, STR_UNICODE);
     414           6 :         if (volume_name == NULL) {
     415           0 :                 status = map_nt_error_from_unix(errno);
     416           0 :                 TALLOC_FREE(rdata);
     417           0 :                 return status;
     418             :         }
     419             : 
     420             :         /* todo: but not yet needed
     421             :          *       return the other stuff
     422             :          */
     423             : 
     424           6 :         *_volume_name = volume_name;
     425           6 :         TALLOC_FREE(rdata);
     426           6 :         return NT_STATUS_OK;
     427             : }
     428             : 
     429         296 : NTSTATUS cli_get_fs_full_size_info(struct cli_state *cli,
     430             :                                    uint64_t *total_allocation_units,
     431             :                                    uint64_t *caller_allocation_units,
     432             :                                    uint64_t *actual_allocation_units,
     433             :                                    uint64_t *sectors_per_allocation_unit,
     434             :                                    uint64_t *bytes_per_sector)
     435             : {
     436           0 :         uint16_t setup[1];
     437           0 :         uint8_t param[2];
     438         296 :         uint8_t *rdata = NULL;
     439           0 :         uint32_t rdata_count;
     440           0 :         NTSTATUS status;
     441             : 
     442         296 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     443           0 :                 return cli_smb2_get_fs_full_size_info(cli,
     444             :                                                 total_allocation_units,
     445             :                                                 caller_allocation_units,
     446             :                                                 actual_allocation_units,
     447             :                                                 sectors_per_allocation_unit,
     448             :                                                 bytes_per_sector);
     449             :         }
     450             : 
     451         296 :         SSVAL(setup, 0, TRANSACT2_QFSINFO);
     452         296 :         SSVAL(param, 0, SMB_FS_FULL_SIZE_INFORMATION);
     453             : 
     454         296 :         status = cli_trans(talloc_tos(), cli, SMBtrans2,
     455             :                            NULL, 0, 0, 0,
     456             :                            setup, 1, 0, /* setup */
     457             :                            param, 2, 0,  /* param */
     458             :                            NULL, 0, 560, /* data */
     459             :                            NULL,
     460             :                            NULL, 0, NULL, /* rsetup */
     461             :                            NULL, 0, NULL, /* rparam */
     462             :                            &rdata, 32, &rdata_count);  /* rdata */
     463         296 :         if (!NT_STATUS_IS_OK(status)) {
     464           0 :                 goto fail;
     465             :         }
     466             : 
     467         296 :         if (total_allocation_units) {
     468         296 :                 *total_allocation_units = BIG_UINT(rdata, 0);
     469             :         }
     470         296 :         if (caller_allocation_units) {
     471         296 :                 *caller_allocation_units = BIG_UINT(rdata,8);
     472             :         }
     473         296 :         if (actual_allocation_units) {
     474           0 :                 *actual_allocation_units = BIG_UINT(rdata,16);
     475             :         }
     476         296 :         if (sectors_per_allocation_unit) {
     477         296 :                 *sectors_per_allocation_unit = IVAL(rdata,24);
     478             :         }
     479         296 :         if (bytes_per_sector) {
     480         296 :                 *bytes_per_sector = IVAL(rdata,28);
     481             :         }
     482             : 
     483           0 : fail:
     484         296 :         TALLOC_FREE(rdata);
     485         296 :         return status;
     486             : }
     487             : 
     488           0 : NTSTATUS cli_get_posix_fs_info(struct cli_state *cli,
     489             :                                uint32_t *optimal_transfer_size,
     490             :                                uint32_t *block_size,
     491             :                                uint64_t *total_blocks,
     492             :                                uint64_t *blocks_available,
     493             :                                uint64_t *user_blocks_available,
     494             :                                uint64_t *total_file_nodes,
     495             :                                uint64_t *free_file_nodes,
     496             :                                uint64_t *fs_identifier)
     497             : {
     498           0 :         uint16_t setup[1];
     499           0 :         uint8_t param[2];
     500           0 :         uint8_t *rdata = NULL;
     501           0 :         uint32_t rdata_count;
     502           0 :         NTSTATUS status;
     503             : 
     504           0 :         SSVAL(setup, 0, TRANSACT2_QFSINFO);
     505           0 :         SSVAL(param,0,SMB_QUERY_POSIX_FS_INFO);
     506             : 
     507           0 :         status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0, 0, 0,
     508             :                            setup, 1, 0,
     509             :                            param, 2, 0,
     510             :                            NULL, 0, 560,
     511             :                            NULL,
     512             :                            NULL, 0, NULL, /* rsetup */
     513             :                            NULL, 0, NULL, /* rparam */
     514             :                            &rdata, 56, &rdata_count);
     515           0 :         if (!NT_STATUS_IS_OK(status)) {
     516           0 :                 return status;
     517             :         }
     518             : 
     519           0 :         if (optimal_transfer_size) {
     520           0 :                 *optimal_transfer_size = IVAL(rdata, 0);
     521             :         }
     522           0 :         if (block_size) {
     523           0 :                 *block_size = IVAL(rdata,4);
     524             :         }
     525           0 :         if (total_blocks) {
     526           0 :                 *total_blocks = BIG_UINT(rdata,8);
     527             :         }
     528           0 :         if (blocks_available) {
     529           0 :                 *blocks_available = BIG_UINT(rdata,16);
     530             :         }
     531           0 :         if (user_blocks_available) {
     532           0 :                 *user_blocks_available = BIG_UINT(rdata,24);
     533             :         }
     534           0 :         if (total_file_nodes) {
     535           0 :                 *total_file_nodes = BIG_UINT(rdata,32);
     536             :         }
     537           0 :         if (free_file_nodes) {
     538           0 :                 *free_file_nodes = BIG_UINT(rdata,40);
     539             :         }
     540           0 :         if (fs_identifier) {
     541           0 :                 *fs_identifier = BIG_UINT(rdata,48);
     542             :         }
     543           0 :         return NT_STATUS_OK;
     544             : }
     545             : 
     546             : /****************************************************************************
     547             :  Do a UNIX extensions SMB_QUERY_POSIX_WHOAMI call.
     548             : ****************************************************************************/
     549             : 
     550             : struct posix_whoami_state {
     551             :         uint16_t setup[1];
     552             :         uint8_t param[2];
     553             :         uint32_t max_rdata;
     554             :         bool guest;
     555             :         uint64_t uid;
     556             :         uint64_t gid;
     557             :         uint32_t num_gids;
     558             :         uint64_t *gids;
     559             :         uint32_t num_sids;
     560             :         struct dom_sid *sids;
     561             : };
     562             : 
     563             : static void cli_posix_whoami_done(struct tevent_req *subreq);
     564             : 
     565             : static const uint32_t posix_whoami_max_rdata = 62*1024;
     566             : 
     567          12 : struct tevent_req *cli_posix_whoami_send(TALLOC_CTX *mem_ctx,
     568             :                                         struct tevent_context *ev,
     569             :                                         struct cli_state *cli)
     570             : {
     571          12 :         struct tevent_req *req = NULL, *subreq = NULL;
     572          12 :         struct posix_whoami_state *state = NULL;
     573             : 
     574          12 :         req = tevent_req_create(mem_ctx, &state, struct posix_whoami_state);
     575          12 :         if (req == NULL) {
     576           0 :                 return NULL;
     577             :         }
     578             : 
     579             :         /* Setup setup word. */
     580          12 :         SSVAL(state->setup, 0, TRANSACT2_QFSINFO);
     581          12 :         SSVAL(state->param, 0, SMB_QUERY_POSIX_WHOAMI);
     582             : 
     583          12 :         state->max_rdata = posix_whoami_max_rdata;
     584             : 
     585          12 :         subreq = cli_trans_send(state,                  /* mem ctx. */
     586             :                                 ev,                     /* event ctx. */
     587             :                                 cli,                    /* cli_state. */
     588             :                                 0,                      /* additional_flags2 */
     589             :                                 SMBtrans2,              /* cmd. */
     590             :                                 NULL,                   /* pipe name. */
     591             :                                 -1,                     /* fid. */
     592             :                                 0,                      /* function. */
     593             :                                 0,                      /* flags. */
     594          12 :                                 state->setup,           /* setup. */
     595             :                                 1,                      /* num setup uint16_t words. */
     596             :                                 0,                      /* max returned setup. */
     597          12 :                                 state->param,           /* param. */
     598             :                                 2,                      /* num param. */
     599             :                                 0,                      /* max returned param. */
     600             :                                 NULL,                   /* data. */
     601             :                                 0,                      /* num data. */
     602          12 :                                 state->max_rdata);      /* max returned data. */
     603             : 
     604          12 :         if (tevent_req_nomem(subreq, req)) {
     605           0 :                 return tevent_req_post(req, ev);
     606             :         }
     607          12 :         tevent_req_set_callback(subreq, cli_posix_whoami_done, req);
     608          12 :         return req;
     609             : }
     610             : 
     611          12 : static void cli_posix_whoami_done(struct tevent_req *subreq)
     612             : {
     613          12 :         struct tevent_req *req = tevent_req_callback_data(
     614             :                         subreq, struct tevent_req);
     615          12 :         struct posix_whoami_state *state = tevent_req_data(
     616             :                         req, struct posix_whoami_state);
     617          12 :         uint8_t *rdata = NULL;
     618          12 :         uint8_t *p = NULL;
     619          12 :         uint32_t num_rdata = 0;
     620           0 :         uint32_t i;
     621           0 :         NTSTATUS status;
     622             : 
     623          12 :         status = cli_trans_recv(subreq,
     624             :                                 state,
     625             :                                 NULL,
     626             :                                 NULL,
     627             :                                 0,
     628             :                                 NULL,
     629             :                                 NULL,
     630             :                                 0,
     631             :                                 NULL,
     632             :                                 &rdata,
     633             :                                 40,
     634             :                                 &num_rdata);
     635          12 :         TALLOC_FREE(subreq);
     636          12 :         if (tevent_req_nterror(req, status)) {
     637           0 :                 return;
     638             :         }
     639             : 
     640             :         /*
     641             :          * Not strictly needed - cli_trans_recv()
     642             :          * will ensure at least 40 bytes here. Added
     643             :          * as more of a reminder to be careful when
     644             :          * parsing network packets in C.
     645             :          */
     646             : 
     647          12 :         if (num_rdata < 40 || num_rdata > posix_whoami_max_rdata) {
     648           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     649           0 :                 return;
     650             :         }
     651             : 
     652          12 :         state->guest = (IVAL(rdata, 0) & SMB_WHOAMI_GUEST);
     653          12 :         state->uid = BVAL(rdata, 8);
     654          12 :         state->gid = BVAL(rdata, 16);
     655          12 :         state->num_gids = IVAL(rdata, 24);
     656          12 :         state->num_sids = IVAL(rdata, 28);
     657             : 
     658             :         /* Ensure the gid array doesn't overflow */
     659          12 :         if (state->num_gids > (num_rdata - 40) / sizeof(uint64_t)) {
     660           0 :                 tevent_req_nterror(req,
     661             :                         NT_STATUS_INVALID_NETWORK_RESPONSE);
     662           0 :                 return;
     663             :         }
     664             : 
     665          12 :         state->gids = talloc_array(state, uint64_t, state->num_gids);
     666          12 :         if (tevent_req_nomem(state->gids, req)) {
     667           0 :                 return;
     668             :         }
     669          12 :         state->sids = talloc_array(state, struct dom_sid, state->num_sids);
     670          12 :         if (tevent_req_nomem(state->sids, req)) {
     671           0 :                 return;
     672             :         }
     673             : 
     674          12 :         p = rdata + 40;
     675             : 
     676          82 :         for (i = 0; i < state->num_gids; i++) {
     677          70 :                 state->gids[i] = BVAL(p, 0);
     678          70 :                 p += 8;
     679             :         }
     680             : 
     681          12 :         num_rdata -= (p - rdata);
     682             : 
     683         136 :         for (i = 0; i < state->num_sids; i++) {
     684           0 :                 size_t sid_size;
     685         124 :                 DATA_BLOB in = data_blob_const(p, num_rdata);
     686           0 :                 enum ndr_err_code ndr_err;
     687             : 
     688         124 :                 ndr_err = ndr_pull_struct_blob(&in,
     689             :                                 state,
     690         124 :                                 &state->sids[i],
     691             :                                 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
     692         124 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     693           0 :                         tevent_req_nterror(req,
     694             :                                 NT_STATUS_INVALID_NETWORK_RESPONSE);
     695           0 :                         return;
     696             :                 }
     697             : 
     698         124 :                 sid_size = ndr_size_dom_sid(&state->sids[i], 0);
     699             : 
     700         124 :                 if (sid_size > num_rdata) {
     701           0 :                         tevent_req_nterror(req,
     702             :                                 NT_STATUS_INVALID_NETWORK_RESPONSE);
     703           0 :                         return;
     704             :                 }
     705             : 
     706         124 :                 p += sid_size;
     707         124 :                 num_rdata -= sid_size;
     708             :         }
     709             : 
     710          12 :         if (num_rdata != 0) {
     711           0 :                 tevent_req_nterror(req,
     712             :                         NT_STATUS_INVALID_NETWORK_RESPONSE);
     713           0 :                 return;
     714             :         }
     715             : 
     716          12 :         tevent_req_done(req);
     717             : }
     718             : 
     719          12 : NTSTATUS cli_posix_whoami_recv(struct tevent_req *req,
     720             :                         TALLOC_CTX *mem_ctx,
     721             :                         uint64_t *puid,
     722             :                         uint64_t *pgid,
     723             :                         uint32_t *pnum_gids,
     724             :                         uint64_t **pgids,
     725             :                         uint32_t *pnum_sids,
     726             :                         struct dom_sid **psids,
     727             :                         bool *pguest)
     728             : {
     729           0 :         NTSTATUS status;
     730          12 :         struct posix_whoami_state *state = tevent_req_data(
     731             :                         req, struct posix_whoami_state);
     732             : 
     733          12 :         if (tevent_req_is_nterror(req, &status)) {
     734           0 :                 return status;
     735             :         }
     736             : 
     737          12 :         if (puid) {
     738          12 :                 *puid = state->uid;
     739             :         }
     740          12 :         if (pgid) {
     741          12 :                 *pgid = state->gid;
     742             :         }
     743          12 :         if (pnum_gids) {
     744          12 :                 *pnum_gids = state->num_gids;
     745             :         }
     746          12 :         if (pgids) {
     747          12 :                 *pgids = talloc_move(mem_ctx, &state->gids);
     748             :         }
     749          12 :         if (pnum_sids) {
     750          12 :                 *pnum_sids = state->num_sids;
     751             :         }
     752          12 :         if (psids) {
     753          12 :                 *psids = talloc_move(mem_ctx, &state->sids);
     754             :         }
     755          12 :         if (pguest) {
     756          12 :                 *pguest = state->guest;
     757             :         }
     758          12 :         return NT_STATUS_OK;
     759             : }
     760             : 
     761           0 : NTSTATUS cli_posix_whoami(struct cli_state *cli,
     762             :                         TALLOC_CTX *mem_ctx,
     763             :                         uint64_t *puid,
     764             :                         uint64_t *pgid,
     765             :                         uint32_t *num_gids,
     766             :                         uint64_t **gids,
     767             :                         uint32_t *num_sids,
     768             :                         struct dom_sid **sids,
     769             :                         bool *pguest)
     770             : {
     771           0 :         TALLOC_CTX *frame = talloc_stackframe();
     772           0 :         struct tevent_context *ev = NULL;
     773           0 :         struct tevent_req *req = NULL;
     774           0 :         NTSTATUS status = NT_STATUS_OK;
     775             : 
     776           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     777             :                 /*
     778             :                  * Can't use sync call while an async call is in flight
     779             :                  */
     780           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     781           0 :                 goto fail;
     782             :         }
     783             : 
     784           0 :         ev = samba_tevent_context_init(frame);
     785           0 :         if (ev == NULL) {
     786           0 :                 status = NT_STATUS_NO_MEMORY;
     787           0 :                 goto fail;
     788             :         }
     789             : 
     790           0 :         req = cli_posix_whoami_send(frame,
     791             :                                 ev,
     792             :                                 cli);
     793           0 :         if (req == NULL) {
     794           0 :                 status = NT_STATUS_NO_MEMORY;
     795           0 :                 goto fail;
     796             :         }
     797             : 
     798           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     799           0 :                 goto fail;
     800             :         }
     801             : 
     802           0 :         status = cli_posix_whoami_recv(req,
     803             :                         mem_ctx,
     804             :                         puid,
     805             :                         pgid,
     806             :                         num_gids,
     807             :                         gids,
     808             :                         num_sids,
     809             :                         sids,
     810             :                         pguest);
     811             : 
     812           0 :  fail:
     813           0 :         TALLOC_FREE(frame);
     814           0 :         return status;
     815             : }

Generated by: LCOV version 1.14