Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/libsmb/clitrans.c

    r746 r988  
    2222#include "../lib/util/tevent_ntstatus.h"
    2323#include "async_smb.h"
    24 
    25 struct trans_recvblob {
    26         uint8_t *data;
    27         uint32_t max, total, received;
    28 };
     24#include "../libcli/smb/smbXcli_base.h"
    2925
    3026struct cli_trans_state {
    3127        struct cli_state *cli;
    32         struct event_context *ev;
    33         uint8_t cmd;
    34         uint16_t mid;
    35         const char *pipe_name;
    36         uint8_t *pipe_name_conv;
    37         size_t pipe_name_conv_len;
    38         uint16_t fid;
    39         uint16_t function;
    40         int flags;
    41         uint16_t *setup;
    42         uint8_t num_setup, max_setup;
    43         uint8_t *param;
    44         uint32_t num_param, param_sent;
    45         uint8_t *data;
    46         uint32_t num_data, data_sent;
    47 
    48         uint8_t num_rsetup;
    49         uint16_t *rsetup;
    50         struct trans_recvblob rparam;
    51         struct trans_recvblob rdata;
    52         uint16_t recv_flags2;
    53 
    54         struct iovec iov[6];
    55         uint8_t pad[4];
    56         uint8_t zero_pad[4];
    57         uint16_t vwv[32];
    58 
    59         struct tevent_req *primary_subreq;
     28        struct tevent_req *req;
     29        struct cli_trans_state **ptr;
    6030};
    61 
    62 static void cli_trans_cleanup_primary(struct cli_trans_state *state)
    63 {
    64         if (state->primary_subreq) {
    65                 cli_smb_req_set_mid(state->primary_subreq, 0);
    66                 cli_smb_req_unset_pending(state->primary_subreq);
    67                 TALLOC_FREE(state->primary_subreq);
    68         }
    69 }
    7031
    7132static int cli_trans_state_destructor(struct cli_trans_state *state)
    7233{
    73         cli_trans_cleanup_primary(state);
     34        talloc_set_destructor(state->ptr, NULL);
     35        talloc_free(state->ptr);
    7436        return 0;
    7537}
    7638
    77 static NTSTATUS cli_pull_trans(uint8_t *inbuf,
    78                                uint8_t wct, uint16_t *vwv,
    79                                uint16_t num_bytes, uint8_t *bytes,
    80                                uint8_t smb_cmd, bool expect_first_reply,
    81                                uint8_t *pnum_setup, uint16_t **psetup,
    82                                uint32_t *ptotal_param, uint32_t *pnum_param,
    83                                uint32_t *pparam_disp, uint8_t **pparam,
    84                                uint32_t *ptotal_data, uint32_t *pnum_data,
    85                                uint32_t *pdata_disp, uint8_t **pdata)
     39static int cli_trans_state_ptr_destructor(struct cli_trans_state **ptr)
    8640{
    87         uint32_t param_ofs, data_ofs;
     41        struct cli_trans_state *state = *ptr;
     42        void *parent = talloc_parent(state);
    8843
    89         if (expect_first_reply) {
    90                 if ((wct != 0) || (num_bytes != 0)) {
    91                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    92                 }
    93                 return NT_STATUS_OK;
    94         }
     44        talloc_set_destructor(state, NULL);
    9545
    96         switch (smb_cmd) {
    97         case SMBtrans:
    98         case SMBtrans2:
    99                 if (wct < 10) {
    100                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    101                 }
    102                 *ptotal_param   = SVAL(vwv + 0, 0);
    103                 *ptotal_data    = SVAL(vwv + 1, 0);
    104                 *pnum_param     = SVAL(vwv + 3, 0);
    105                 param_ofs       = SVAL(vwv + 4, 0);
    106                 *pparam_disp    = SVAL(vwv + 5, 0);
    107                 *pnum_data      = SVAL(vwv + 6, 0);
    108                 data_ofs        = SVAL(vwv + 7, 0);
    109                 *pdata_disp     = SVAL(vwv + 8, 0);
    110                 *pnum_setup     = CVAL(vwv + 9, 0);
    111                 if (wct < 10 + (*pnum_setup)) {
    112                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    113                 }
    114                 *psetup = vwv + 10;
    115 
    116                 break;
    117         case SMBnttrans:
    118                 if (wct < 18) {
    119                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    120                 }
    121                 *ptotal_param   = IVAL(vwv, 3);
    122                 *ptotal_data    = IVAL(vwv, 7);
    123                 *pnum_param     = IVAL(vwv, 11);
    124                 param_ofs       = IVAL(vwv, 15);
    125                 *pparam_disp    = IVAL(vwv, 19);
    126                 *pnum_data      = IVAL(vwv, 23);
    127                 data_ofs        = IVAL(vwv, 27);
    128                 *pdata_disp     = IVAL(vwv, 31);
    129                 *pnum_setup     = CVAL(vwv, 35);
    130                 *psetup         = vwv + 18;
    131                 break;
    132 
    133         default:
    134                 return NT_STATUS_INTERNAL_ERROR;
    135         }
    136 
    137         /*
    138          * Check for buffer overflows. data_ofs needs to be checked against
    139          * the incoming buffer length, data_disp against the total
    140          * length. Likewise for param_ofs/param_disp.
    141          */
    142 
    143         if (trans_oob(smb_len(inbuf), param_ofs, *pnum_param)
    144             || trans_oob(*ptotal_param, *pparam_disp, *pnum_param)
    145             || trans_oob(smb_len(inbuf), data_ofs, *pnum_data)
    146             || trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) {
    147                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    148         }
    149 
    150         *pparam = (uint8_t *)inbuf + 4 + param_ofs;
    151         *pdata = (uint8_t *)inbuf + 4 + data_ofs;
    152 
    153         return NT_STATUS_OK;
     46        talloc_reparent(state, parent, state->req);
     47        talloc_free(state);
     48        return 0;
    15449}
    15550
    156 static NTSTATUS cli_trans_pull_blob(TALLOC_CTX *mem_ctx,
    157                                     struct trans_recvblob *blob,
    158                                     uint32_t total, uint32_t thistime,
    159                                     uint8_t *buf, uint32_t displacement)
    160 {
    161         if (blob->data == NULL) {
    162                 if (total > blob->max) {
    163                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    164                 }
    165                 blob->total = total;
    166                 blob->data = TALLOC_ARRAY(mem_ctx, uint8_t, total);
    167                 if (blob->data == NULL) {
    168                         return NT_STATUS_NO_MEMORY;
    169                 }
    170         }
    171 
    172         if (total > blob->total) {
    173                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    174         }
    175 
    176         if (thistime) {
    177                 memcpy(blob->data + displacement, buf, thistime);
    178                 blob->received += thistime;
    179         }
    180 
    181         return NT_STATUS_OK;
    182 }
    183 
    184 static void cli_trans_format(struct cli_trans_state *state, uint8_t *pwct,
    185                              int *piov_count)
    186 {
    187         uint8_t wct = 0;
    188         struct iovec *iov = state->iov;
    189         uint8_t *pad = state->pad;
    190         uint16_t *vwv = state->vwv;
    191         uint32_t param_offset;
    192         uint32_t this_param = 0;
    193         uint32_t param_pad;
    194         uint32_t data_offset;
    195         uint32_t this_data = 0;
    196         uint32_t data_pad;
    197         uint32_t useable_space;
    198         uint8_t cmd;
    199 
    200         cmd = state->cmd;
    201 
    202         if ((state->param_sent != 0) || (state->data_sent != 0)) {
    203                 /* The secondary commands are one after the primary ones */
    204                 cmd += 1;
    205         }
    206 
    207         param_offset = smb_size - 4;
    208 
    209         switch (cmd) {
    210         case SMBtrans:
    211                 if (cli_ucs2(state->cli)) {
    212                         pad[0] = 0;
    213                         iov[0].iov_base = (void *)pad;
    214                         iov[0].iov_len = 1;
    215                         param_offset += 1;
    216                         iov += 1;
    217                 }
    218                 iov[0].iov_base = (void *)state->pipe_name_conv;
    219                 iov[0].iov_len = state->pipe_name_conv_len;
    220                 wct = 14 + state->num_setup;
    221                 param_offset += iov[0].iov_len;
    222                 iov += 1;
    223                 break;
    224         case SMBtrans2:
    225                 pad[0] = 0;
    226                 pad[1] = 'D'; /* Copy this from "old" 3.0 behaviour */
    227                 pad[2] = ' ';
    228                 iov[0].iov_base = (void *)pad;
    229                 iov[0].iov_len = 3;
    230                 wct = 14 + state->num_setup;
    231                 param_offset += 3;
    232                 iov += 1;
    233                 break;
    234         case SMBtranss:
    235                 wct = 8;
    236                 break;
    237         case SMBtranss2:
    238                 wct = 9;
    239                 break;
    240         case SMBnttrans:
    241                 wct = 19 + state->num_setup;
    242                 break;
    243         case SMBnttranss:
    244                 wct = 18;
    245                 break;
    246         }
    247 
    248         param_offset += wct * sizeof(uint16_t);
    249         useable_space = state->cli->max_xmit - param_offset;
    250 
    251         param_pad = param_offset % 4;
    252         if (param_pad > 0) {
    253                 param_pad = MIN(param_pad, useable_space);
    254                 iov[0].iov_base = (void *)state->zero_pad;
    255                 iov[0].iov_len = param_pad;
    256                 iov += 1;
    257                 param_offset += param_pad;
    258         }
    259         useable_space = state->cli->max_xmit - param_offset;
    260 
    261         if (state->param_sent < state->num_param) {
    262                 this_param = MIN(state->num_param - state->param_sent,
    263                                  useable_space);
    264                 iov[0].iov_base = (void *)(state->param + state->param_sent);
    265                 iov[0].iov_len = this_param;
    266                 iov += 1;
    267         }
    268 
    269         data_offset = param_offset + this_param;
    270         useable_space = state->cli->max_xmit - data_offset;
    271 
    272         data_pad = data_offset % 4;
    273         if (data_pad > 0) {
    274                 data_pad = MIN(data_pad, useable_space);
    275                 iov[0].iov_base = (void *)state->zero_pad;
    276                 iov[0].iov_len = data_pad;
    277                 iov += 1;
    278                 data_offset += data_pad;
    279         }
    280         useable_space = state->cli->max_xmit - data_offset;
    281 
    282         if (state->data_sent < state->num_data) {
    283                 this_data = MIN(state->num_data - state->data_sent,
    284                                 useable_space);
    285                 iov[0].iov_base = (void *)(state->data + state->data_sent);
    286                 iov[0].iov_len = this_data;
    287                 iov += 1;
    288         }
    289 
    290         DEBUG(10, ("num_setup=%u, max_setup=%u, "
    291                    "param_total=%u, this_param=%u, max_param=%u, "
    292                    "data_total=%u, this_data=%u, max_data=%u, "
    293                    "param_offset=%u, param_pad=%u, param_disp=%u, "
    294                    "data_offset=%u, data_pad=%u, data_disp=%u\n",
    295                    (unsigned)state->num_setup, (unsigned)state->max_setup,
    296                    (unsigned)state->num_param, (unsigned)this_param,
    297                    (unsigned)state->rparam.max,
    298                    (unsigned)state->num_data, (unsigned)this_data,
    299                    (unsigned)state->rdata.max,
    300                    (unsigned)param_offset, (unsigned)param_pad,
    301                    (unsigned)state->param_sent,
    302                    (unsigned)data_offset, (unsigned)data_pad,
    303                    (unsigned)state->data_sent));
    304 
    305         switch (cmd) {
    306         case SMBtrans:
    307         case SMBtrans2:
    308                 SSVAL(vwv + 0, 0, state->num_param);
    309                 SSVAL(vwv + 1, 0, state->num_data);
    310                 SSVAL(vwv + 2, 0, state->rparam.max);
    311                 SSVAL(vwv + 3, 0, state->rdata.max);
    312                 SCVAL(vwv + 4, 0, state->max_setup);
    313                 SCVAL(vwv + 4, 1, 0);   /* reserved */
    314                 SSVAL(vwv + 5, 0, state->flags);
    315                 SIVAL(vwv + 6, 0, 0);   /* timeout */
    316                 SSVAL(vwv + 8, 0, 0);   /* reserved */
    317                 SSVAL(vwv + 9, 0, this_param);
    318                 SSVAL(vwv +10, 0, param_offset);
    319                 SSVAL(vwv +11, 0, this_data);
    320                 SSVAL(vwv +12, 0, data_offset);
    321                 SCVAL(vwv +13, 0, state->num_setup);
    322                 SCVAL(vwv +13, 1, 0);   /* reserved */
    323                 memcpy(vwv + 14, state->setup,
    324                        sizeof(uint16_t) * state->num_setup);
    325                 break;
    326         case SMBtranss:
    327         case SMBtranss2:
    328                 SSVAL(vwv + 0, 0, state->num_param);
    329                 SSVAL(vwv + 1, 0, state->num_data);
    330                 SSVAL(vwv + 2, 0, this_param);
    331                 SSVAL(vwv + 3, 0, param_offset);
    332                 SSVAL(vwv + 4, 0, state->param_sent);
    333                 SSVAL(vwv + 5, 0, this_data);
    334                 SSVAL(vwv + 6, 0, data_offset);
    335                 SSVAL(vwv + 7, 0, state->data_sent);
    336                 if (cmd == SMBtranss2) {
    337                         SSVAL(vwv + 8, 0, state->fid);
    338                 }
    339                 break;
    340         case SMBnttrans:
    341                 SCVAL(vwv + 0, 0, state->max_setup);
    342                 SSVAL(vwv + 0, 1, 0); /* reserved */
    343                 SIVAL(vwv + 1, 1, state->num_param);
    344                 SIVAL(vwv + 3, 1, state->num_data);
    345                 SIVAL(vwv + 5, 1, state->rparam.max);
    346                 SIVAL(vwv + 7, 1, state->rdata.max);
    347                 SIVAL(vwv + 9, 1, this_param);
    348                 SIVAL(vwv +11, 1, param_offset);
    349                 SIVAL(vwv +13, 1, this_data);
    350                 SIVAL(vwv +15, 1, data_offset);
    351                 SCVAL(vwv +17, 1, state->num_setup);
    352                 SSVAL(vwv +18, 0, state->function);
    353                 memcpy(vwv + 19, state->setup,
    354                        sizeof(uint16_t) * state->num_setup);
    355                 break;
    356         case SMBnttranss:
    357                 SSVAL(vwv + 0, 0, 0); /* reserved */
    358                 SCVAL(vwv + 1, 0, 0); /* reserved */
    359                 SIVAL(vwv + 1, 1, state->num_param);
    360                 SIVAL(vwv + 3, 1, state->num_data);
    361                 SIVAL(vwv + 5, 1, this_param);
    362                 SIVAL(vwv + 7, 1, param_offset);
    363                 SIVAL(vwv + 9, 1, state->param_sent);
    364                 SIVAL(vwv +11, 1, this_data);
    365                 SIVAL(vwv +13, 1, data_offset);
    366                 SIVAL(vwv +15, 1, state->data_sent);
    367                 SCVAL(vwv +17, 1, 0); /* reserved */
    368                 break;
    369         }
    370 
    371         state->param_sent += this_param;
    372         state->data_sent += this_data;
    373 
    374         *pwct = wct;
    375         *piov_count = iov - state->iov;
    376 }
    377 
    378 static void cli_trans_done(struct tevent_req *subreq);
    379 
    38051struct tevent_req *cli_trans_send(
    381         TALLOC_CTX *mem_ctx, struct event_context *ev,
     52        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
    38253        struct cli_state *cli, uint8_t cmd,
    38354        const char *pipe_name, uint16_t fid, uint16_t function, int flags,
     
    38657        uint8_t *data, uint32_t num_data, uint32_t max_data)
    38758{
    388         struct tevent_req *req, *subreq;
    38959        struct cli_trans_state *state;
    390         int iov_count;
    391         uint8_t wct;
    392         NTSTATUS status;
     60        uint8_t additional_flags = 0;
     61        uint8_t clear_flags = 0;
     62        uint16_t additional_flags2 = 0;
     63        uint16_t clear_flags2 = 0;
    39364
    394         req = tevent_req_create(mem_ctx, &state, struct cli_trans_state);
    395         if (req == NULL) {
     65        state = talloc_zero(mem_ctx, struct cli_trans_state);
     66        if (state == NULL) {
     67                return NULL;
     68        }
     69        state->cli = cli;
     70        state->ptr = talloc(state, struct cli_trans_state *);
     71        if (state->ptr == NULL) {
     72                talloc_free(state);
     73                return NULL;
     74        }
     75        *state->ptr = state;
     76
     77        state->req = smb1cli_trans_send(state, ev,
     78                                        cli->conn, cmd,
     79                                        additional_flags, clear_flags,
     80                                        additional_flags2, clear_flags2,
     81                                        cli->timeout,
     82                                        cli->smb1.pid,
     83                                        cli->smb1.tcon,
     84                                        cli->smb1.session,
     85                                        pipe_name, fid, function, flags,
     86                                        setup, num_setup, max_setup,
     87                                        param, num_param, max_param,
     88                                        data, num_data, max_data);
     89        if (state->req == NULL) {
     90                talloc_free(state);
    39691                return NULL;
    39792        }
    39893
    399         if ((cmd == SMBtrans) || (cmd == SMBtrans2)) {
    400                 if ((num_param > 0xffff) || (max_param > 0xffff)
    401                     || (num_data > 0xffff) || (max_data > 0xffff)) {
    402                         DEBUG(3, ("Attempt to send invalid trans2 request "
    403                                   "(setup %u, params %u/%u, data %u/%u)\n",
    404                                   (unsigned)num_setup,
    405                                   (unsigned)num_param, (unsigned)max_param,
    406                                   (unsigned)num_data, (unsigned)max_data));
    407                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    408                         return tevent_req_post(req, ev);
    409                 }
    410         }
     94        talloc_reparent(state, state->req, state->ptr);
     95        talloc_set_destructor(state, cli_trans_state_destructor);
     96        talloc_set_destructor(state->ptr, cli_trans_state_ptr_destructor);
    41197
    412         /*
    413          * The largest wct will be for nttrans (19+num_setup). Make sure we
    414          * don't overflow state->vwv in cli_trans_format.
    415          */
    416 
    417         if ((num_setup + 19) > ARRAY_SIZE(state->vwv)) {
    418                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    419                 return tevent_req_post(req, ev);
    420         }
    421 
    422         state->cli = cli;
    423         state->ev = ev;
    424         state->cmd = cmd;
    425         state->flags = flags;
    426         state->num_rsetup = 0;
    427         state->rsetup = NULL;
    428         ZERO_STRUCT(state->rparam);
    429         ZERO_STRUCT(state->rdata);
    430 
    431         if ((pipe_name != NULL)
    432             && (!convert_string_talloc(state, CH_UNIX,
    433                                        cli_ucs2(cli) ? CH_UTF16LE : CH_DOS,
    434                                        pipe_name, strlen(pipe_name) + 1,
    435                                        &state->pipe_name_conv,
    436                                        &state->pipe_name_conv_len, true))) {
    437                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
    438                 return tevent_req_post(req, ev);
    439         }
    440         state->fid = fid;       /* trans2 */
    441         state->function = function; /* nttrans */
    442 
    443         state->setup = setup;
    444         state->num_setup = num_setup;
    445         state->max_setup = max_setup;
    446 
    447         state->param = param;
    448         state->num_param = num_param;
    449         state->param_sent = 0;
    450         state->rparam.max = max_param;
    451 
    452         state->data = data;
    453         state->num_data = num_data;
    454         state->data_sent = 0;
    455         state->rdata.max = max_data;
    456 
    457         cli_trans_format(state, &wct, &iov_count);
    458 
    459         subreq = cli_smb_req_create(state, ev, cli, cmd, 0, wct, state->vwv,
    460                                     iov_count, state->iov);
    461         if (tevent_req_nomem(subreq, req)) {
    462                 return tevent_req_post(req, ev);
    463         }
    464         status = cli_smb_req_send(subreq);
    465         if (!NT_STATUS_IS_OK(status)) {
    466                 tevent_req_nterror(req, status);
    467                 return tevent_req_post(req, state->ev);
    468         }
    469         tevent_req_set_callback(subreq, cli_trans_done, req);
    470 
    471         /*
    472          * Now get the MID of the primary request
    473          * and mark it as persistent. This means
    474          * we will able to send and receive multiple
    475          * SMB pdus using this MID in both directions
    476          * (including correct SMB signing).
    477          */
    478         state->mid = cli_smb_req_mid(subreq);
    479         cli_smb_req_set_mid(subreq, state->mid);
    480         state->primary_subreq = subreq;
    481         talloc_set_destructor(state, cli_trans_state_destructor);
    482 
    483         return req;
    484 }
    485 
    486 static void cli_trans_done2(struct tevent_req *subreq);
    487 
    488 static void cli_trans_done(struct tevent_req *subreq)
    489 {
    490         struct tevent_req *req = tevent_req_callback_data(
    491                 subreq, struct tevent_req);
    492         struct cli_trans_state *state = tevent_req_data(
    493                 req, struct cli_trans_state);
    494         NTSTATUS status;
    495         bool sent_all;
    496         uint8_t wct;
    497         uint16_t *vwv;
    498         uint32_t num_bytes;
    499         uint8_t *bytes;
    500         uint8_t *inbuf;
    501         uint8_t num_setup       = 0;
    502         uint16_t *setup         = NULL;
    503         uint32_t total_param    = 0;
    504         uint32_t num_param      = 0;
    505         uint32_t param_disp     = 0;
    506         uint32_t total_data     = 0;
    507         uint32_t num_data       = 0;
    508         uint32_t data_disp      = 0;
    509         uint8_t *param          = NULL;
    510         uint8_t *data           = NULL;
    511 
    512         status = cli_smb_recv(subreq, state, &inbuf, 0, &wct, &vwv,
    513                               &num_bytes, &bytes);
    514         /*
    515          * Do not TALLOC_FREE(subreq) here, we might receive more than
    516          * one response for the same mid.
    517          */
    518 
    519         /*
    520          * We can receive something like STATUS_MORE_ENTRIES, so don't use
    521          * !NT_STATUS_IS_OK(status) here.
    522          */
    523 
    524         if (NT_STATUS_IS_ERR(status)) {
    525                 goto fail;
    526         }
    527 
    528         sent_all = ((state->param_sent == state->num_param)
    529                     && (state->data_sent == state->num_data));
    530 
    531         status = cli_pull_trans(
    532                 inbuf, wct, vwv, num_bytes, bytes,
    533                 state->cmd, !sent_all, &num_setup, &setup,
    534                 &total_param, &num_param, &param_disp, &param,
    535                 &total_data, &num_data, &data_disp, &data);
    536 
    537         if (!NT_STATUS_IS_OK(status)) {
    538                 goto fail;
    539         }
    540 
    541         if (!sent_all) {
    542                 int iov_count;
    543                 struct tevent_req *subreq2;
    544 
    545                 cli_trans_format(state, &wct, &iov_count);
    546 
    547                 subreq2 = cli_smb_req_create(state, state->ev, state->cli,
    548                                              state->cmd + 1, 0, wct, state->vwv,
    549                                              iov_count, state->iov);
    550                 if (tevent_req_nomem(subreq2, req)) {
    551                         return;
    552                 }
    553                 cli_smb_req_set_mid(subreq2, state->mid);
    554 
    555                 status = cli_smb_req_send(subreq2);
    556 
    557                 if (!NT_STATUS_IS_OK(status)) {
    558                         goto fail;
    559                 }
    560                 tevent_req_set_callback(subreq2, cli_trans_done2, req);
    561 
    562                 return;
    563         }
    564 
    565         status = cli_trans_pull_blob(
    566                 state, &state->rparam, total_param, num_param, param,
    567                 param_disp);
    568 
    569         if (!NT_STATUS_IS_OK(status)) {
    570                 DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status)));
    571                 goto fail;
    572         }
    573 
    574         status = cli_trans_pull_blob(
    575                 state, &state->rdata, total_data, num_data, data,
    576                 data_disp);
    577 
    578         if (!NT_STATUS_IS_OK(status)) {
    579                 DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status)));
    580                 goto fail;
    581         }
    582 
    583         if ((state->rparam.total == state->rparam.received)
    584             && (state->rdata.total == state->rdata.received)) {
    585                 state->recv_flags2 = SVAL(inbuf, smb_flg2);
    586                 cli_trans_cleanup_primary(state);
    587                 tevent_req_done(req);
    588                 return;
    589         }
    590 
    591         TALLOC_FREE(inbuf);
    592 
    593         return;
    594 
    595  fail:
    596         cli_trans_cleanup_primary(state);
    597         tevent_req_nterror(req, status);
    598 }
    599 
    600 static void cli_trans_done2(struct tevent_req *subreq2)
    601 {
    602         struct tevent_req *req = tevent_req_callback_data(
    603                 subreq2, struct tevent_req);
    604         struct cli_trans_state *state = tevent_req_data(
    605                 req, struct cli_trans_state);
    606         NTSTATUS status;
    607         bool sent_all;
    608         uint8_t wct;
    609         uint32_t seqnum;
    610 
    611         /*
    612          * First backup the seqnum of the secondary request
    613          * and attach it to the primary request.
    614          */
    615         seqnum = cli_smb_req_seqnum(subreq2);
    616         cli_smb_req_set_seqnum(state->primary_subreq, seqnum);
    617 
    618         status = cli_smb_recv(subreq2, state, NULL, 0, &wct, NULL,
    619                               NULL, NULL);
    620         TALLOC_FREE(subreq2);
    621 
    622         if (!NT_STATUS_IS_OK(status)) {
    623                 goto fail;
    624         }
    625 
    626         if (wct != 0) {
    627                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    628                 goto fail;
    629         }
    630 
    631         sent_all = ((state->param_sent == state->num_param)
    632                     && (state->data_sent == state->num_data));
    633 
    634         if (!sent_all) {
    635                 int iov_count;
    636 
    637                 cli_trans_format(state, &wct, &iov_count);
    638 
    639                 subreq2 = cli_smb_req_create(state, state->ev, state->cli,
    640                                              state->cmd + 1, 0, wct, state->vwv,
    641                                              iov_count, state->iov);
    642                 if (tevent_req_nomem(subreq2, req)) {
    643                         return;
    644                 }
    645                 cli_smb_req_set_mid(subreq2, state->mid);
    646 
    647                 status = cli_smb_req_send(subreq2);
    648 
    649                 if (!NT_STATUS_IS_OK(status)) {
    650                         goto fail;
    651                 }
    652                 tevent_req_set_callback(subreq2, cli_trans_done2, req);
    653                 return;
    654         }
    655 
    656         return;
    657 
    658  fail:
    659         cli_trans_cleanup_primary(state);
    660         tevent_req_nterror(req, status);
     98        return state->req;
    66199}
    662100
     
    670108                        uint32_t *num_data)
    671109{
    672         struct cli_trans_state *state = tevent_req_data(
    673                 req, struct cli_trans_state);
    674110        NTSTATUS status;
     111        void *parent = talloc_parent(req);
     112        struct cli_trans_state *state =
     113                talloc_get_type(parent,
     114                struct cli_trans_state);
     115        bool map_dos_errors = true;
    675116
    676         cli_trans_cleanup_primary(state);
     117        status = smb1cli_trans_recv(req, mem_ctx, recv_flags2,
     118                                    setup, min_setup, num_setup,
     119                                    param, min_param, num_param,
     120                                    data, min_data, num_data);
    677121
    678         if (tevent_req_is_nterror(req, &status)) {
    679                 return status;
     122        if (state) {
     123                map_dos_errors = state->cli->map_dos_errors;
     124                state->cli->raw_status = status;
     125                talloc_free(state->ptr);
     126                state = NULL;
    680127        }
    681128
    682         if ((state->num_rsetup < min_setup)
    683             || (state->rparam.total < min_param)
    684             || (state->rdata.total < min_data)) {
    685                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     129        if (NT_STATUS_IS_DOS(status) && map_dos_errors) {
     130                uint8_t eclass = NT_STATUS_DOS_CLASS(status);
     131                uint16_t ecode = NT_STATUS_DOS_CODE(status);
     132                /*
     133                 * TODO: is it really a good idea to do a mapping here?
     134                 *
     135                 * The old cli_pull_error() also does it, so I do not change
     136                 * the behavior yet.
     137                 */
     138                status = dos_to_ntstatus(eclass, ecode);
    686139        }
    687140
    688         if (recv_flags2 != NULL) {
    689                 *recv_flags2 = state->recv_flags2;
    690         }
    691 
    692         if (setup != NULL) {
    693                 *setup = talloc_move(mem_ctx, &state->rsetup);
    694                 *num_setup = state->num_rsetup;
    695         } else {
    696                 TALLOC_FREE(state->rsetup);
    697         }
    698 
    699         if (param != NULL) {
    700                 *param = talloc_move(mem_ctx, &state->rparam.data);
    701                 *num_param = state->rparam.total;
    702         } else {
    703                 TALLOC_FREE(state->rparam.data);
    704         }
    705 
    706         if (data != NULL) {
    707                 *data = talloc_move(mem_ctx, &state->rdata.data);
    708                 *num_data = state->rdata.total;
    709         } else {
    710                 TALLOC_FREE(state->rdata.data);
    711         }
    712 
    713         return NT_STATUS_OK;
     141        return status;
    714142}
    715143
     
    726154                   uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata)
    727155{
    728         TALLOC_CTX *frame = talloc_stackframe();
    729         struct event_context *ev;
    730         struct tevent_req *req;
    731         NTSTATUS status = NT_STATUS_OK;
     156        NTSTATUS status;
     157        uint8_t additional_flags = 0;
     158        uint8_t clear_flags = 0;
     159        uint16_t additional_flags2 = 0;
     160        uint16_t clear_flags2 = 0;
    732161
    733         if (cli_has_async_calls(cli)) {
     162        status = smb1cli_trans(mem_ctx,
     163                               cli->conn, trans_cmd,
     164                               additional_flags, clear_flags,
     165                               additional_flags2, clear_flags2,
     166                               cli->timeout,
     167                               cli->smb1.pid,
     168                               cli->smb1.tcon,
     169                               cli->smb1.session,
     170                               pipe_name, fid, function, flags,
     171                               setup, num_setup, max_setup,
     172                               param, num_param, max_param,
     173                               data, num_data, max_data,
     174                               recv_flags2,
     175                               rsetup, min_rsetup, num_rsetup,
     176                               rparam, min_rparam, num_rparam,
     177                               rdata, min_rdata, num_rdata);
     178
     179        cli->raw_status = status;
     180
     181        if (NT_STATUS_IS_DOS(status) && cli->map_dos_errors) {
     182                uint8_t eclass = NT_STATUS_DOS_CLASS(status);
     183                uint16_t ecode = NT_STATUS_DOS_CODE(status);
    734184                /*
    735                  * Can't use sync call while an async call is in flight
     185                 * TODO: is it really a good idea to do a mapping here?
     186                 *
     187                 * The old cli_pull_error() also does it, so I do not change
     188                 * the behavior yet.
    736189                 */
    737                 status = NT_STATUS_INVALID_PARAMETER;
    738                 goto fail;
     190                status = dos_to_ntstatus(eclass, ecode);
    739191        }
    740192
    741         ev = event_context_init(frame);
    742         if (ev == NULL) {
    743                 status = NT_STATUS_NO_MEMORY;
    744                 goto fail;
    745         }
    746 
    747         req = cli_trans_send(frame, ev, cli, trans_cmd,
    748                              pipe_name, fid, function, flags,
    749                              setup, num_setup, max_setup,
    750                              param, num_param, max_param,
    751                              data, num_data, max_data);
    752         if (req == NULL) {
    753                 status = NT_STATUS_NO_MEMORY;
    754                 goto fail;
    755         }
    756 
    757         if (!tevent_req_poll(req, ev)) {
    758                 status = map_nt_error_from_unix(errno);
    759                 goto fail;
    760         }
    761 
    762         status = cli_trans_recv(req, mem_ctx, recv_flags2,
    763                                 rsetup, min_rsetup, num_rsetup,
    764                                 rparam, min_rparam, num_rparam,
    765                                 rdata, min_rdata, num_rdata);
    766  fail:
    767         TALLOC_FREE(frame);
    768193        return status;
    769194}
Note: See TracChangeset for help on using the changeset viewer.