]> 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 10:57:11 +0000 (10:57 +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>
(cherry picked from commit 0651fa474cd68b18d8eb9bdc7c4ba5b847ba9ad9)

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

index fec8df513a83ebf39afd9f2b31d3865a56160b1d..99d8e016216031eb6e233fb83eddbb2349c9e48f 100644 (file)
@@ -130,11 +130,13 @@ 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 = cb->auth.gensec_prepare(
                auth,
                call,
                &auth->gensec_security,
                cb->auth.private_data);
+       cb->auth.unbecome_root();
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Failed to call samba_server_gensec_start %s\n",
                          nt_errstr(status)));
@@ -329,6 +331,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) {
@@ -359,9 +362,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 015c7639a51b08e455d5afa99718f714deb57c5a..9fd7181290563e070e79d288aa37b3e29be437cf 100644 (file)
@@ -970,6 +970,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;
@@ -1175,9 +1176,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;
        }
@@ -1192,10 +1195,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);
@@ -1253,6 +1259,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;
 
@@ -1297,9 +1304,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;
        }
@@ -1315,10 +1324,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);
@@ -1587,6 +1599,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;
@@ -1698,9 +1711,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;
        }
@@ -1715,10 +1730,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 e8e87bcce94426390a2884ab30961e2687c71fca..69815b71f3dd91b025e49c51fb655081f2068408 100644 (file)
@@ -392,6 +392,8 @@ struct dcesrv_context_callbacks {
                        struct gensec_security **out,
                        void *private_data);
                void *private_data;
+               void (*become_root)(void);
+               void (*unbecome_root)(void);
        } auth;
        struct {
                NTSTATUS (*find)(
index 5153e9229c8b66094b71a8974896c28f1ce2ebd5..af167d817d55a733731e195c4d4e5035f0118fbf 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 dc5df4075e6566ffd64b7f297ab0d9a7389394cb..2d2bb35af0f189d56b2a1a73397ef8e840e3d09e 100644 (file)
@@ -718,6 +718,8 @@ static struct rpc_worker *rpc_worker_new(
        worker->cb = (struct dcesrv_context_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 = rpc_worker_assoc_group_find,
                .assoc_group.private_data = worker,
        };
index d8c6746d7815d812d5bab4810d9a82f6a36bfdb4..ebb50f8a7ef3864ced97fdefabb0c547a243f6bc 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)
+{
+}
+
 static 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,
 };