11c8e3
From 10f485b3a27e10906aa6ee40833fca8bf81b5511 Mon Sep 17 00:00:00 2001
11c8e3
From: Stefan Metzmacher <metze@samba.org>
11c8e3
Date: Sat, 22 Jan 2022 01:08:26 +0100
11c8e3
Subject: [PATCH] dcesrv_core: wrap gensec_*() calls in [un]become_root() calls
11c8e3
11c8e3
This is important for the source3/rpc_server code as it might
11c8e3
be called embedded in smbd and may not run as root with access
11c8e3
to our private tdb/ldb files.
11c8e3
11c8e3
Note this is only really needed for 4.15 and older, as
11c8e3
we no longer run the rpc_server embedded in smbd,
11c8e3
but we better be consistent for now.
11c8e3
11c8e3
This should be able to fix the problem the printing no longer works
11c8e3
on Windows 7 with 2021-10 monthly rollup patch (KB5006743).
11c8e3
11c8e3
Windows uses NTLMSSP with privacy at the DCERPC layer on top
11c8e3
of NCACN_NP (smb).
11c8e3
11c8e3
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14867
11c8e3
11c8e3
Signed-off-by: Stefan Metzmacher <metze@samba.org>
11c8e3
Reviewed-by: Andreas Schneider <asn@samba.org>
11c8e3
(cherry picked from commit 0651fa474cd68b18d8eb9bdc7c4ba5b847ba9ad9)
11c8e3
---
11c8e3
 librpc/rpc/dcesrv_auth.c         |  5 +++++
11c8e3
 librpc/rpc/dcesrv_core.c         | 18 ++++++++++++++++++
11c8e3
 librpc/rpc/dcesrv_core.h         |  2 ++
11c8e3
 source3/rpc_server/rpc_config.c  |  2 ++
11c8e3
 source4/rpc_server/service_rpc.c | 10 ++++++++++
11c8e3
 5 files changed, 37 insertions(+)
11c8e3
11c8e3
diff --git a/librpc/rpc/dcesrv_auth.c b/librpc/rpc/dcesrv_auth.c
11c8e3
index fec8df513a83..99d8e0162160 100644
11c8e3
--- a/librpc/rpc/dcesrv_auth.c
11c8e3
+++ b/librpc/rpc/dcesrv_auth.c
11c8e3
@@ -130,11 +130,13 @@ static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call)
11c8e3
 	auth->auth_level = call->in_auth_info.auth_level;
11c8e3
 	auth->auth_context_id = call->in_auth_info.auth_context_id;
11c8e3
 
11c8e3
+	cb->auth.become_root();
11c8e3
 	status = cb->auth.gensec_prepare(
11c8e3
 		auth,
11c8e3
 		call,
11c8e3
 		&auth->gensec_security,
11c8e3
 		cb->auth.private_data);
