]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
dcesrv_core: wrap gensec_*() calls in [un]become_root() calls
authorStefan Metzmacher <metze@samba.org>
Sat, 22 Jan 2022 00:08:26 +0000 (01:08 +0100)
committerJule Anger <janger@samba.org>
Sun, 30 Jan 2022 09:15:13 +0000 (09:15 +0000)
This is important for the source3/rpc_server code as it might
be called embedded in smbd and may not run as root with access
to our private tdb/ldb files.

Note this is only really needed for 4.15 and older, as
we no longer run the rpc_server embedded in smbd,
but we better be consistent for now.

This should be able to fix the problem the printing no longer works
on Windows 7 with 2021-10 monthly rollup patch (KB5006743).

Windows uses NTLMSSP with privacy at the DCERPC layer on top
of NCACN_NP (smb).

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14867

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(similar to commit 0651fa474cd68b18d8eb9bdc7c4ba5b847ba9ad9)

librpc/rpc/dcesrv_auth.c
librpc/rpc/dcesrv_core.c
librpc/rpc/dcesrv_core.h
source3/rpc_server/rpc_config.c
source4/rpc_server/service_rpc.c

index 9d8df6c42e29dd49c66e56d19baa494c1a1bff38..b4a29ea9ab4eaa34c988d4948f150f663d0d0fd4 100644 (file)
@@ -81,6 +81,7 @@ static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call)
 {
        struct dcesrv_connection *dce_conn = call->conn;
        struct dcesrv_auth *auth = call->auth_state;
+       struct dcesrv_context_callbacks *cb = &call->conn->dce_ctx->callbacks;
        NTSTATUS status;
 
        if (auth->auth_started) {
@@ -129,9 +130,11 @@ static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call)
        auth->auth_level = call->in_auth_info.auth_level;
        auth->auth_context_id = call->in_auth_info.auth_context_id;
 
+       cb->auth.become_root();
        status = call->conn->dce_ctx->callbacks.auth.gensec_prepare(auth,
                                                call,
                                                &auth->gensec_security);
+       cb->auth.unbecome_root();
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Failed to call samba_server_gensec_start %s\n",
                          nt_errstr(status)));
@@ -324,6 +327,7 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
 NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
 {
        struct dcesrv_auth *auth = call->auth_state;
+       struct dcesrv_context_callbacks *cb = &call->conn->dce_ctx->callbacks;
        const char *pdu = "<unknown>";
 
        switch (call->pkt.ptype) {
@@ -354,9 +358,11 @@ NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
                return status;
        }
 
+       cb->auth.become_root();
        status = gensec_session_info(auth->gensec_security,
                                     auth,
                                     &auth->session_info);
+       cb->auth.unbecome_root();
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Failed to establish session_info: %s\n",
                          nt_errstr(status)));
index 0bab4c1064103fa11192f62e3fb1c75e475d9d34..3f7c72db584506c6618a166ec23da334a44d5916 100644 (file)
@@ -951,6 +951,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        struct dcerpc_binding *ep_2nd_description = NULL;
        const char *endpoint = NULL;
        struct dcesrv_auth *auth = call->auth_state;
+       struct dcesrv_context_callbacks *cb = &call->conn->dce_ctx->callbacks;
        struct dcerpc_ack_ctx *ack_ctx_list = NULL;
        struct dcerpc_ack_ctx *ack_features = NULL;
        struct tevent_req *subreq = NULL;
@@ -1155,9 +1156,11 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
                return dcesrv_auth_reply(call);
        }
 
+       cb->auth.become_root();
        subreq = gensec_update_send(call, call->event_ctx,
                                    auth->gensec_security,
                                    call->in_auth_info.credentials);
