From 10f485b3a27e10906aa6ee40833fca8bf81b5511 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 22 Jan 2022 01:08:26 +0100 Subject: [PATCH] dcesrv_core: wrap gensec_*() calls in [un]become_root() calls 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 Reviewed-by: Andreas Schneider (cherry picked from commit 0651fa474cd68b18d8eb9bdc7c4ba5b847ba9ad9) --- librpc/rpc/dcesrv_auth.c | 5 +++++ librpc/rpc/dcesrv_core.c | 18 ++++++++++++++++++ librpc/rpc/dcesrv_core.h | 2 ++ source3/rpc_server/rpc_config.c | 2 ++ source4/rpc_server/service_rpc.c | 10 ++++++++++ 5 files changed, 37 insertions(+) diff --git a/librpc/rpc/dcesrv_auth.c b/librpc/rpc/dcesrv_auth.c index fec8df513a83..99d8e0162160 100644 --- a/librpc/rpc/dcesrv_auth.c +++ b/librpc/rpc/dcesrv_auth.c @@ -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 = ""; 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))); diff --git a/librpc/rpc/dcesrv_core.c b/librpc/rpc/dcesrv_core.c index d16159b0b6cd..ea91fc689b4a 100644 --- a/librpc/rpc/dcesrv_core.c +++ b/librpc/rpc/dcesrv_core.c @@ -938,6 +938,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; @@ -1143,9 +1144,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; } @@ -1160,10 +1163,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); @@ -1221,6 +1227,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; @@ -1265,9 +1272,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; } @@ -1283,10 +1292,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); @@ -1555,6 +1567,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; @@ -1666,9 +1679,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; } @@ -1683,10 +1698,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); diff --git a/librpc/rpc/dcesrv_core.h b/librpc/rpc/dcesrv_core.h index d8d5f9030959..0538442e0ce6 100644 --- a/librpc/rpc/dcesrv_core.h +++ b/librpc/rpc/dcesrv_core.h @@ -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)( diff --git a/source3/rpc_server/rpc_config.c b/source3/rpc_server/rpc_config.c index 2f1a01da1c0b..289c4f398409 100644 --- a/source3/rpc_server/rpc_config.c +++ b/source3/rpc_server/rpc_config.c @@ -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, }; diff --git a/source4/rpc_server/service_rpc.c b/source4/rpc_server/service_rpc.c index d8c6746d7815..ebb50f8a7ef3 100644 --- a/source4/rpc_server/service_rpc.c +++ b/source4/rpc_server/service_rpc.c @@ -40,9 +40,19 @@ #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, }; -- 2.25.1