From 0203330e2fa23482d99809e777ccb8a93a728aa3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 5 Aug 2021 14:24:40 +0200
Subject: [PATCH 266/266] CVE-2021-3738 s4:rpc_server/samr: make use of
 
Conflict: NA 
Reference: https://git.samba.org/samba.git/?p=samba.git;a=patch;h=0203330e2fa23482d99809e777ccb8a93a728aa3

 dcesrv_samdb_connect_as_*() helper

This avoids a crash that's triggered by windows clients using
handles from samr_Connect*() on across multiple connections within
an association group.

In other cases is not strictly required, but it makes it easier to audit that
source4/rpc_server no longer calls samdb_connect() directly and also
improves the auditing for the dcesrv_samdb_connect_as_system() case.

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>

[abartlet@samba.org Backported from master as Samba 4.13 does not
 call dcerpc_is_transport_encrypted() and so session_info becomes
 unused.]
---
 source4/rpc_server/samr/dcesrv_samr.c   | 19 ++------------
 source4/rpc_server/samr/samr_password.c | 33 ++++---------------------
 2 files changed, 7 insertions(+), 45 deletions(-)

diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 7345cac6bd6..c810aac7c8a 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -210,8 +210,6 @@ exit:
 static NTSTATUS dcesrv_samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 			     struct samr_Connect *r)
 {
-	struct auth_session_info *session_info =
-		dcesrv_call_session_info(dce_call);
 	struct samr_connect_state *c_state;
 	struct dcesrv_handle *handle;
 
@@ -223,18 +221,12 @@ static NTSTATUS dcesrv_samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_C
 	}
 
 	/* make sure the sam database is accessible */
-	c_state->sam_ctx = samdb_connect(c_state,
-					 dce_call->event_ctx,
-					 dce_call->conn->dce_ctx->lp_ctx,
-					 session_info,
-					 dce_call->conn->remote_address,
-					 0);
+	c_state->sam_ctx = dcesrv_samdb_connect_as_user(c_state, dce_call);
 	if (c_state->sam_ctx == NULL) {
 		talloc_free(c_state);
 		return NT_STATUS_INVALID_SYSTEM_SERVICE;
 	}
 
-
 	handle = dcesrv_handle_create(dce_call, SAMR_HANDLE_CONNECT);
 	if (!handle) {
 		talloc_free(c_state);
@@ -4807,8 +4799,6 @@ static NTSTATUS dcesrv_samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_st
 static NTSTATUS dcesrv_samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 				  struct samr_GetDomPwInfo *r)
 {
-	struct auth_session_info *session_info =
-		dcesrv_call_session_info(dce_call);
 	struct ldb_message **msgs;
 	int ret;
 	const char * const attrs[] = {"minPwdLength", "pwdProperties", NULL };
@@ -4816,12 +4806,7 @@ static NTSTATUS dcesrv_samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TAL
 
 	ZERO_STRUCTP(r->out.info);
 
-	sam_ctx = samdb_connect(mem_ctx,
-				dce_call->event_ctx,
-				dce_call->conn->dce_ctx->lp_ctx,
-				session_info,
-				dce_call->conn->remote_address,
-				0);
+	sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
 	if (sam_ctx == NULL) {
 		return NT_STATUS_INVALID_SYSTEM_SERVICE;
 	}
diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c
index 52a644176e2..9144c23155b 100644
--- a/source4/rpc_server/samr/samr_password.c
+++ b/source4/rpc_server/samr/samr_password.c
@@ -22,6 +22,7 @@
 
 #include "includes.h"
 #include "rpc_server/dcerpc_server.h"
+#include "rpc_server/common/common.h"
 #include "rpc_server/samr/dcesrv_samr.h"
 #include "system/time.h"
 #include "../lib/crypto/crypto.h"
@@ -101,8 +102,6 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
 					    TALLOC_CTX *mem_ctx,
 					    struct samr_OemChangePasswordUser2 *r)
 {
-	struct auth_session_info *session_info =
-		dcesrv_call_session_info(dce_call);
	NTSTATUS status = NT_STATUS_WRONG_PASSWORD;
	DATA_BLOB new_password, new_unicode_password;
	char *new_pass;
@@ -146,12 +145,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
 
 	/* Connect to a SAMDB with system privileges for fetching the old pw
 	 * hashes. */
-	sam_ctx = 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,
-				0);
+	sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
 	if (sam_ctx == NULL) {
 		return NT_STATUS_INVALID_SYSTEM_SERVICE;
 	}
@@ -249,12 +243,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
 	}
 
 	/* Connect to a SAMDB with user privileges for the password change */
-	sam_ctx = samdb_connect(mem_ctx,
-				dce_call->event_ctx,
-				dce_call->conn->dce_ctx->lp_ctx,
-				session_info,
-				dce_call->conn->remote_address,
-				0);
+	sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
 	if (sam_ctx == NULL) {
 		return NT_STATUS_INVALID_SYSTEM_SERVICE;
 	}
@@ -327,8 +316,6 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
 					 TALLOC_CTX *mem_ctx,
 					 struct samr_ChangePasswordUser3 *r)
 {
-	struct auth_session_info *session_info =
-		dcesrv_call_session_info(dce_call);
	NTSTATUS status = NT_STATUS_WRONG_PASSWORD;
	DATA_BLOB new_password;
	struct ldb_context *sam_ctx = NULL;
@@ -374,12 +361,7 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
 
 	/* Connect to a SAMDB with system privileges for fetching the old pw
 	 * hashes. */
-	sam_ctx = 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,
-				0);
+	sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
 	if (sam_ctx == NULL) {
 		return NT_STATUS_INVALID_SYSTEM_SERVICE;
 	}
@@ -485,12 +467,7 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
 	}
 
 	/* Connect to a SAMDB with user privileges for the password change */
-	sam_ctx = samdb_connect(mem_ctx,
-				dce_call->event_ctx,
-				dce_call->conn->dce_ctx->lp_ctx,
-				session_info,
-				dce_call->conn->remote_address,
-				0);
+	sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
 	if (sam_ctx == NULL) {
 		return NT_STATUS_INVALID_SYSTEM_SERVICE;
 	}
-- 
2.23.0

