STEP04c: HACK: s4:librpc: use dcerpc_do_bind() and dcerpc_do_request
authorStefan Metzmacher <metze@samba.org>
Tue, 21 Jan 2014 15:39:36 +0000 (16:39 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 4 Jun 2019 10:45:39 +0000 (12:45 +0200)
source4/librpc/rpc/dcerpc.c
source4/librpc/rpc/dcerpc_auth.c
source4/librpc/rpc/dcerpc_smb.c
source4/librpc/rpc/dcerpc_sock.c

index 6a59f238217eb9c409c2cb6ffe9a645e2655d68f..b5bd3fb81b7192abdc6ca27bf734becd9046ab09 100644 (file)
@@ -141,21 +141,7 @@ static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
-       c->assoc = dcerpc_association_create(c, 0);
-       if (c->assoc == NULL) {
-               talloc_free(c);
-               return NULL;
-       }
-       //c->conn = dcerpc_connection_create(c, c->assoc,
        c->call_id = 1;
-//     c->security_state.sec = dcerpc_security_allocate(c, c->conn,
-//                                                      DCERPC_AUTH_TYPE_NONE,
-//                                                      DCERPC_AUTH_LEVEL_NONE,
-//                                                      NULL);
-//     if (c->security_state.sec == NULL) {
-//             talloc_free(c);
-//             return NULL;
-//     }
        c->security_state.auth_type = DCERPC_AUTH_TYPE_NONE;
        c->security_state.auth_level = DCERPC_AUTH_LEVEL_NONE;
        c->security_state.auth_context_id = 0;
@@ -205,6 +191,10 @@ static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
                return false;
        }
 
+       if (!hs->p->conn->conn) {
+               return false;
+       }
+
        return true;
 }
 
@@ -247,12 +237,13 @@ static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h,
 struct dcerpc_bh_raw_call_state {
        struct tevent_context *ev;
        struct dcerpc_binding_handle *h;
+       struct dcerpc_call *call;
        DATA_BLOB in_data;
        DATA_BLOB out_data;
        uint32_t out_flags;
 };
 
-static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
+static void dcerpc_bh_raw_call_done(struct tevent_req *subreq);
 
 static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
                                                  struct tevent_context *ev,
@@ -268,7 +259,8 @@ static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
        struct tevent_req *req;
        struct dcerpc_bh_raw_call_state *state;
        bool ok;
