STEP03c: s3 client
authorStefan Metzmacher <metze@samba.org>
Mon, 13 Jan 2014 09:08:20 +0000 (10:08 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 4 Jun 2019 10:45:39 +0000 (12:45 +0200)
source3/librpc/rpc/dcerpc.h
source3/rpc_client/cli_pipe.c
source3/rpc_client/rpc_client.h

index e032a7479e644a71374e08ce114f13714508339c..4b04dfedc94503a347d79bf7ff9f9b102450c9b0 100644 (file)
@@ -44,6 +44,7 @@ struct pipe_auth_data {
        bool client_hdr_signing;
        bool hdr_signing;
        bool verified_bitmask1;
+       struct dcerpc_security *sec;
 
        struct gensec_security *auth_ctx;
 
index 2c28346cd7febd4342c911add3d37088f161c3c8..217738d53f9e8e5c0423be73e44e89a7864261c3 100644 (file)
@@ -1852,20 +1852,11 @@ static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
 ****************************************************************************/
 
 struct rpc_pipe_bind_state {
-       struct tevent_context *ev;
-       struct rpc_pipe_client *cli;
-       DATA_BLOB rpc_out;
-       bool auth3;
-       uint32_t rpc_call_id;
+       struct dcerpc_presentation *pres[1];
+       struct dcerpc_call *call;
 };
 
-static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
-static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
-                                  struct rpc_pipe_bind_state *state,
-                                  DATA_BLOB *credentials);
-static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
-                                    struct rpc_pipe_bind_state *state,
-                                    DATA_BLOB *credentials);
+static void rpc_pipe_bind_done(struct tevent_req *subreq);
 
 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
                                      struct tevent_context *ev,
@@ -1874,7 +1865,8 @@ struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
 {
        struct tevent_req *req, *subreq;
        struct rpc_pipe_bind_state *state;
-       NTSTATUS status;
+       struct gensec_security *gensec = NULL;
+       struct gensec_security **gensec_ptr = NULL;
 
        req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
        if (req == NULL) {
@@ -1886,238 +1878,54 @@ struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
                (unsigned int)auth->auth_type,
                (unsigned int)auth->auth_level ));
 
-       state->ev = ev;
-       state->cli = cli;
-       state->rpc_call_id = get_rpc_call_id();
+       if (auth->auth_ctx != NULL) {
+               gensec = talloc_get_type_abort(auth->auth_ctx,
+                                              struct gensec_security);
+               gensec_ptr = &gensec;
+       }
 
-       cli->auth = talloc_move(cli, &auth);
+       auth->sec = dcerpc_security_allocate(auth, cli->conn,
+                                            auth->auth_type,
+                                            auth->auth_level,
+                                            gensec_ptr);
+       if (tevent_req_nomem(auth->sec, req)) {
+               return tevent_req_post(req, ev);
+       }
 
-       /* Marshall the outgoing data. */
-       status = create_rpc_bind_req(state, cli,
-                                    cli->auth,
-                                    state->rpc_call_id,
-                                    &cli->abstract_syntax,
-                                    &cli->transfer_syntax,
-                                    &state->rpc_out);
+       cli->auth = talloc_move(cli, &auth);
 
-       if (!NT_STATUS_IS_OK(status) &&
-           !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               goto post_status;
+       state->call = dcerpc_call_allocate(state, cli->assoc, NULL, NULL);
+       if (tevent_req_nomem(state->call, req)) {
+               return tevent_req_post(req, ev);
        }
 
-       subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
-                                  DCERPC_PKT_BIND_ACK, state->rpc_call_id);
-       if (subreq == NULL) {
-               goto fail;
+       state->pres[0] = cli->pres;
+
+       subreq = dcerpc_do_bind_send(state, ev, cli->conn,
+                                    state->call, cli->auth->sec,
+                                    ARRAY_SIZE(state->pres),
+                                    state->pres);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
        }
-       tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
-       return req;
+       tevent_req_set_callback(subreq, rpc_pipe_bind_done, req);
 
- post_status:
-       tevent_req_nterror(req, status);
-       return tevent_req_post(req, ev);
- fail:
-       TALLOC_FREE(req);
-       return NULL;
+       return req;
 }
 
-static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
+static void rpc_pipe_bind_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
-       struct rpc_pipe_bind_state *state = tevent_req_data(
-               req, struct rpc_pipe_bind_state);
-       struct pipe_auth_data *pauth = state->cli->auth;
-       struct gensec_security *gensec_security;
-       struct ncacn_packet *pkt = NULL;
-       struct dcerpc_auth auth;
-       DATA_BLOB auth_token = data_blob_null;
        NTSTATUS status;
 