11c8e3
+	cb->auth.unbecome_root();
11c8e3
 	if (!NT_STATUS_IS_OK(status)) {
11c8e3
 		DEBUG(1, ("Failed to call samba_server_gensec_start %s\n",
11c8e3
 			  nt_errstr(status)));
11c8e3
@@ -329,6 +331,7 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
11c8e3
 NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
11c8e3
 {
11c8e3
 	struct dcesrv_auth *auth = call->auth_state;
11c8e3
+	struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
11c8e3
 	const char *pdu = "<unknown>";
11c8e3
 
11c8e3
 	switch (call->pkt.ptype) {
11c8e3
@@ -359,9 +362,11 @@ NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
11c8e3
 		return status;
11c8e3
 	}
11c8e3
 
11c8e3
+	cb->auth.become_root();
11c8e3
 	status = gensec_session_info(auth->gensec_security,
11c8e3
 				     auth,
11c8e3
 				     &auth->session_info);
11c8e3
+	cb->auth.unbecome_root();
11c8e3
 	if (!NT_STATUS_IS_OK(status)) {
11c8e3
 		DEBUG(1, ("Failed to establish session_info: %s\n",
11c8e3
 			  nt_errstr(status)));
11c8e3
diff --git a/librpc/rpc/dcesrv_core.c b/librpc/rpc/dcesrv_core.c
11c8e3
index d16159b0b6cd..ea91fc689b4a 100644
11c8e3
--- a/librpc/rpc/dcesrv_core.c
11c8e3
+++ b/librpc/rpc/dcesrv_core.c
11c8e3
@@ -938,6 +938,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
11c8e3
 	struct dcerpc_binding *ep_2nd_description = NULL;
11c8e3
 	const char *endpoint = NULL;
11c8e3
 	struct dcesrv_auth *auth = call->auth_state;
11c8e3
+	struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
11c8e3
 	struct dcerpc_ack_ctx *ack_ctx_list = NULL;
11c8e3
 	struct dcerpc_ack_ctx *ack_features = NULL;
11c8e3
 	struct tevent_req *subreq = NULL;
11c8e3
@@ -1143,9 +1144,11 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
11c8e3
 		return dcesrv_auth_reply(call);
11c8e3
 	}
11c8e3
 
11c8e3
+	cb->auth.become_root();
11c8e3
 	subreq = gensec_update_send(call, call->event_ctx,
11c8e3
 				    auth->gensec_security,
11c8e3
 				    call->in_auth_info.credentials);
11c8e3
+	cb->auth.unbecome_root();
11c8e3
 	if (subreq == NULL) {
11c8e3
 		return NT_STATUS_NO_MEMORY;
11c8e3
 	}
11c8e3
@@ -1160,10 +1163,13 @@ static void dcesrv_bind_done(struct tevent_req *subreq)
11c8e3
 		tevent_req_callback_data(subreq,
11c8e3
 		struct dcesrv_call_state);
11c8e3
 	struct dcesrv_connection *conn = call->conn;
11c8e3
+	struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
11c8e3
 	NTSTATUS status;
11c8e3
 
11c8e3
+	cb->auth.become_root();
11c8e3
 	status = gensec_update_recv(subreq, call,
11c8e3
 				    &call->out_auth_info->credentials);
11c8e3
+	cb->auth.unbecome_root();
11c8e3
 	TALLOC_FREE(subreq);
11c8e3
 
11c8e3
 	status = dcesrv_auth_complete(call, status);
11c8e3
@@ -1221,6 +1227,7 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
11c8e3
 {
11c8e3
 	struct dcesrv_connection *conn = call->conn;
11c8e3
 	struct dcesrv_auth *auth = call->auth_state;
11c8e3
+	struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
11c8e3
 	struct tevent_req *subreq = NULL;
11c8e3
 	NTSTATUS status;
11c8e3
 
11c8e3
@@ -1265,9 +1272,11 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
11c8e3
 		return NT_STATUS_OK;
11c8e3
 	}
11c8e3
 
11c8e3
+	cb->auth.become_root();
11c8e3
 	subreq = gensec_update_send(call, call->event_ctx,
11c8e3
 				    auth->gensec_security,
11c8e3
 				    call->in_auth_info.credentials);
11c8e3
+	cb->auth.unbecome_root();
11c8e3
 	if (subreq == NULL) {
11c8e3
 		return NT_STATUS_NO_MEMORY;
11c8e3
 	}
11c8e3
@@ -1283,10 +1292,13 @@ static void dcesrv_auth3_done(struct tevent_req *subreq)
11c8e3
 		struct dcesrv_call_state);
11c8e3
 	struct dcesrv_connection *conn = call->conn;
11c8e3
 	struct dcesrv_auth *auth = call->auth_state;
11c8e3
+	struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
11c8e3
 	NTSTATUS status;
11c8e3
 
11c8e3
+	cb->auth.become_root();
11c8e3
 	status = gensec_update_recv(subreq, call,
11c8e3
 				    &call->out_auth_info->credentials);
11c8e3
+	cb->auth.unbecome_root();
11c8e3
 	TALLOC_FREE(subreq);
11c8e3
 
11c8e3
 	status = dcesrv_auth_complete(call, status);
11c8e3
@@ -1555,6 +1567,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
11c8e3
 	struct ncacn_packet *pkt = &call->ack_pkt;
11c8e3
 	uint32_t extra_flags = 0;
11c8e3
 	struct dcesrv_auth *auth = call->auth_state;
11c8e3
+	struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
11c8e3
 	struct dcerpc_ack_ctx *ack_ctx_list = NULL;
11c8e3
 	struct tevent_req *subreq = NULL;
11c8e3
 	size_t i;
11c8e3
@@ -1666,9 +1679,11 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
11c8e3
 		return dcesrv_auth_reply(call);
11c8e3
 	}