-       struct rpc_request *subreq;
+       struct tevent_req *subreq;
+       bool bigendian = false;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct dcerpc_bh_raw_call_state);
@@ -286,58 +278,54 @@ static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
-       subreq = dcerpc_request_send(state,
-                                    hs->p,
-                                    object,
-                                    opnum,
-                                    &state->in_data);
+       state->call = dcerpc_call_allocate(state, hs->p->conn->assoc,
+                                          hs->p->conn->security_state.sec,
+                                          hs->p->pres);
+       if (tevent_req_nomem(state->call, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       if (in_flags & LIBNDR_FLAG_BIGENDIAN) {
+               bigendian = true;
+       }
+
+       subreq = dcerpc_do_request_send(state, ev,
+                                       hs->p->conn->conn,
+                                       state->call,
+                                       object,
+                                       opnum,
+                                       &state->in_data,
+                                       bigendian);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
-       subreq->async.callback = dcerpc_bh_raw_call_done;
-       subreq->async.private_data = req;
+       tevent_req_set_callback(subreq, dcerpc_bh_raw_call_done, req);
 
        return req;
 }
 
-static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
+static void dcerpc_bh_raw_call_done(struct tevent_req *subreq)
 {
        struct tevent_req *req =
-               talloc_get_type_abort(subreq->async.private_data,
+               tevent_req_callback_data(subreq,
                struct tevent_req);
        struct dcerpc_bh_raw_call_state *state =
                tevent_req_data(req,
                struct dcerpc_bh_raw_call_state);
        NTSTATUS status;
-       uint32_t fault_code;
-
-       state->out_flags = 0;
-       if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
-               state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
-       }
-
-       fault_code = subreq->fault_code;
+       bool bigendian = false;
 
-       status = dcerpc_request_recv(subreq, state, &state->out_data);
-       if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-               status = dcerpc_fault_to_nt_status(fault_code);
+       status = dcerpc_do_request_recv(subreq, state,
+                                       &state->out_data,
+                                       &bigendian);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
        }
 
-       /*
-        * We trigger the callback in the next event run
-        * because the code in this file might trigger
-        * multiple request callbacks from within a single
-        * while loop.
-        *
-        * In order to avoid segfaults from within
-        * dcerpc_connection_dead() we call
-        * tevent_req_defer_callback().
-        */
-       tevent_req_defer_callback(req, state->ev);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-               return;
+       state->out_flags = 0;
+       if (bigendian) {
+               state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
        }
 
        tevent_req_done(req);
index 8327bde67440051890f77a8f944beb4901cc6d98..dc3daaccd57485e420ea6f243e09c8cadd334a6b 100644 (file)
@@ -28,6 +28,7 @@
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/rpc/dcerpc_proto.h"
 #include "param/param.h"
+#include "librpc/rpc/dcerpc_connection.h"
 
 /*
   return the rpc syntax and transfer syntax given the pipe uuid and version
@@ -76,10 +77,23 @@ struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
 
        struct composite_context *c;
        struct tevent_req *subreq;
+       struct dcerpc_call *call;
 
        c = composite_create(mem_ctx, p->conn->event_ctx);
        if (c == NULL) return NULL;
 
+       if (p->conn->security_state.sec != NULL) {
+               composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+               return c;
+       }
+
+       p->conn->security_state.sec = dcerpc_security_allocate(p->conn,
+                                                       p->conn->conn,
+                                                       DCERPC_AUTH_TYPE_NONE,
+                                                       DCERPC_AUTH_LEVEL_NONE,
+                                                       NULL);
+       if (composite_nomem(p->conn->security_state.sec, c)) return c;
+
        c->status = dcerpc_init_syntaxes(p, table,
                                         &syntax, &transfer_syntax);
        if (!NT_STATUS_IS_OK(c->status)) {
@@ -89,8 +103,17 @@ struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
                return c;
        }
 
-       subreq = dcerpc_bind_send(mem_ctx, p->conn->event_ctx, p,
-                                 &syntax, &transfer_syntax);
+       p->pres = dcerpc_presentation_allocate(p, p->conn->conn,
+                                              table, &transfer_syntax);
+       if (composite_nomem(p->pres, c)) return c;
+
+       call = dcerpc_call_allocate(c, p->conn->assoc, NULL, NULL);
+       if (composite_nomem(call, c)) return c;
+
+       subreq = dcerpc_do_bind_send(call, p->conn->event_ctx,
+                                    p->conn->conn, call,
+                                    p->conn->security_state.sec,
+                                    1, &p->pres);
        if (composite_nomem(subreq, c)) return c;
        tevent_req_set_callback(subreq, dcerpc_bind_auth_none_done, c);
 
@@ -103,7 +126,7 @@ static void dcerpc_bind_auth_none_done(struct tevent_req *subreq)
                tevent_req_callback_data(subreq,
                struct composite_context);
 
-       ctx->status = dcerpc_bind_recv(subreq);
+       ctx->status = dcerpc_do_bind_recv(subreq);
        TALLOC_FREE(subreq);
        if (!composite_is_ok(ctx)) return;
 
@@ -123,174 +146,19 @@ NTSTATUS dcerpc_bind_auth_none_recv(struct composite_context *ctx)
 
 struct bind_auth_state {
        struct dcerpc_pipe *pipe;
-       struct ndr_syntax_id syntax;
-       struct ndr_syntax_id transfer_syntax;
-       struct dcerpc_auth out_auth_info;
-       struct dcerpc_auth in_auth_info;
-       bool more_processing;   /* Is there anything more to do after the
-                                * first bind itself received? */
 };
 
