Revert "Revert "s3:rpc_client: implement preauth hashing support""
authorStefan Metzmacher <metze@samba.org>
Tue, 23 Apr 2024 16:16:43 +0000 (18:16 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 23 Apr 2024 16:16:43 +0000 (18:16 +0200)
This reverts commit 75fd726e66ebbd1f73992ecd89d5f976374b3c96.

source3/rpc_client/cli_pipe.c
source3/rpc_client/rpc_client.h

index cf551f6f548fa9c63867d16369c1104bc142b5e9..d1d48af3d42f92b30a8ef724f2d92ce9bf0647a0 100644 (file)
@@ -387,6 +387,14 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
         */
        *rdata = *pdu;
 
+       ret = dcerpc_sec_vt_preauth_update(&cli->preauth,
+                                          pkt,
+                                          pdu,
+                                          &cli->preauth);
+       if (!NT_STATUS_IS_OK(ret)) {
+               return ret;
+       }
+
        if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
            !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
                /*
@@ -1132,7 +1140,8 @@ static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        struct ndr_syntax_id bind_time_features = dcerpc_construct_bind_time_features(
                        DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING |
-                       DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN);
+                       DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN |
+                       DCERPC_BIND_TIME_SUPPORT_PREAUTH);
        struct dcerpc_ctx_list ctx_list[2] = {
                [0] = {
                        .context_id = 0,
@@ -1250,6 +1259,7 @@ struct rpc_api_pipe_req_state {
        uint32_t req_trailer_sent;
        bool verify_bitmask1;
        bool verify_pcontext;
+       bool verify_preauth;
        DATA_BLOB rpc_out;
        DATA_BLOB reply_pdu;
 };
@@ -1395,6 +1405,38 @@ static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *stat
                };
        }
 
+       if (!state->cli->verified_preauth) {
+               struct dcerpc_sec_vt *c = NULL;
+               DATA_BLOB buffer = { .length = 0, };
+               NTSTATUS status;
+
+               t->commands = talloc_realloc(t, t->commands,
+                                            struct dcerpc_sec_vt,
+                                            t->count.count + 1);
+               if (t->commands == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               c = &t->commands[t->count.count++];
+               *c = (struct dcerpc_sec_vt) {
+                       .command = DCERPC_SEC_VT_COMMAND_PREAUTH,
+               };
+
+               generate_random_buffer(c->u.preauth.salt,
+                                      sizeof(c->u.preauth.salt));
+
+               buffer = data_blob_const(c->u.preauth.salt,
+                                        sizeof(c->u.preauth.salt));
+
+               status = dcerpc_sec_vt_preauth_update(&state->cli->preauth,
+                                                     NULL, &buffer,
+                                                     &c->u.preauth);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               state->verify_preauth = true;
+       }
+
        if (t->count.count == 0) {
                TALLOC_FREE(t);
                return NT_STATUS_OK;
@@ -1635,6 +1677,10 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq)
                state->cli->verified_pcontext = true;
        }
 
+       if (state->verify_preauth) {
+               state->cli->verified_preauth = true;
+       }
+
        tevent_req_done(req);
 }
 
@@ -1855,6 +1901,14 @@ struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
+       status = dcerpc_sec_vt_preauth_update(&state->cli->preauth,
+                                             NULL,
+                                             &state->rpc_out,
+                                             &state->cli->preauth);
+       if (tevent_req_nterror(req, status)) {
+               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 (tevent_req_nomem(subreq, req)) {
@@ -2011,6 +2065,14 @@ static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
                return status;
        }
 
+       status = dcerpc_sec_vt_preauth_update(&state->cli->preauth,
+                                             NULL,
+                                             &state->rpc_out,
+                                             &state->cli->preauth);
+       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);
@@ -2042,6 +2104,14 @@ static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
                return status;
        }
 
+       status = dcerpc_sec_vt_preauth_update(&state->cli->preauth,
+                                             NULL,
+                                             &state->rpc_out,
+                                             &state->cli->preauth);
+       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);
index 55eb4dec90bbe8e2701c8de1887dd25f0f7c36c2..811d34f4c640c1d11dcc611a5e04216e840f9978 100644 (file)
@@ -48,6 +48,20 @@ struct rpc_pipe_client {
        struct ndr_syntax_id transfer_syntax;
        bool verified_pcontext;
 
+       /*
+        * This is per transport connection.
+        */
+       struct dcerpc_sec_vt_preauth preauth;
+
+       /*
+        * This needs to be more complex if we really support multiple
+        * security contexts and multiple presentation contexts.
+        *
+        * We need to verify the preauth hash once for each combination
+        * of presentation context and security context.
+        */
+       bool verified_preauth;
+
        char *desthost;
        char *srv_name_slash;