From: Volker Lendecke Date: Mon, 9 Nov 2020 20:37:10 +0000 (+0100) Subject: libsmb: Make cli_query_security_descriptor() async X-Git-Tag: samba-4.14.0rc1~613 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=207ca06189e1bd3e536dbe35ff0ef0b763c5e152;p=thirdparty%2Fsamba.git libsmb: Make cli_query_security_descriptor() async Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c index f9a7a057ed6..a3a955c16d7 100644 --- a/source3/libsmb/clisecdesc.c +++ b/source3/libsmb/clisecdesc.c @@ -21,65 +21,179 @@ #include "libsmb/libsmb.h" #include "../libcli/security/secdesc.h" #include "../libcli/smb/smbXcli_base.h" +#include "lib/util/tevent_ntstatus.h" -NTSTATUS cli_query_security_descriptor(struct cli_state *cli, - uint16_t fnum, - uint32_t sec_info, - TALLOC_CTX *mem_ctx, - struct security_descriptor **sd) -{ +struct cli_query_security_descriptor_state { uint8_t param[8]; - uint8_t *rdata=NULL; - uint32_t rdata_count=0; - NTSTATUS status; - struct security_descriptor *lsd; + DATA_BLOB outbuf; +}; + +static void cli_query_security_descriptor_done1(struct tevent_req *subreq); +static void cli_query_security_descriptor_done2(struct tevent_req *subreq); + +struct tevent_req *cli_query_security_descriptor_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint32_t sec_info) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct cli_query_security_descriptor_state *state = NULL; + + req = tevent_req_create( + mem_ctx, &state, struct cli_query_security_descriptor_state); + if (req == NULL) { + return NULL; + } if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - return cli_smb2_query_security_descriptor(cli, - fnum, - sec_info, - mem_ctx, - sd); + subreq = cli_smb2_query_info_fnum_send( + state, /* mem_ctx */ + ev, /* ev */ + cli, /* cli */ + fnum, /* fnum */ + 3, /* in_info_type */ + 0, /* in_info_class */ + 0xFFFF, /* in_max_output_length */ + NULL, /* in_input_buffer */ + sec_info, /* in_additional_info */ + 0); /* in_flags */ + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback( + subreq, cli_query_security_descriptor_done2, req); + return req; } - SIVAL(param, 0, fnum); - SIVAL(param, 4, sec_info); + PUSH_LE_U32(state->param, 0, fnum); + PUSH_LE_U32(state->param, 4, sec_info); - status = cli_trans(talloc_tos(), cli, SMBnttrans, - NULL, -1, /* name, fid */ - NT_TRANSACT_QUERY_SECURITY_DESC, 0, /* function, flags */ - NULL, 0, 0, /* setup, length, max */ - param, 8, 4, /* param, length, max */ - NULL, 0, 0x10000, /* data, length, max */ - NULL, /* recv_flags2 */ - NULL, 0, NULL, /* rsetup, length */ - NULL, 0, NULL, - &rdata, 0, &rdata_count); + subreq = cli_trans_send( + state, /* mem_ctx */ + ev, /* ev */ + cli, /* cli */ + 0, /* additional_flags2 */ + SMBnttrans, /* cmd */ + NULL, /* pipe_name */ + -1, /* fid */ + NT_TRANSACT_QUERY_SECURITY_DESC, /* function */ + 0, /* flags */ + NULL, /* setup */ + 0, /* num_setup */ + 0, /* max_setup */ + state->param, /* param */ + 8, /* num_param */ + 4, /* max_param */ + NULL, /* data */ + 0, /* num_data */ + 0x10000); /* max_data */ + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback( + subreq, cli_query_security_descriptor_done1, req); + return req; +} - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("NT_TRANSACT_QUERY_SECURITY_DESC failed: %s\n", - nt_errstr(status))); - goto cleanup; +static void cli_query_security_descriptor_done1(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_query_security_descriptor_state *state = tevent_req_data( + req, struct cli_query_security_descriptor_state); + NTSTATUS status; + uint32_t len; + + status = cli_trans_recv( + subreq, /* req */ + state, /* mem_ctx */ + NULL, /* recv_flags2 */ + NULL, /* setup */ + 0, /* min_setup */ + NULL, /* num_setup */ + NULL, /* param */ + 0, /* min_param */ + NULL, /* num_param */ + &state->outbuf.data, /* data */ + 0, /* min_data */ + &len); /* num_data */ + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; } + state->outbuf.length = len; /* uint32_t -> size_t */ + tevent_req_done(req); +} - status = unmarshall_sec_desc(mem_ctx, (uint8_t *)rdata, rdata_count, - &lsd); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("unmarshall_sec_desc failed: %s\n", - nt_errstr(status))); - goto cleanup; +static void cli_query_security_descriptor_done2(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_query_security_descriptor_state *state = tevent_req_data( + req, struct cli_query_security_descriptor_state); + NTSTATUS status; + + status = cli_smb2_query_info_fnum_recv(subreq, state, &state->outbuf); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; } + tevent_req_done(req); +} + +NTSTATUS cli_query_security_descriptor_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct security_descriptor **sd) +{ + struct cli_query_security_descriptor_state *state = tevent_req_data( + req, struct cli_query_security_descriptor_state); + NTSTATUS status = NT_STATUS_OK; + if (tevent_req_is_nterror(req, &status)) { + goto done; + } if (sd != NULL) { - *sd = lsd; - } else { - TALLOC_FREE(lsd); + status = unmarshall_sec_desc( + mem_ctx, state->outbuf.data, state->outbuf.length, sd); } +done: + tevent_req_received(req); + return status; +} - cleanup: - - TALLOC_FREE(rdata); +NTSTATUS cli_query_security_descriptor(struct cli_state *cli, + uint16_t fnum, + uint32_t sec_info, + TALLOC_CTX *mem_ctx, + struct security_descriptor **sd) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_NO_MEMORY; + if (smbXcli_conn_has_async_calls(cli->conn)) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = cli_query_security_descriptor_send( + frame, ev, cli, fnum, sec_info); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = cli_query_security_descriptor_recv(req, mem_ctx, sd); + fail: + TALLOC_FREE(frame); return status; } diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h index 8fd3a436fd5..84dfd2a6e70 100644 --- a/source3/libsmb/proto.h +++ b/source3/libsmb/proto.h @@ -937,6 +937,16 @@ NTSTATUS cli_splice(struct cli_state *srccli, struct cli_state *dstcli, /* The following definitions come from libsmb/clisecdesc.c */ +struct tevent_req *cli_query_security_descriptor_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint32_t sec_info); +NTSTATUS cli_query_security_descriptor_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct security_descriptor **sd); NTSTATUS cli_query_security_descriptor(struct cli_state *cli, uint16_t fnum, uint32_t sec_info,