-static void bind_auth_next_gensec_done(struct tevent_req *subreq);
-static void bind_auth_recv_alter(struct tevent_req *subreq);
-
-static void bind_auth_next_step(struct composite_context *c)
-{
-       struct bind_auth_state *state;
-       struct dcecli_security *sec;
-       struct tevent_req *subreq;
-
-       state = talloc_get_type(c->private_data, struct bind_auth_state);
-       sec = &state->pipe->conn->security_state;
-
-       if (state->in_auth_info.auth_type != sec->auth_type) {
-               composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
-               return;
-       }
-
-       if (state->in_auth_info.auth_level != sec->auth_level) {
-               composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
-               return;
-       }
-
-       if (state->in_auth_info.auth_context_id != sec->auth_context_id) {
-               composite_error(c, NT_STATUS_RPC_PROTOCOL_ERROR);
-               return;
-       }
-
-       state->out_auth_info = (struct dcerpc_auth) {
-               .auth_type = sec->auth_type,
-               .auth_level = sec->auth_level,
-               .auth_context_id = sec->auth_context_id,
-       };
-
-       /* The status value here, from GENSEC is vital to the security
-        * of the system.  Even if the other end accepts, if GENSEC
-        * claims 'MORE_PROCESSING_REQUIRED' then you must keep
-        * feeding it blobs, or else the remote host/attacker might
-        * avoid mutal authentication requirements.
-        *
-        * Likewise, you must not feed GENSEC too much (after the OK),
-        * it doesn't like that either
-        */
-
-       state->pipe->inhibit_timeout_processing = true;
-       state->pipe->timed_out = false;
-
-       subreq = gensec_update_send(state,
-                                   state->pipe->conn->event_ctx,
-                                   sec->generic_state,
-                                   state->in_auth_info.credentials);
-       if (composite_nomem(subreq, c)) return;
-       tevent_req_set_callback(subreq, bind_auth_next_gensec_done, c);
-}
-
-static void bind_auth_next_gensec_done(struct tevent_req *subreq)
-{
-       struct composite_context *c =
-               tevent_req_callback_data(subreq,
-               struct composite_context);
-       struct bind_auth_state *state =
-               talloc_get_type_abort(c->private_data,
-               struct bind_auth_state);
-       struct dcerpc_pipe *p = state->pipe;
-       struct dcecli_security *sec = &p->conn->security_state;
-       bool more_processing = false;
-
-       state->pipe->inhibit_timeout_processing = false;
-
-       c->status = gensec_update_recv(subreq, state,
-                                      &state->out_auth_info.credentials);
-       TALLOC_FREE(subreq);
-
-       if (NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               more_processing = true;
-               c->status = NT_STATUS_OK;
-       }
-
-       if (!composite_is_ok(c)) return;
-
-       if (!more_processing) {
-               if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) {
-                       gensec_want_feature(sec->generic_state,
-                                       GENSEC_FEATURE_SIGN_PKT_HEADER);
-               }
-       }
-
-       if (state->out_auth_info.credentials.length == 0) {
-               composite_done(c);
-               return;
-       }
-
-       state->in_auth_info = (struct dcerpc_auth) {
-               .auth_type = DCERPC_AUTH_TYPE_NONE,
-       };
-       sec->tmp_auth_info.in = &state->in_auth_info;
-       sec->tmp_auth_info.mem = state;
-       sec->tmp_auth_info.out = &state->out_auth_info;
-
-       if (!more_processing) {
-               /* NO reply expected, so just send it */
-               c->status = dcerpc_auth3(state->pipe, state);
-               if (!composite_is_ok(c)) return;
-
-               composite_done(c);
-               return;
-       }
-
-       /* We are demanding a reply, so use a request that will get us one */
-
-       subreq = dcerpc_alter_context_send(state, state->pipe->conn->event_ctx,
-                                          state->pipe,
-                                          &state->pipe->syntax,
-                                          &state->pipe->transfer_syntax);
-       if (composite_nomem(subreq, c)) return;
-       tevent_req_set_callback(subreq, bind_auth_recv_alter, c);
-}
-
-
-static void bind_auth_recv_alter(struct tevent_req *subreq)
-{
-       struct composite_context *c =
-               tevent_req_callback_data(subreq,
-               struct composite_context);
-       struct bind_auth_state *state = talloc_get_type(c->private_data,
-                                                       struct bind_auth_state);
-       struct dcecli_security *sec = &state->pipe->conn->security_state;
-
-       ZERO_STRUCT(sec->tmp_auth_info);
-
-       c->status = dcerpc_alter_context_recv(subreq);
-       TALLOC_FREE(subreq);
-       if (!composite_is_ok(c)) return;
-
-       bind_auth_next_step(c);
-}
-
-
 static void bind_auth_recv_bindreply(struct tevent_req *subreq)
 {
        struct composite_context *c =
                tevent_req_callback_data(subreq,
                struct composite_context);
-       struct bind_auth_state *state = talloc_get_type(c->private_data,
-                                                       struct bind_auth_state);
-       struct dcecli_security *sec = &state->pipe->conn->security_state;
 
-       ZERO_STRUCT(sec->tmp_auth_info);
-
-       c->status = dcerpc_bind_recv(subreq);
+       c->status = dcerpc_do_bind_recv(subreq);
        TALLOC_FREE(subreq);
        if (!composite_is_ok(c)) return;
 
-       if (!state->more_processing) {
-               /* The first gensec_update has not requested a second run, so
-                * we're done here. */
-               composite_done(c);
-               return;
-       }
-
-       bind_auth_next_step(c);
+       composite_done(c);
 }
 
 
