libsmb: Make cli_query_security_descriptor() async
authorVolker Lendecke <vl@samba.org>
Mon, 9 Nov 2020 20:37:10 +0000 (21:37 +0100)
committerJeremy Allison <jra@samba.org>
Mon, 16 Nov 2020 19:53:45 +0000 (19:53 +0000)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/libsmb/clisecdesc.c
source3/libsmb/proto.h

index f9a7a057ed64e67643037735844e4bc2b6c4777c..a3a955c16d7fa22908f0013a3e6605f09280af57 100644 (file)
 #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;
 }
 
index 8fd3a436fd58e765171d65af47400a65dcffdba3..84dfd2a6e70f5955bf2d9dce74e576ef40458144 100644 (file)
@@ -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,