184 lines
5.6 KiB
Diff
184 lines
5.6 KiB
Diff
From 7c3b037600077ade1d0ee97f5707e1c5061c1b28 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Thu, 5 Aug 2021 14:22:32 +0200
|
|
Subject: [PATCH 261/266] CVE-2021-3738 s4:rpc_server/common: provide
|
|
|
|
Conflict: NA
|
|
Reference: https://git.samba.org/samba.git/?p=samba.git;a=patch;h=7c3b037600077ade1d0ee97f5707e1c5061c1b28
|
|
|
|
assoc_group aware dcesrv_samdb_connect_as_{system,user}() helpers
|
|
|
|
We already had dcesrv_samdb_connect_as_system(), but it uses the per
|
|
connection memory of auth_session_info and remote_address.
|
|
|
|
But in order to use the samdb connection on a per association group
|
|
context/policy handle, we need to make copies, which last for the
|
|
whole lifetime of the 'samdb' context.
|
|
|
|
We need the same logic also for all cases we make use of
|
|
the almost same logic where we want to create a samdb context
|
|
on behalf of the authenticated user (without allowing system access),
|
|
so we introduce dcesrv_samdb_connect_as_user().
|
|
|
|
In the end we need to replace all direct callers to samdb_connect()
|
|
from source4/rpc_server.
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14468
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
|
|
---
|
|
source4/rpc_server/common/server_info.c | 121 ++++++++++++++++++++----
|
|
1 file changed, 105 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/source4/rpc_server/common/server_info.c b/source4/rpc_server/common/server_info.c
|
|
index 6e475bcc796..a2af37653ef 100644
|
|
--- a/source4/rpc_server/common/server_info.c
|
|
+++ b/source4/rpc_server/common/server_info.c
|
|
@@ -28,6 +28,8 @@
|
|
#include "param/param.h"
|
|
#include "rpc_server/common/common.h"
|
|
#include "libds/common/roles.h"
|
|
+#include "auth/auth_util.h"
|
|
+#include "lib/tsocket/tsocket.h"
|
|
|
|
/*
|
|
Here are common server info functions used by some dcerpc server interfaces
|
|
@@ -188,30 +190,117 @@ bool dcesrv_common_validate_share_name(TALLOC_CTX *mem_ctx, const char *share_na
|
|
return true;
|
|
}
|
|
|
|
-/*
|
|
- * Open an ldb connection under the system session and save the remote users
|
|
- * session details in a ldb_opaque. This will allow the audit logging to
|
|
- * log the original session for operations performed in the system session.
|
|
- */
|
|
-struct ldb_context *dcesrv_samdb_connect_as_system(
|
|
+static struct ldb_context *dcesrv_samdb_connect_common(
|
|
TALLOC_CTX *mem_ctx,
|
|
- struct dcesrv_call_state *dce_call)
|
|
+ struct dcesrv_call_state *dce_call,
|
|
+ bool as_system)
|
|
{
|
|
struct ldb_context *samdb = NULL;
|
|
+ struct auth_session_info *system_session_info = NULL;
|
|
+ const struct auth_session_info *call_session_info =
|
|
+ dcesrv_call_session_info(dce_call);
|
|
+ struct auth_session_info *user_session_info = NULL;
|
|
+ struct auth_session_info *ldb_session_info = NULL;
|
|
+ struct auth_session_info *audit_session_info = NULL;
|
|
+ struct tsocket_address *remote_address = NULL;
|
|
+
|
|
+ if (as_system) {
|
|
+ system_session_info = system_session(dce_call->conn->dce_ctx->lp_ctx);
|
|
+ if (system_session_info == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ user_session_info = copy_session_info(mem_ctx, call_session_info);
|
|
+ if (user_session_info == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (dce_call->conn->remote_address != NULL) {
|
|
+ remote_address = tsocket_address_copy(dce_call->conn->remote_address,
|
|
+ user_session_info);
|
|
+ if (remote_address == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (system_session_info != NULL) {
|
|
+ ldb_session_info = system_session_info;
|
|
+ audit_session_info = user_session_info;
|
|
+ } else {
|
|
+ ldb_session_info = user_session_info;
|
|
+ audit_session_info = NULL;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * We need to make sure every argument
|
|
+ * stays arround for the lifetime of 'samdb',
|
|
+ * typically it is allocated on the scope of
|
|
+ * an assoc group, so we can't reference dce_call->conn,
|
|
+ * as the assoc group may stay when the current connection
|
|
+ * gets disconnected.
|
|
+ *
|
|
+ * The following are global per process:
|
|
+ * - dce_call->conn->dce_ctx->lp_ctx
|
|
+ * - dce_call->event_ctx
|
|
+ * - system_session
|
|
+ *
|
|
+ * We make a copy of:
|
|
+ * - dce_call->conn->remote_address
|
|
+ * - dce_call->auth_state->session_info
|
|
+ */
|
|
samdb = samdb_connect(
|
|
mem_ctx,
|
|
dce_call->event_ctx,
|
|
dce_call->conn->dce_ctx->lp_ctx,
|
|
- system_session(dce_call->conn->dce_ctx->lp_ctx),
|
|
- dce_call->conn->remote_address,
|
|
+ ldb_session_info,
|
|
+ remote_address,
|
|
0);
|
|
- if (samdb) {
|
|
- struct auth_session_info *session_info =
|
|
- dcesrv_call_session_info(dce_call);
|
|
- ldb_set_opaque(
|
|
- samdb,
|
|
- DSDB_NETWORK_SESSION_INFO,
|
|
- session_info);
|
|
+ if (samdb == NULL) {
|
|
+ talloc_free(user_session_info);
|
|
+ return NULL;
|
|
}
|
|
+ talloc_move(samdb, &user_session_info);
|
|
+
|
|
+ if (audit_session_info != NULL) {
|
|
+ int ret;
|
|
+
|
|
+ ret = ldb_set_opaque(samdb,
|
|
+ DSDB_NETWORK_SESSION_INFO,
|
|
+ audit_session_info);
|
|
+ if (ret != LDB_SUCCESS) {
|
|
+ talloc_free(samdb);
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
return samdb;
|
|
}
|
|
+
|
|
+/*
|
|
+ * Open an ldb connection under the system session and save the remote users
|
|
+ * session details in a ldb_opaque. This will allow the audit logging to
|
|
+ * log the original session for operations performed in the system session.
|
|
+ *
|
|
+ * Access checks are required by the caller!
|
|
+ */
|
|
+struct ldb_context *dcesrv_samdb_connect_as_system(
|
|
+ TALLOC_CTX *mem_ctx,
|
|
+ struct dcesrv_call_state *dce_call)
|
|
+{
|
|
+ return dcesrv_samdb_connect_common(mem_ctx, dce_call,
|
|
+ true /* as_system */);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Open an ldb connection under the remote users session details.
|
|
+ *
|
|
+ * Access checks are done at the ldb level.
|
|
+ */
|
|
+struct ldb_context *dcesrv_samdb_connect_as_user(
|
|
+ TALLOC_CTX *mem_ctx,
|
|
+ struct dcesrv_call_state *dce_call)
|
|
+{
|
|
+ return dcesrv_samdb_connect_common(mem_ctx, dce_call,
|
|
+ false /* not as_system */);
|
|
+}
|
|
--
|
|
2.23.0
|
|
|