@@ -320,6 +188,8 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
        struct bind_auth_state *state;
        struct dcecli_security *sec;
        struct tevent_req *subreq;
+       struct dcerpc_call *call;
+       struct ndr_syntax_id syntax, transfer_syntax;
        const char *target_principal = NULL;
 
        /* composite context allocation and setup */
@@ -332,10 +202,10 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
 
        state->pipe = p;
 
-       c->status = dcerpc_init_syntaxes(p, table,
-                                        &state->syntax,
-                                        &state->transfer_syntax);
-       if (!composite_is_ok(c)) return c;
+       if (p->conn->security_state.sec != NULL) {
+               composite_error(c, NT_STATUS_INVALID_PARAMETER_MIX);
+               return c;
+       }
 
        sec = &p->conn->security_state;
 
@@ -401,92 +271,29 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
                return c;
        }
 
-       sec->auth_type = auth_type;
-       sec->auth_level = auth_level,
-       /*
-        * We use auth_context_id = 1 as some older
-        * Samba versions (<= 4.2.3) use that value hardcoded
-        * in a response.
-        */
-       sec->auth_context_id = 1;
-
-       state->out_auth_info = (struct dcerpc_auth) {
-               .auth_type = sec->auth_type,
-               .auth_level = sec->auth_level,
-               .auth_context_id = sec->auth_context_id,
-       };
-
-       /* The status value here, from GENSEC is vital to the security
-        * of the system.  Even if the other end accepts, if GENSEC
-        * claims 'MORE_PROCESSING_REQUIRED' then you must keep
-        * feeding it blobs, or else the remote host/attacker might
-        * avoid mutal authentication requirements.
-        *
-        * Likewise, you must not feed GENSEC too much (after the OK),
-        * it doesn't like that either
-        */
-
-       state->pipe->inhibit_timeout_processing = true;
-       state->pipe->timed_out = false;
-
-       subreq = gensec_update_send(state,
-                                   p->conn->event_ctx,
-                                   sec->generic_state,
-                                   data_blob_null);
-       if (composite_nomem(subreq, c)) return c;
-       tevent_req_set_callback(subreq, dcerpc_bind_auth_gensec_done, c);
-
-       return c;
-}
-
-static void dcerpc_bind_auth_gensec_done(struct tevent_req *subreq)
-{
-       struct composite_context *c =
-               tevent_req_callback_data(subreq,
-               struct composite_context);
-       struct bind_auth_state *state =
-               talloc_get_type_abort(c->private_data,
-               struct bind_auth_state);
-       struct dcerpc_pipe *p = state->pipe;
-       struct dcecli_security *sec = &p->conn->security_state;
-
-       state->pipe->inhibit_timeout_processing = false;
-
-       c->status = gensec_update_recv(subreq, state,
-                                      &state->out_auth_info.credentials);
-       TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(c->status) &&
-           !NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               composite_error(c, c->status);
-               return;
-       }
+       sec->sec = dcerpc_security_allocate(p->conn,
+                                           p->conn->conn,
+                                           auth_type, auth_level,
+                                           &sec->generic_state);
+       if (composite_nomem(sec->sec, c)) return c;
 
-       state->more_processing = NT_STATUS_EQUAL(c->status,
-                                                NT_STATUS_MORE_PROCESSING_REQUIRED);
+       c->status = dcerpc_init_syntaxes(p, table,
+                                        &syntax,
+                                        &transfer_syntax);
+       if (!composite_is_ok(c)) return c;
 
-       if (state->out_auth_info.credentials.length == 0) {
-               composite_done(c);
-               return;
-       }
+       p->pres = dcerpc_presentation_allocate(p, p->conn->conn,
+                                              table, &transfer_syntax);
+       if (composite_nomem(p->pres, c)) return c;
 
-       if (gensec_have_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER)) {
-               if (sec->auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
-                       state->pipe->conn->flags |= DCERPC_PROPOSE_HEADER_SIGNING;
-               }
-       }
+       call = dcerpc_call_allocate(c, p->conn->assoc, NULL, NULL);
+       if (composite_nomem(call, c)) return c;
 
