From b371acd1e03ef7eaf644932a8aafadcf49f7db3f 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 (similar to commit 0651fa474cd68b18d8eb9bdc7c4ba5b847ba9ad9) --- librpc/rpc/dcesrv_auth.c | 6 ++++++ 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, 38 insertions(+) diff --git a/librpc/rpc/dcesrv_auth.c b/librpc/rpc/dcesrv_auth.c index 9d8df6c42e29..b4a29ea9ab4e 100644 --- a/librpc/rpc/dcesrv_auth.c +++ b/librpc/rpc/dcesrv_auth.c @@ -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 = ""; 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))); diff --git a/librpc/rpc/dcesrv_core.c b/librpc/rpc/dcesrv_core.c index 0bab4c106410..3f7c72db5845 100644 --- a/librpc/rpc/dcesrv_core.c +++ b/librpc/rpc/dcesrv_core.c @@ -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); diff --git a/librpc/rpc/dcesrv_core.h b/librpc/rpc/dcesrv_core.h index 41ae622ecfe6..48adebe1b0a2 100644 --- a/librpc/rpc/dcesrv_core.h +++ b/librpc/rpc/dcesrv_core.h @@ -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 *); 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 ae8d91e68f01..5bc28f85ca78 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) +{ +} + 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