From f4cf1c56a20916018c9a6513754b0b08c24c9d04 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 14 Nov 2009 11:12:50 +0100 Subject: s3: Add min_setup, min_param and min_data to cli_trans_recv Every caller that expects to receive something needs to check if enough was sent. Make this check mandatory for everyone. Yes, this makes the parameter list for cli_trans a bit silly, but that's just the way it is: A silly protocol request :-) While there, convert some _done functions to tevent_req_simple_finish_ntstatus. --- source3/include/proto.h | 15 +++-- source3/libsmb/clifile.c | 113 +++++++++------------------------- source3/libsmb/clifsinfo.c | 12 ++-- source3/libsmb/clirap.c | 20 ++---- source3/libsmb/clisecdesc.c | 11 ++-- source3/libsmb/clitrans.c | 26 +++++--- source3/rpc_client/rpc_transport_np.c | 4 +- 7 files changed, 72 insertions(+), 129 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index d4e0ac55c5..86f6626a69 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3040,9 +3040,12 @@ struct tevent_req *cli_trans_send( uint8_t *param, uint32_t num_param, uint32_t max_param, uint8_t *data, uint32_t num_data, uint32_t max_data); NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - uint16_t **setup, uint8_t *num_setup, - uint8_t **param, uint32_t *num_param, - uint8_t **data, uint32_t *num_data); + uint16_t **setup, uint8_t min_setup, + uint8_t *num_setup, + uint8_t **param, uint32_t min_param, + uint32_t *num_param, + uint8_t **data, uint32_t min_data, + uint32_t *num_data); NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint8_t trans_cmd, const char *pipe_name, uint16_t fid, uint16_t function, @@ -3050,9 +3053,9 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t *setup, uint8_t num_setup, uint8_t max_setup, uint8_t *param, uint32_t num_param, uint32_t max_param, uint8_t *data, uint32_t num_data, uint32_t max_data, - uint16_t **rsetup, uint8_t *num_rsetup, - uint8_t **rparam, uint32_t *num_rparam, - uint8_t **rdata, uint32_t *num_rdata); + uint16_t **rsetup, uint8_t min_rsetup, uint8_t *num_rsetup, + uint8_t **rparam, uint32_t min_rparam, uint32_t *num_rparam, + uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata); /* The following definitions come from libsmb/conncache.c */ diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 5eb8bd471b..1a09c41680 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -119,18 +119,9 @@ struct link_state { static void cli_posix_link_internal_done(struct tevent_req *subreq) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct link_state *state = tevent_req_data(req, struct link_state); - NTSTATUS status; - - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } - tevent_req_done(req); + return tevent_req_simple_finish_ntstatus( + subreq, cli_trans_recv(subreq, NULL, NULL, 0, NULL, + NULL, 0, NULL, NULL, 0, NULL)); } static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx, @@ -289,8 +280,8 @@ static void cli_posix_readlink_done(struct tevent_req *subreq) struct readlink_state *state = tevent_req_data(req, struct readlink_state); NTSTATUS status; - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, - &state->data, &state->num_data); + status = cli_trans_recv(subreq, state, NULL, 0, NULL, NULL, 0, NULL, + &state->data, 0, &state->num_data); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); @@ -637,8 +628,8 @@ static void cli_posix_getfacl_done(struct tevent_req *subreq) struct getfacl_state *state = tevent_req_data(req, struct getfacl_state); NTSTATUS status; - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, - &state->data, &state->num_data); + status = cli_trans_recv(subreq, state, NULL, 0, NULL, NULL, 0, NULL, + &state->data, 0, &state->num_data); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); @@ -786,8 +777,8 @@ static void cli_posix_stat_done(struct tevent_req *subreq) struct stat_state *state = tevent_req_data(req, struct stat_state); NTSTATUS status; - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, - &state->data, &state->num_data); + status = cli_trans_recv(subreq, state, NULL, 0, NULL, NULL, 0, NULL, + &state->data, 96, &state->num_data); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); @@ -954,18 +945,9 @@ struct ch_state { static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct ch_state *state = tevent_req_data(req, struct ch_state); - NTSTATUS status; - - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } - tevent_req_done(req); + return tevent_req_simple_finish_ntstatus( + subreq, cli_trans_recv(subreq, NULL, NULL, 0, NULL, + NULL, 0, NULL, NULL, 0, NULL)); } static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx, @@ -1861,18 +1843,9 @@ struct doc_state { static void cli_nt_delete_on_close_done(struct tevent_req *subreq) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct doc_state *state = tevent_req_data(req, struct doc_state); - NTSTATUS status; - - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } - tevent_req_done(req); + return tevent_req_simple_finish_ntstatus( + subreq, cli_trans_recv(subreq, NULL, NULL, 0, NULL, + NULL, 0, NULL, NULL, 0, NULL)); } struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx, @@ -2476,18 +2449,9 @@ struct ftrunc_state { static void cli_ftruncate_done(struct tevent_req *subreq) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct ftrunc_state *state = tevent_req_data(req, struct ftrunc_state); - NTSTATUS status; - - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } - tevent_req_done(req); + return tevent_req_simple_finish_ntstatus( + subreq, cli_trans_recv(subreq, NULL, NULL, 0, NULL, + NULL, 0, NULL, NULL, 0, NULL)); } struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx, @@ -3010,18 +2974,9 @@ struct posix_lock_state { static void cli_posix_unlock_internal_done(struct tevent_req *subreq) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct posix_lock_state *state = tevent_req_data(req, struct posix_lock_state); - NTSTATUS status; - - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } - tevent_req_done(req); + return tevent_req_simple_finish_ntstatus( + subreq, cli_trans_recv(subreq, NULL, NULL, 0, NULL, + NULL, 0, NULL, NULL, 0, NULL)); } static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx, @@ -4579,16 +4534,13 @@ static void cli_posix_open_internal_done(struct tevent_req *subreq) uint8_t *data; uint32_t num_data; - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, &data, &num_data); + status = cli_trans_recv(subreq, state, NULL, 0, NULL, NULL, 0, NULL, + &data, 12, &num_data); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } - if (num_data < 12) { - tevent_req_nterror(req, status); - return; - } state->fnum = SVAL(data,2); tevent_req_done(req); } @@ -4818,18 +4770,9 @@ struct unlink_state { static void cli_posix_unlink_internal_done(struct tevent_req *subreq) { - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct unlink_state *state = tevent_req_data(req, struct unlink_state); - NTSTATUS status; - - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } - tevent_req_done(req); + return tevent_req_simple_finish_ntstatus( + subreq, cli_trans_recv(subreq, NULL, NULL, 0, NULL, + NULL, 0, NULL, NULL, 0, NULL)); } static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx, @@ -5094,8 +5037,8 @@ static void cli_notify_done(struct tevent_req *subreq) uint8_t *params; uint32_t i, ofs, num_params; - status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL, - ¶ms, &num_params, NULL, NULL); + status = cli_trans_recv(subreq, talloc_tos(), NULL, 0, NULL, + ¶ms, 0, &num_params, NULL, 0, NULL); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status))); diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 9e2177a0ed..6e23dbc689 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -71,17 +71,13 @@ static void cli_unix_extensions_version_done(struct tevent_req *subreq) uint32_t num_data; NTSTATUS status; - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, - &data, &num_data); + status = cli_trans_recv(subreq, state, NULL, 0, NULL, NULL, 0, NULL, + &data, 12, &num_data); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } - if (num_data < 12) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } state->major = SVAL(data, 0); state->minor = SVAL(data, 2); @@ -211,8 +207,8 @@ static void cli_set_unix_extensions_capabilities_done( struct tevent_req *subreq) { return tevent_req_simple_finish_ntstatus( - subreq, cli_trans_recv(subreq, NULL, NULL, NULL, NULL, NULL, - NULL, NULL)); + subreq, cli_trans_recv(subreq, NULL, NULL, 0, NULL, + NULL, 0, NULL, NULL, 0, NULL)); } NTSTATUS cli_set_unix_extensions_capabilities_recv(struct tevent_req *req) diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index c3ec82bd3e..13e16b26df 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -974,19 +974,16 @@ bool cli_qfileinfo(struct cli_state *cli, uint16_t fnum, struct timespec *change_time, SMB_INO_T *ino) { - unsigned int data_len = 0; - unsigned int param_len = 0; + uint32_t data_len = 0; uint16 setup; uint8_t param[4]; - uint8_t *rparam=NULL, *rdata=NULL; + uint8_t *rdata=NULL; NTSTATUS status; /* if its a win95 server then fail this - win95 totally screws it up */ if (cli->win95) return False; - param_len = 4; - SSVAL(param, 0, fnum); SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO); @@ -995,20 +992,16 @@ bool cli_qfileinfo(struct cli_state *cli, uint16_t fnum, status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0, /* name, fid, function, flags */ &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ + param, 4, 2, /* param, length, max */ NULL, 0, MIN(cli->max_xmit, 0xffff), /* data, length, max */ - NULL, NULL, /* rsetup, length */ - &rparam, ¶m_len, /* rparam, length */ - &rdata, &data_len); + NULL, 0, NULL, /* rsetup, length */ + NULL, 0, NULL, /* rparam, length */ + &rdata, 68, &data_len); if (!NT_STATUS_IS_OK(status)) { return false; } - if (!rdata || data_len < 68) { - return False; - } - if (create_time) { *create_time = interpret_long_date((char *)rdata+0); } @@ -1032,7 +1025,6 @@ bool cli_qfileinfo(struct cli_state *cli, uint16_t fnum, } TALLOC_FREE(rdata); - TALLOC_FREE(rparam); return True; } diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c index 1c87eabafe..f4f7c545e1 100644 --- a/source3/libsmb/clisecdesc.c +++ b/source3/libsmb/clisecdesc.c @@ -26,8 +26,8 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, uint16_t fnum, TALLOC_CTX *mem_ctx) { uint8_t param[8]; - uint8_t *rparam=NULL, *rdata=NULL; - unsigned int rparam_count=0, rdata_count=0; + uint8_t *rdata=NULL; + uint32_t rdata_count=0; SEC_DESC *psd = NULL; NTSTATUS status; @@ -40,9 +40,9 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, uint16_t fnum, NULL, 0, 0, /* setup, length, max */ param, 8, 4, /* param, length, max */ NULL, 0, 0x10000, /* data, length, max */ - NULL, NULL, /* rsetup, length */ - &rparam, &rparam_count, - &rdata, &rdata_count); + NULL, 0, NULL, /* rsetup, length */ + NULL, 0, NULL, + &rdata, 0, &rdata_count); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("NT_TRANSACT_QUERY_SECURITY_DESC failed: %s\n", @@ -61,7 +61,6 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, uint16_t fnum, cleanup: - TALLOC_FREE(rparam); TALLOC_FREE(rdata); return psd; diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index 98c09ed6e7..ec63bc3b9d 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -1204,9 +1204,12 @@ static void cli_trans_done(struct tevent_req *subreq) } NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - uint16_t **setup, uint8_t *num_setup, - uint8_t **param, uint32_t *num_param, - uint8_t **data, uint32_t *num_data) + uint16_t **setup, uint8_t min_setup, + uint8_t *num_setup, + uint8_t **param, uint32_t min_param, + uint32_t *num_param, + uint8_t **data, uint32_t min_data, + uint32_t *num_data) { struct cli_trans_state *state = tevent_req_data( req, struct cli_trans_state); @@ -1216,6 +1219,12 @@ NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, return status; } + if ((state->num_rsetup < min_setup) + || (state->rparam.total < min_param) + || (state->rdata.total < min_data)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + if (setup != NULL) { *setup = talloc_move(mem_ctx, &state->rsetup); *num_setup = state->num_rsetup; @@ -1247,9 +1256,9 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t *setup, uint8_t num_setup, uint8_t max_setup, uint8_t *param, uint32_t num_param, uint32_t max_param, uint8_t *data, uint32_t num_data, uint32_t max_data, - uint16_t **rsetup, uint8_t *num_rsetup, - uint8_t **rparam, uint32_t *num_rparam, - uint8_t **rdata, uint32_t *num_rdata) + uint16_t **rsetup, uint8_t min_rsetup, uint8_t *num_rsetup, + uint8_t **rparam, uint32_t min_rparam, uint32_t *num_rparam, + uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata) { TALLOC_CTX *frame = talloc_stackframe(); struct event_context *ev; @@ -1285,8 +1294,9 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli, goto fail; } - status = cli_trans_recv(req, mem_ctx, rsetup, num_rsetup, - rparam, num_rparam, rdata, num_rdata); + status = cli_trans_recv(req, mem_ctx, rsetup, min_rsetup, num_rsetup, + rparam, min_rparam, num_rparam, + rdata, min_rdata, num_rdata); fail: TALLOC_FREE(frame); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index c28664d007..de748d9bbc 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -244,8 +244,8 @@ static void rpc_np_trans_done(struct tevent_req *subreq) req, struct rpc_np_trans_state); NTSTATUS status; - status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, - &state->rdata, &state->rdata_len); + status = cli_trans_recv(subreq, state, NULL, 0, NULL, NULL, 0, NULL, + &state->rdata, 0, &state->rdata_len); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); -- cgit