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

Generated by: LCOV version 1.14