LCOV - code coverage report
Current view: top level - source3/libsmb - clifsinfo.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 111 332 33.4 %
Date: 2024-06-13 04:01:37 Functions: 8 19 42.1 %

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

Generated by: LCOV version 1.13