+       cb->auth.unbecome_root();
        if (subreq == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1172,10 +1175,13 @@ static void dcesrv_bind_done(struct tevent_req *subreq)
                tevent_req_callback_data(subreq,
                struct dcesrv_call_state);
        struct dcesrv_connection *conn = call->conn;
+       struct dcesrv_context_callbacks *cb = &call->conn->dce_ctx->callbacks;
        NTSTATUS status;
 
+       cb->auth.become_root();
        status = gensec_update_recv(subreq, call,
                                    &call->out_auth_info->credentials);
+       cb->auth.unbecome_root();
        TALLOC_FREE(subreq);
 
        status = dcesrv_auth_complete(call, status);
@@ -1233,6 +1239,7 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
 {
        struct dcesrv_connection *conn = call->conn;
        struct dcesrv_auth *auth = call->auth_state;
+       struct dcesrv_context_callbacks *cb = &call->conn->dce_ctx->callbacks;
        struct tevent_req *subreq = NULL;
        NTSTATUS status;
 
@@ -1277,9 +1284,11 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
                return NT_STATUS_OK;
        }
 
+       cb->auth.become_root();
        subreq = gensec_update_send(call, call->event_ctx,
                                    auth->gensec_security,
                                    call->in_auth_info.credentials);
+       cb->auth.unbecome_root();
        if (subreq == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1295,10 +1304,13 @@ static void dcesrv_auth3_done(struct tevent_req *subreq)
                struct dcesrv_call_state);
        struct dcesrv_connection *conn = call->conn;
        struct dcesrv_auth *auth = call->auth_state;
+       struct dcesrv_context_callbacks *cb = &call->conn->dce_ctx->callbacks;
        NTSTATUS status;
 
+       cb->auth.become_root();
        status = gensec_update_recv(subreq, call,
                                    &call->out_auth_info->credentials);
+       cb->auth.unbecome_root();
        TALLOC_FREE(subreq);
 
        status = dcesrv_auth_complete(call, status);
@@ -1570,6 +1582,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
        struct ncacn_packet *pkt = &call->ack_pkt;
        uint32_t extra_flags = 0;
        struct dcesrv_auth *auth = call->auth_state;
+       struct dcesrv_context_callbacks *cb = &call->conn->dce_ctx->callbacks;
        struct dcerpc_ack_ctx *ack_ctx_list = NULL;
        struct tevent_req *subreq = NULL;
        size_t i;
@@ -1681,9 +1694,11 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
                return dcesrv_auth_reply(call);
        }
 
+       cb->auth.become_root();
        subreq = gensec_update_send(call, call->event_ctx,
                                    auth->gensec_security,
                                    call->in_auth_info.credentials);
+       cb->auth.unbecome_root();
        if (subreq == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1698,10 +1713,13 @@ static void dcesrv_alter_done(struct tevent_req *subreq)
                tevent_req_callback_data(subreq,
                struct dcesrv_call_state);
        struct dcesrv_connection *conn = call->conn;
+       struct dcesrv_context_callbacks *cb = &call->conn->dce_ctx->callbacks;
        NTSTATUS status;
 
+       cb->auth.become_root();
        status = gensec_update_recv(subreq, call,
                                    &call->out_auth_info->credentials);
+       cb->auth.unbecome_root();
        TALLOC_FREE(subreq);
 
        status = dcesrv_auth_complete(call, status);
index 41ae622ecfe6974f23a6871c2c0d7ab5fca83a55..48adebe1b0a21240e975f5aa821460e45ec1d3a9 100644 (file)
@@ -386,6 +386,8 @@ struct dcesrv_context_callbacks {
                NTSTATUS (*gensec_prepare)(TALLOC_CTX *mem_ctx,
                                        struct dcesrv_call_state *call,
                                        struct gensec_security **out);
+               void (*become_root)(void);
+               void (*unbecome_root)(void);
        } auth;
        struct {
                NTSTATUS (*find)(struct dcesrv_call_state *);
index 2f1a01da1c0befe5b7ff5b0361fe1dacf54c7aaf..289c4f398409c7b7cbe234af468b1da8eeba95cc 100644 (file)
@@ -31,6 +31,8 @@
 static struct dcesrv_context_callbacks srv_callbacks = {
        .log.successful_authz = dcesrv_log_successful_authz,
        .auth.gensec_prepare = dcesrv_auth_gensec_prepare,
+       .auth.become_root = become_root,
+       .auth.unbecome_root = unbecome_root,
        .assoc_group.find = dcesrv_assoc_group_find,
 };
 
index ae8d91e68f01bca46e496d402b8fa9aea0655b20..5bc28f85ca788b018b171481c8b0474b8cdccb55 100644 (file)
 #include "../libcli/named_pipe_auth/npa_tstream.h"
 #include "samba/process_model.h"
 
+static void skip_become_root(void)
+{
+}
+
+static void skip_unbecome_root(void)
+{
+}
+
 struct dcesrv_context_callbacks srv_callbacks = {
        .log.successful_authz = log_successful_dcesrv_authz_event,
        .auth.gensec_prepare = dcesrv_gensec_prepare,
+       .auth.become_root = skip_become_root,
+       .auth.unbecome_root = skip_unbecome_root,
        .assoc_group.find = dcesrv_assoc_group_find,
 };