11c8e3
 
11c8e3
+	cb->auth.become_root();
11c8e3
 	subreq = gensec_update_send(call, call->event_ctx,
11c8e3
 				    auth->gensec_security,
11c8e3
 				    call->in_auth_info.credentials);
11c8e3
+	cb->auth.unbecome_root();
11c8e3
 	if (subreq == NULL) {
11c8e3
 		return NT_STATUS_NO_MEMORY;
11c8e3
 	}
11c8e3
@@ -1683,10 +1698,13 @@ static void dcesrv_alter_done(struct tevent_req *subreq)
11c8e3
 		tevent_req_callback_data(subreq,
11c8e3
 		struct dcesrv_call_state);
11c8e3
 	struct dcesrv_connection *conn = call->conn;
11c8e3
+	struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
11c8e3
 	NTSTATUS status;
11c8e3
 
11c8e3
+	cb->auth.become_root();
11c8e3
 	status = gensec_update_recv(subreq, call,
11c8e3
 				    &call->out_auth_info->credentials);
11c8e3
+	cb->auth.unbecome_root();
11c8e3
 	TALLOC_FREE(subreq);
11c8e3
 
11c8e3
 	status = dcesrv_auth_complete(call, status);
11c8e3
diff --git a/librpc/rpc/dcesrv_core.h b/librpc/rpc/dcesrv_core.h
11c8e3
index d8d5f9030959..0538442e0ce6 100644
11c8e3
--- a/librpc/rpc/dcesrv_core.h
11c8e3
+++ b/librpc/rpc/dcesrv_core.h
11c8e3
@@ -392,6 +392,8 @@ struct dcesrv_context_callbacks {
11c8e3
 			struct gensec_security **out,
11c8e3
 			void *private_data);
11c8e3
 		void *private_data;
11c8e3
+		void (*become_root)(void);
11c8e3
+		void (*unbecome_root)(void);
11c8e3
 	} auth;
11c8e3
 	struct {
11c8e3
 		NTSTATUS (*find)(
11c8e3
diff --git a/source3/rpc_server/rpc_config.c b/source3/rpc_server/rpc_config.c
11c8e3
index 2f1a01da1c0b..289c4f398409 100644
11c8e3
--- a/source3/rpc_server/rpc_config.c
11c8e3
+++ b/source3/rpc_server/rpc_config.c
11c8e3
@@ -31,6 +31,8 @@
11c8e3
 static struct dcesrv_context_callbacks srv_callbacks = {
11c8e3
 	.log.successful_authz = dcesrv_log_successful_authz,
11c8e3
 	.auth.gensec_prepare = dcesrv_auth_gensec_prepare,
11c8e3
+	.auth.become_root = become_root,
11c8e3
+	.auth.unbecome_root = unbecome_root,
11c8e3
 	.assoc_group.find = dcesrv_assoc_group_find,
11c8e3
 };
11c8e3
 
11c8e3
diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c
11c8e3
index d8c6746d7815..ebb50f8a7ef3 100644
11c8e3
--- a/source4/rpc_server/service_rpc.c
11c8e3
+++ b/source4/rpc_server/service_rpc.c
11c8e3
@@ -40,9 +40,19 @@
11c8e3
 #include "../libcli/named_pipe_auth/npa_tstream.h"
11c8e3
 #include "samba/process_model.h"
11c8e3
 
11c8e3
+static void skip_become_root(void)
11c8e3
+{
11c8e3
+}
11c8e3
+
11c8e3
+static void skip_unbecome_root(void)
11c8e3
+{
11c8e3
+}
11c8e3
+
11c8e3
 static struct dcesrv_context_callbacks srv_callbacks = {
11c8e3
 	.log.successful_authz = log_successful_dcesrv_authz_event,
11c8e3
 	.auth.gensec_prepare = dcesrv_gensec_prepare,
11c8e3
+	.auth.become_root = skip_become_root,
11c8e3
+	.auth.unbecome_root = skip_unbecome_root,
11c8e3
 	.assoc_group.find = dcesrv_assoc_group_find,
11c8e3
 };
11c8e3
 
11c8e3
-- 
11c8e3
2.25.1
11c8e3