s3:libsmb: use new simplified smb_signing code for the client side
[abartlet/samba.git/.git] / source3 / libsmb / clitrans.c
index 5b84e68fc4446ca75fc0fa11045ea88b0fd2e3e8..c566972b211102e98efb84da0ae6f248eac2d8fa 100644 (file)
@@ -94,14 +94,12 @@ bool cli_send_trans(struct cli_state *cli, int trans,
                return False;
        }
 
-       /* Note we're in a trans state. Save the sequence
-        * numbers for replies. */
-       client_set_trans_sign_state_on(cli, mid);
+       cli_state_seqnum_persistent(cli, mid);
 
        if (this_ldata < ldata || this_lparam < lparam) {
                /* receive interim response */
                if (!cli_receive_smb(cli) || cli_is_error(cli)) {
-                       client_set_trans_sign_state_off(cli, mid);
+                       cli_state_seqnum_remove(cli, mid);
                        return(False);
                }
 
@@ -112,9 +110,6 @@ bool cli_send_trans(struct cli_state *cli, int trans,
                        this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
                        this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
 
-                       client_set_trans_sign_state_off(cli, mid);
-                       client_set_trans_sign_state_on(cli, mid);
-
                        cli_set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
                        SCVAL(cli->outbuf,smb_com,(trans==SMBtrans ? SMBtranss : SMBtranss2));
 
@@ -138,21 +133,14 @@ bool cli_send_trans(struct cli_state *cli, int trans,
                                memcpy(outdata,data+tot_data,this_ldata);
                        cli_setup_bcc(cli, outdata+this_ldata);
 
-                       /*
-                        * Save the mid we're using. We need this for finding
-                        * signing replies.
-                        */
-                       mid = cli->mid;
-
                        show_msg(cli->outbuf);
+
+                       cli->mid = mid;
                        if (!cli_send_smb(cli)) {
-                               client_set_trans_sign_state_off(cli, mid);
+                               cli_state_seqnum_remove(cli, mid);
                                return False;
                        }
 
-                       /* Ensure we use the same mid for the secondaries. */
-                       cli->mid = mid;
-
                        tot_data += this_ldata;
                        tot_param += this_lparam;
                }
@@ -174,10 +162,14 @@ bool cli_receive_trans(struct cli_state *cli,int trans,
        unsigned int this_data,this_param;
        NTSTATUS status;
        bool ret = False;
+       uint16_t mid;
 
        *data_len = *param_len = 0;
 
+       mid = SVAL(cli->inbuf,smb_mid);
+
        if (!cli_receive_smb(cli)) {
+               cli_state_seqnum_remove(cli, mid);
                return False;
        }
 
@@ -188,6 +180,7 @@ bool cli_receive_trans(struct cli_state *cli,int trans,
                DEBUG(0,("Expected %s response, got command 0x%02x\n",
                         trans==SMBtrans?"SMBtrans":"SMBtrans2",
                         CVAL(cli->inbuf,smb_com)));
+               cli_state_seqnum_remove(cli, mid);
                return False;
        }
 
@@ -340,6 +333,8 @@ bool cli_receive_trans(struct cli_state *cli,int trans,
 
   out:
 
+       cli_state_seqnum_remove(cli, mid);
+
        if (ret) {
                /* Ensure the last 2 bytes of param and data are 2 null
                 * bytes. These are malloc'ed, but not included in any
@@ -353,7 +348,6 @@ bool cli_receive_trans(struct cli_state *cli,int trans,
                }
        }
 
-       client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid));
        return ret;
 }
 
@@ -421,14 +415,12 @@ bool cli_send_nt_trans(struct cli_state *cli,
                return False;
        }
 
-       /* Note we're in a trans state. Save the sequence
-        * numbers for replies. */
-       client_set_trans_sign_state_on(cli, mid);
+       cli_state_seqnum_persistent(cli, mid);
 
        if (this_ldata < ldata || this_lparam < lparam) {
                /* receive interim response */
                if (!cli_receive_smb(cli) || cli_is_error(cli)) {
-                       client_set_trans_sign_state_off(cli, mid);
+                       cli_state_seqnum_remove(cli, mid);
                        return(False);
                }
 
@@ -461,22 +453,14 @@ bool cli_send_nt_trans(struct cli_state *cli,
                                memcpy(outdata,data+tot_data,this_ldata);
                        cli_setup_bcc(cli, outdata+this_ldata);
 
-                       /*
-                        * Save the mid we're using. We need this for finding
-                        * signing replies.
-                        */
-                       mid = cli->mid;
-
                        show_msg(cli->outbuf);
 
+                       cli->mid = mid;
                        if (!cli_send_smb(cli)) {
-                               client_set_trans_sign_state_off(cli, mid);
+                               cli_state_seqnum_remove(cli, mid);
                                return False;
                        }
 
-                       /* Ensure we use the same mid for the secondaries. */
-                       cli->mid = mid;
-
                        tot_data += this_ldata;
                        tot_param += this_lparam;
                }
@@ -499,10 +483,14 @@ bool cli_receive_nt_trans(struct cli_state *cli,
        uint8 eclass;
        uint32 ecode;
        bool ret = False;
+       uint16_t mid;
 
        *data_len = *param_len = 0;
 
+       mid = SVAL(cli->inbuf,smb_mid);
+
        if (!cli_receive_smb(cli)) {
+               cli_state_seqnum_remove(cli, mid);
                return False;
        }
 
@@ -512,6 +500,7 @@ bool cli_receive_nt_trans(struct cli_state *cli,
        if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
                DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
                         CVAL(cli->inbuf,smb_com)));
+               cli_state_seqnum_remove(cli, mid);
                return(False);
        }
 
@@ -685,6 +674,8 @@ bool cli_receive_nt_trans(struct cli_state *cli,
 
   out:
 
+       cli_state_seqnum_remove(cli, mid);
+
        if (ret) {
                /* Ensure the last 2 bytes of param and data are 2 null
                 * bytes. These are malloc'ed, but not included in any
@@ -698,7 +689,6 @@ bool cli_receive_nt_trans(struct cli_state *cli,
                }
        }
 
-       client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid));
        return ret;
 }
 
@@ -712,6 +702,7 @@ struct cli_trans_state {
        struct event_context *ev;
        uint8_t cmd;
        uint16_t mid;
+       uint32_t seqnum;
        const char *pipe_name;
        uint16_t fid;
        uint16_t function;
@@ -747,6 +738,7 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
        uint16_t this_data = 0;
        uint32_t useable_space;
        uint8_t cmd;
+       uint8_t pad[3];
 
        frame = talloc_stackframe();
 
@@ -759,15 +751,22 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
 
        param_offset = smb_size - 4;
 
+       bytes = TALLOC_ARRAY(talloc_tos(), uint8_t, 0); /* padding */
+       if (bytes == NULL) {
+               goto fail;
+       }
+
        switch (cmd) {
        case SMBtrans:
-               bytes = TALLOC_ZERO_P(talloc_tos(), uint8_t); /* padding */
+               pad[0] = 0;
+               bytes = (uint8_t *)talloc_append_blob(talloc_tos(), bytes,
+                                               data_blob_const(pad, 1));
                if (bytes == NULL) {
                        goto fail;
                }
-               bytes = smb_bytes_push_str(
-                       bytes, (state->cli->capabilities & CAP_UNICODE) != 0,
-                       state->pipe_name);
+               bytes = smb_bytes_push_str(bytes, cli_ucs2(state->cli),
+                                          state->pipe_name,
+                                          strlen(state->pipe_name)+1, NULL);
                if (bytes == NULL) {
                        goto fail;
                }
@@ -775,13 +774,14 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
                param_offset += talloc_get_size(bytes);
                break;
        case SMBtrans2:
-               bytes = TALLOC_ARRAY(talloc_tos(), uint8_t, 3); /* padding */
+               pad[0] = 0;
+               pad[1] = 'D'; /* Copy this from "old" 3.0 behaviour */
+               pad[2] = ' ';
+               bytes = (uint8_t *)talloc_append_blob(talloc_tos(), bytes,
+                                               data_blob_const(pad, 3));
                if (bytes == NULL) {
                        goto fail;
                }
-               bytes[0] = 0;
-               bytes[1] = 'D'; /* Copy this from "old" 3.0 behaviour */
-               bytes[2] = ' ';
                wct = 14 + state->num_setup;
                param_offset += talloc_get_size(bytes);
                break;
@@ -918,7 +918,7 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
                 * Primary request, retrieve our mid
                 */
                result = cli_request_send(mem_ctx, state->ev, state->cli,
-                                         cmd, 0, wct, vwv,
+                                         cmd, 0, wct, vwv, 0,
                                          talloc_get_size(bytes), bytes);
                if (result == NULL) {
                        goto fail;
@@ -926,6 +926,7 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
                cli_req = talloc_get_type_abort(result->private_data,
                                                struct cli_request);
                state->mid = cli_req->mid;
+               state->seqnum = cli_req->seqnum;
        } else {
                uint16_t num_bytes = talloc_get_size(bytes);
                /*
@@ -936,8 +937,8 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
                                    wct * sizeof(uint16_t) + num_bytes + 3)) {
                        goto fail;
                }
-               result = cli_request_send(mem_ctx, state->ev, state->cli,
-                                         cmd, 0, wct, vwv, num_bytes, bytes);
+               result = cli_request_send(mem_ctx, state->ev, state->cli, cmd,
+                                         0, wct, vwv, 0, num_bytes, bytes);
                if (result == NULL) {
                        goto fail;
                }
@@ -946,12 +947,10 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
                cli_req->recv_helper.fn = cli_trans_recv_helper;
                cli_req->recv_helper.priv = state;
                cli_req->mid = state->mid;
-               client_set_trans_sign_state_off(state->cli, state->mid);
                cli_chain_uncork(state->cli);
+               state->seqnum = cli_req->seqnum;
        }
 
-       client_set_trans_sign_state_on(state->cli, state->mid);
-
  fail:
        TALLOC_FREE(frame);
        return result;
@@ -960,35 +959,29 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx,
 static void cli_trans_ship_rest(struct async_req *req,
                                struct cli_trans_state *state)
 {
+       struct cli_request *cli_req;
+
        state->secondary_request_ctx = talloc_new(state);
        if (state->secondary_request_ctx == NULL) {
-               async_req_error(req, NT_STATUS_NO_MEMORY);
+               async_req_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
 
        while ((state->param_sent < state->num_param)
               || (state->data_sent < state->num_data)) {
-               struct async_req *cli_req;
+               struct async_req *subreq;
 
-               cli_req = cli_ship_trans(state->secondary_request_ctx, state);
-               if (cli_req == NULL) {
-                       async_req_error(req, NT_STATUS_NO_MEMORY);
+               subreq = cli_ship_trans(state->secondary_request_ctx, state);
+               if (subreq == NULL) {
+                       async_req_nterror(req, NT_STATUS_NO_MEMORY);
                        return;
                }
        }
-}
 
-static bool cli_trans_oob(uint32_t bufsize, uint32_t offset, uint32_t length)
-{
-       if ((offset + length < offset) || (offset + length < length)) {
-               /* wrap */
-               return true;
-       }
-       if ((offset > bufsize) || (offset + length > bufsize)) {
-               /* overflow */
-               return true;
-       }
-       return false;
+       cli_req = talloc_get_type_abort(req->private_data,
+                                       struct cli_request);
+
+       cli_req->seqnum = state->seqnum;
 }
 
 static NTSTATUS cli_pull_trans(struct async_req *req,
@@ -1072,10 +1065,10 @@ static NTSTATUS cli_pull_trans(struct async_req *req,
         * length. Likewise for param_ofs/param_disp.
         */
 
-       if (cli_trans_oob(smb_len(cli_req->inbuf), param_ofs, *pnum_param)
-           || cli_trans_oob(*ptotal_param, *pparam_disp, *pnum_param)
-           || cli_trans_oob(smb_len(cli_req->inbuf), data_ofs, *pnum_data)
-           || cli_trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) {
+       if (trans_oob(smb_len(cli_req->inbuf), param_ofs, *pnum_param)
+           || trans_oob(*ptotal_param, *pparam_disp, *pnum_param)
+           || trans_oob(smb_len(cli_req->inbuf), data_ofs, *pnum_data)
+           || trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) {
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
        }
 
@@ -1119,11 +1112,16 @@ static void cli_trans_recv_helper(struct async_req *req)
                req->private_data, struct cli_request);
        struct cli_trans_state *state = talloc_get_type_abort(
                cli_req->recv_helper.priv, struct cli_trans_state);
-       uint8_t num_setup;
-       uint16_t *setup;
-       uint32_t total_param, num_param, param_disp;
-       uint32_t total_data, num_data, data_disp;
-       uint8_t *param, *data;
+       uint8_t num_setup       = 0;
+       uint16_t *setup         = NULL;
+       uint32_t total_param    = 0;
+       uint32_t num_param      = 0;
+       uint32_t param_disp     = 0;
+       uint32_t total_data     = 0;
+       uint32_t num_data       = 0;
+       uint32_t data_disp      = 0;
+       uint8_t *param          = NULL;
+       uint8_t *data           = NULL;
        bool sent_all;
        NTSTATUS status;
 
@@ -1141,7 +1139,7 @@ static void cli_trans_recv_helper(struct async_req *req)
         */
 
        if (NT_STATUS_IS_ERR(status)) {
-               async_req_error(req, status);
+               async_req_nterror(req, status);
                return;
        }
 
@@ -1162,7 +1160,7 @@ static void cli_trans_recv_helper(struct async_req *req)
                state->rsetup = (uint16_t *)TALLOC_MEMDUP(
                        state, setup, sizeof(uint16_t) * num_setup);
                if (state->rsetup == NULL) {
-                       async_req_error(req, NT_STATUS_NO_MEMORY);
+                       async_req_nterror(req, NT_STATUS_NO_MEMORY);
                        return;
                }
        }
@@ -1173,7 +1171,7 @@ static void cli_trans_recv_helper(struct async_req *req)
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status)));
-               async_req_error(req, status);
+               async_req_nterror(req, status);
                return;
        }
 
@@ -1183,13 +1181,12 @@ static void cli_trans_recv_helper(struct async_req *req)
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status)));
-               async_req_error(req, status);
+               async_req_nterror(req, status);
                return;
        }
 
        if ((state->rparam.total == state->rparam.received)
            && (state->rdata.total == state->rdata.received)) {
-               client_set_trans_sign_state_off(state->cli, state->mid);
                async_req_done(req);
        }
 }
@@ -1324,10 +1321,10 @@ NTSTATUS cli_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
                req->private_data, struct cli_request);
        struct cli_trans_state *state = talloc_get_type_abort(
                cli_req->recv_helper.priv, struct cli_trans_state);
+       NTSTATUS status;
 
-       SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
-       if (req->state == ASYNC_REQ_ERROR) {
-               return req->status;
+       if (async_req_is_nterror(req, &status)) {
+               return status;
        }
 
        if (setup != NULL) {