-       status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
+       status = dcerpc_do_bind_recv(subreq);
        TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
-                         rpccli_pipe_txt(talloc_tos(), state->cli),
-                         nt_errstr(status)));
-               tevent_req_nterror(req, status);
-               return;
-       }
-
-       if (state->auth3) {
-               tevent_req_done(req);
-               return;
-       }
-
-       if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
-               DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
-               tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
-               return;
-       }
-
-       if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
-               if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
-                       if (pauth->client_hdr_signing) {
-                               pauth->hdr_signing = true;
-                       }
-               }
-       }
-
-       state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
-
-       switch(pauth->auth_type) {
-
-       case DCERPC_AUTH_TYPE_NONE:
-               /* Bind complete. */
-               tevent_req_done(req);
-               return;
-
-       default:
-               if (pkt->auth_length == 0) {
-                       tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
-                       return;
-               }
-
-               /* get auth credentials */
-               status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
-                                                 &pkt->u.bind_ack.auth_info,
-                                                 &auth, NULL, true);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
-                                 nt_errstr(status)));
-                       tevent_req_nterror(req, status);
-                       return;
-               }
-
-               if (auth.auth_type != pauth->auth_type) {
-                       DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
-                                 auth.auth_type, pauth->auth_type));
-                       tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
-                       return;
-               }
-
-               if (auth.auth_level != pauth->auth_level) {
-                       DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
-                                 auth.auth_level, pauth->auth_level));
-                       tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
-                       return;
-               }
-
-               if (auth.auth_context_id != pauth->auth_context_id) {
-                       DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
-                                 (unsigned)auth.auth_context_id,
-                                 (unsigned)pauth->auth_context_id));
-                       tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
-                       return;
-               }
-
-               break;
-       }
-
-       /*
-        * For authenticated binds we may need to do 3 or 4 leg binds.
-        */
-
-       switch(pauth->auth_type) {
-
-       case DCERPC_AUTH_TYPE_NONE:
-               /* Bind complete. */
-               tevent_req_done(req);
+       if (tevent_req_nterror(req, status)) {
                return;
-
-       default:
-               gensec_security = pauth->auth_ctx;
-
-
-               status = gensec_update(gensec_security, state,
-                                      auth.credentials, &auth_token);
-               if (NT_STATUS_EQUAL(status,
-                                   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-                       status = rpc_bind_next_send(req, state,
-                                                       &auth_token);
-               } else if (NT_STATUS_IS_OK(status)) {
-                       if (pauth->hdr_signing) {
-                               gensec_want_feature(gensec_security,
-                                                   GENSEC_FEATURE_SIGN_PKT_HEADER);
-                       }
-
-                       if (auth_token.length == 0) {
-                               /* Bind complete. */
-                               tevent_req_done(req);
-                               return;
-                       }
-                       status = rpc_bind_finish_send(req, state,
-                                                       &auth_token);
-               }
-               break;
        }
 
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-       }
-       return;
-}
-
-static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
-                                  struct rpc_pipe_bind_state *state,
-                                  DATA_BLOB *auth_token)
-{
-       struct pipe_auth_data *auth = state->cli->auth;
-       struct tevent_req *subreq;
-       NTSTATUS status;
-
-       /* Now prepare the alter context pdu. */
-       data_blob_free(&state->rpc_out);
-
-       status = create_rpc_alter_context(state, auth,
-                                         state->rpc_call_id,
-                                         &state->cli->abstract_syntax,
-                                         &state->cli->transfer_syntax,
-                                         auth_token,
-                                         &state->rpc_out);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       subreq = rpc_api_pipe_send(state, state->ev, state->cli,
-                                  &state->rpc_out, DCERPC_PKT_ALTER_RESP,
-                                  state->rpc_call_id);
-       if (subreq == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
-                                    struct rpc_pipe_bind_state *state,
-                                    DATA_BLOB *auth_token)
-{
-       struct pipe_auth_data *auth = state->cli->auth;
-       struct tevent_req *subreq;
-       NTSTATUS status;
-
-       state->auth3 = true;
-
-       /* Now prepare the auth3 context pdu. */
-       data_blob_free(&state->rpc_out);
-
-       status = create_rpc_bind_auth3(state, state->cli, auth,
-                                       state->rpc_call_id,
-                                       auth_token,
-                                       &state->rpc_out);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       subreq = rpc_api_pipe_send(state, state->ev, state->cli,
-                                  &state->rpc_out, DCERPC_PKT_AUTH3,
-                                  state->rpc_call_id);
-       if (subreq == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
-       return NT_STATUS_OK;
+       tevent_req_done(req);
 }
 
 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
@@ -2131,12 +1939,7 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
        TALLOC_CTX *frame = talloc_stackframe();
        struct tevent_context *ev;
        NTSTATUS status = NT_STATUS_OK;
-       struct dcerpc_call *call;
-       struct tevent_req *subreq;
-       struct auth_generic_state *auth_generic_ctx;
-       struct gensec_security *gensec = NULL;
-       struct gensec_security **gensec_ptr = NULL;
-       struct dcerpc_presentation *pres[1];
+       struct tevent_req *req;
 
        ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
@@ -2144,34 +1947,17 @@ NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
                goto fail;
        }
 
-       if (auth->auth_ctx != NULL) {
-               gensec = talloc_get_type_abort(auth->auth_ctx,
-                                              struct gensec_security);
-               gensec_ptr = &gensec;
-       }
-
-       cli->sec = dcerpc_security_allocate(cli, cli->conn,
-                                          auth->auth_type,
-                                          auth->auth_level,
-                                          gensec_ptr);
-
-       call = dcerpc_call_allocate(frame, cli->assoc, NULL, NULL);
-
-       pres[0] = cli->pres;
-
-       subreq = dcerpc_do_bind_send(frame, ev, cli->conn, call,
-                                    cli->sec, ARRAY_SIZE(pres), pres);
-
-       if (subreq == NULL) {
+       req = rpc_pipe_bind_send(frame, ev, cli, auth);
+       if (req == NULL) {
                status = NT_STATUS_NO_MEMORY;
                goto fail;
        }
 
-       if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
+       if (!tevent_req_poll_ntstatus(req, ev, &status)) {
                goto fail;
        }
 
-       status = dcerpc_do_bind_recv(subreq);
+       status = rpc_pipe_bind_recv(req);
  fail:
        TALLOC_FREE(frame);
        return status;
@@ -2295,7 +2081,7 @@ static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
 
        state->call = dcerpc_call_allocate(state,
                                           hs->rpc_cli->assoc,
-                                          hs->rpc_cli->sec,
+                                          hs->rpc_cli->auth->sec,
                                           hs->rpc_cli->pres);
 
        if (in_flags & LIBNDR_FLAG_BIGENDIAN) {
@@ -2747,10 +2533,6 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
                                                &result->transport->stream);
        result->pres = dcerpc_presentation_allocate(result, result->conn, table,
                                                    &ndr_transfer_syntax_ndr);
-       result->sec = dcerpc_security_allocate(result, result->conn,
-                                              DCERPC_AUTH_TYPE_NONE,
-                                              DCERPC_AUTH_LEVEL_NONE,
-                                              NULL);
 
        result->binding_handle = rpccli_bh_create(result, NULL, table);
        if (result->binding_handle == NULL) {
@@ -3007,10 +2789,6 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
                                                &result->transport->stream);
        result->pres = dcerpc_presentation_allocate(result, result->conn, table,
                                                    &ndr_transfer_syntax_ndr);
-       result->sec = dcerpc_security_allocate(result, result->conn,
-                                              DCERPC_AUTH_TYPE_NONE,
-                                              DCERPC_AUTH_LEVEL_NONE,
-                                              NULL);
 
        result->binding_handle = rpccli_bh_create(result, NULL, table);
        if (result->binding_handle == NULL) {
@@ -3098,10 +2876,6 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
                                           tstream_smbXcli_np_use_trans);
        result->pres = dcerpc_presentation_allocate(result, result->conn, table,
                                                    &ndr_transfer_syntax_ndr);
-       result->sec = dcerpc_security_allocate(result, result->conn,
-                                              DCERPC_AUTH_TYPE_NONE,
-                                              DCERPC_AUTH_LEVEL_NONE,
-                                              NULL);
 
        np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
        if (np_ref == NULL) {
index 965aa42a0a280d6943348c2e531e596a26972407..9234365cd6f0fb170d4d6310a11f2b3629d8ed16 100644 (file)
@@ -44,7 +44,6 @@ struct rpc_pipe_client {
        struct dcerpc_association *assoc;
        struct dcerpc_connection *conn;
        struct dcerpc_presentation *pres;
-       struct dcerpc_security *sec;
 
        char *desthost;
        char *srv_name_slash;