-       state->in_auth_info = (struct dcerpc_auth) {
-               .auth_type = DCERPC_AUTH_TYPE_NONE,
-       };
-       sec->tmp_auth_info.in = &state->in_auth_info;
-       sec->tmp_auth_info.mem = state;
-       sec->tmp_auth_info.out = &state->out_auth_info;
-
-       /* The first request always is a dcerpc_bind. The subsequent ones
-        * depend on gensec results */
-       subreq = dcerpc_bind_send(state, p->conn->event_ctx, p,
-                                 &state->syntax, &state->transfer_syntax);
-       if (composite_nomem(subreq, c)) return;
+       subreq = dcerpc_do_bind_send(call, p->conn->event_ctx,
+                                    p->conn->conn, call,
+                                    p->conn->security_state.sec,
+                                    1, &p->pres);
+       if (composite_nomem(subreq, c)) return c;
        tevent_req_set_callback(subreq, bind_auth_recv_bindreply, c);
 
        return;
index 1487bde75a5890f213cc3da8f9970bc7092770f1..468f3989802021c99a3ff2a4db7687c4b4ca77c7 100644 (file)
@@ -32,6 +32,7 @@
 #include "librpc/rpc/dcerpc.h"
 #include "librpc/rpc/dcerpc_proto.h"
 #include "libcli/composite/composite.h"
+#include "librpc/rpc/dcerpc_connection.h"
 
 /* transport private information used by SMB pipe transport */
 struct smb_private {
@@ -132,23 +133,29 @@ static void dcerpc_pipe_open_smb_done(struct tevent_req *subreq)
                struct dcerpc_pipe_open_smb_state);
        struct composite_context *ctx = state->ctx;
        struct dcecli_connection *c = state->c;
+       struct tstream_context *stream;
 
-       ctx->status = tstream_smbXcli_np_open_recv(subreq,
-                                                  state->smb,
-                                                  &state->c->transport.stream);
+       ctx->status = tstream_smbXcli_np_open_recv(subreq, state, &stream);
        TALLOC_FREE(subreq);
        if (!composite_is_ok(ctx)) return;
 
-       state->c->transport.write_queue =
-               tevent_queue_create(state->c, "dcerpc_smb write queue");
-       if (composite_nomem(state->c->transport.write_queue, ctx)) return;
-
        /*
          fill in the transport methods
        */
        c->transport.transport       = NCACN_NP;
        c->transport.private_data    = NULL;
 
+       c->assoc = dcerpc_association_create(c, 0);
+       if (composite_nomem(c->assoc, ctx)) {
+               return;
+       }
+       c->conn = dcerpc_connection_create(c, c->assoc, &stream);
+       if (composite_nomem(c->conn, ctx)) {
+               return;
+       }
+       dcerpc_connection_set_use_trans_fn(c->conn,
+                                          tstream_smbXcli_np_use_trans);
+
        /*
         * Windows uses 4280 for ncacn_np,
         * so we also use it, this is what our
index e7ecca73e3c19e9ee31aecca8b4cc47900a2adc6..b13e7a6945ccd957cda2c13ef9061ee2e616b1ba 100644 (file)
@@ -31,6 +31,7 @@
 #include "librpc/rpc/dcerpc_proto.h"
 #include "libcli/resolve/resolve.h"
 #include "librpc/rpc/rpc_common.h"
+#include "librpc/rpc/dcerpc_connection.h"
 
 struct pipe_open_socket_state {
        struct dcecli_connection *conn;
@@ -52,6 +53,7 @@ static void continue_socket_connect(struct composite_context *ctx)
                c->private_data, struct pipe_open_socket_state);
        int rc;
        int sock_fd;
+       struct tstream_context *stream;
 
        /* make it easier to write a function calls */
        conn = s->conn;
@@ -96,19 +98,19 @@ static void continue_socket_connect(struct composite_context *ctx)
        conn->transport.pending_reads = 0;
        conn->server_name   = strupper_talloc(conn, s->target_hostname);
 
-       rc = tstream_bsd_existing_socket(conn, sock_fd,
-                                        &conn->transport.stream);
+       rc = tstream_bsd_existing_socket(conn, sock_fd, &stream);
        if (rc < 0) {
                close(sock_fd);
                composite_error(c, NT_STATUS_NO_MEMORY);
                return;
        }
 
-       conn->transport.write_queue =
-               tevent_queue_create(conn, "dcerpc sock write queue");
-       if (conn->transport.write_queue == NULL) {
-               TALLOC_FREE(conn->transport.stream);
-               composite_error(c, NT_STATUS_NO_MEMORY);
+       conn->assoc = dcerpc_association_create(conn, 0);
+       if (composite_nomem(conn->assoc, c)) {
+               return;
+       }
+       conn->conn = dcerpc_connection_create(conn, conn->assoc, &stream);
+       if (composite_nomem(conn->conn, c)) {
                return;
        }