diff options
author | Volker Lendecke <vl@samba.org> | 2008-03-07 15:03:20 +0100 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2008-03-08 22:02:33 +0100 |
commit | 464f74df2f6f50525c3701025860fe0435d9c91c (patch) | |
tree | ee0a5388722385c26db401f801c93b884f4fcd11 /source3/libsmb | |
parent | 8da1e033a876ab273bf4949535b31817585a953d (diff) | |
download | samba-464f74df2f6f50525c3701025860fe0435d9c91c.tar.gz samba-464f74df2f6f50525c3701025860fe0435d9c91c.tar.bz2 samba-464f74df2f6f50525c3701025860fe0435d9c91c.zip |
Move inbuf handling to before the PDU handling
In an error case, correctly discard the offending PDU
(This used to be commit 0aa195b5d623e1f26f2a1b9e91323a5ddd3ff282)
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/async_smb.c | 117 |
1 files changed, 59 insertions, 58 deletions
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 21bcd5b9b1..04c22a9d17 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -174,24 +174,72 @@ static void handle_incoming_pdu(struct cli_state *cli) { struct cli_request *req; uint16_t mid; - size_t raw_pdu_len, buf_len, pdu_len; - size_t rest_len; + size_t raw_pdu_len, buf_len, pdu_len, rest_len; + char *pdu; NTSTATUS status; /* * The encrypted PDU len might differ from the unencrypted one */ raw_pdu_len = smb_len(cli->evt_inbuf) + 4; + buf_len = talloc_get_size(cli->evt_inbuf); + rest_len = buf_len - raw_pdu_len; + + if (buf_len == raw_pdu_len) { + /* + * Optimal case: Exactly one PDU was in the socket buffer + */ + pdu = cli->evt_inbuf; + cli->evt_inbuf = NULL; + } + else { + DEBUG(11, ("buf_len = %d, raw_pdu_len = %d, splitting " + "buffer\n", (int)buf_len, (int)raw_pdu_len)); + + if (raw_pdu_len < rest_len) { + /* + * The PDU is shorter, talloc_memdup that one. + */ + pdu = (char *)talloc_memdup( + cli, cli->evt_inbuf, raw_pdu_len); + + memmove(cli->evt_inbuf, cli->evt_inbuf + raw_pdu_len, + buf_len - raw_pdu_len); + + cli->evt_inbuf = TALLOC_REALLOC_ARRAY( + NULL, cli->evt_inbuf, char, rest_len); + + if (pdu == NULL) { + status = NT_STATUS_NO_MEMORY; + goto invalidate_requests; + } + } + else { + /* + * The PDU is larger than the rest, talloc_memdup the + * rest + */ + pdu = cli->evt_inbuf; + + cli->evt_inbuf = (char *)talloc_memdup( + cli, pdu + raw_pdu_len, rest_len); + + if (cli->evt_inbuf == NULL) { + status = NT_STATUS_NO_MEMORY; + goto invalidate_requests; + } + } + + } /* * TODO: Handle oplock break requests */ - if (cli_encryption_on(cli) && CVAL(cli->evt_inbuf, 0) == 0) { + if (cli_encryption_on(cli) && CVAL(pdu, 0) == 0) { uint16_t enc_ctx_num; - status = get_enc_ctx_num((uint8_t *)cli->evt_inbuf, - &enc_ctx_num); + status = get_enc_ctx_num((uint8_t *)pdu, &enc_ctx_num); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("get_enc_ctx_num returned %s\n", nt_errstr(status))); @@ -207,7 +255,7 @@ static void handle_incoming_pdu(struct cli_state *cli) } status = common_decrypt_buffer(cli->trans_enc_state, - cli->evt_inbuf); + pdu); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("common_decrypt_buffer returned %s\n", nt_errstr(status))); @@ -215,13 +263,13 @@ static void handle_incoming_pdu(struct cli_state *cli) } } - if (!cli_check_sign_mac(cli, cli->evt_inbuf)) { + if (!cli_check_sign_mac(cli, pdu)) { DEBUG(10, ("cli_check_sign_mac failed\n")); status = NT_STATUS_ACCESS_DENIED; goto invalidate_requests; } - mid = SVAL(cli->evt_inbuf, smb_mid); + mid = SVAL(pdu, smb_mid); DEBUG(10, ("handle_incoming_pdu: got mid %d\n", mid)); @@ -231,64 +279,17 @@ static void handle_incoming_pdu(struct cli_state *cli) } } - buf_len = talloc_get_size(cli->evt_inbuf); - pdu_len = smb_len(cli->evt_inbuf) + 4; - rest_len = buf_len - raw_pdu_len; + pdu_len = smb_len(pdu) + 4; if (req == NULL) { DEBUG(3, ("Request for mid %d not found, dumping PDU\n", mid)); - memmove(cli->evt_inbuf, cli->evt_inbuf + raw_pdu_len, - buf_len - raw_pdu_len); - - cli->evt_inbuf = TALLOC_REALLOC_ARRAY(NULL, cli->evt_inbuf, - char, rest_len); + TALLOC_FREE(pdu); return; } - if (buf_len == pdu_len) { - /* - * Optimal case: Exactly one PDU was in the socket buffer - */ - req->inbuf = talloc_move(req, &cli->evt_inbuf); - goto done; - } - - DEBUG(11, ("buf_len = %d, pdu_len = %d, splitting buffer\n", - (int)buf_len, (int)pdu_len)); - - if (pdu_len < rest_len) { - /* - * The PDU is shorter, talloc_memdup that one. - */ - req->inbuf = (char *)talloc_memdup( - req, cli->evt_inbuf, pdu_len); - - memmove(cli->evt_inbuf, - cli->evt_inbuf + raw_pdu_len, - buf_len - raw_pdu_len); - - cli->evt_inbuf = TALLOC_REALLOC_ARRAY( - NULL, cli->evt_inbuf, char, rest_len); - } - else { - /* - * The PDU is larger than the rest, - * talloc_memdup the rest - */ - req->inbuf = talloc_move(req, &cli->evt_inbuf); - - cli->evt_inbuf = (char *)talloc_memdup( - cli, req->inbuf + raw_pdu_len, - rest_len); - } - - if ((req->inbuf == NULL) || (cli->evt_inbuf == NULL)) { - status = NT_STATUS_NO_MEMORY; - goto invalidate_requests; - } + req->inbuf = talloc_move(req, &pdu); - done: async_req_done(req->async); return; |