samba/backport-0006-CVE-2020-25718-Change-sid-list.patch
haochenstar 8378df4821 fix CVE-2020-25717,CVE-2020-25718,CVE-2020-25719,CVE-2020-25721,CVE-2020-25722,CVE-2016-2124,CVE-2021-3738
(cherry picked from commit aee849c6c0708056f62f6445e3b5274d1cec6408)
2022-01-19 11:41:35 +08:00

305 lines
10 KiB
Diff

From fc65e4b49c9900aeca06276f05f31e20d28a6c20 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
Date: Fri, 1 Oct 2021 10:47:29 +1300
Subject: [PATCH 232/284] CVE-2020-25718 s4-rpc_server: Change sid list
Conflict: NA
Reference: https://git.samba.org/samba.git/?p=samba.git;a=patch;h=fc65e4b49c9900aeca06276f05f31e20d28a6c20
functions to operate on a array of struct dom_sid
This is instead of an array of struct dom_sid *.
The reason is that auth_user_info_dc has an array of struct dom_sid
(the user token) and for checking if an RODC should be allowed
to print a particular ticket, we want to reuse that a rather
then reconstruct it via tokenGroups.
This also avoids a lot of memory allocation.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
---
source4/rpc_server/common/sid_helper.c | 44 +++++++++----------
source4/rpc_server/drsuapi/getncchanges.c | 33 +++++++++-----
source4/rpc_server/netlogon/dcerpc_netlogon.c | 33 +++++++++-----
3 files changed, 67 insertions(+), 43 deletions(-)
diff --git a/source4/rpc_server/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c
index 698249391ef5..65d7e7c7271e 100644
--- a/source4/rpc_server/common/sid_helper.c
+++ b/source4/rpc_server/common/sid_helper.c
@@ -29,13 +29,16 @@
/*
see if any SIDs in list1 are in list2
*/
-bool sid_list_match(const struct dom_sid **list1, const struct dom_sid **list2)
+bool sid_list_match(uint32_t num_sids1,
+ const struct dom_sid *list1,
+ uint32_t num_sids2,
+ const struct dom_sid *list2)
{
unsigned int i, j;
/* do we ever have enough SIDs here to worry about O(n^2) ? */
- for (i=0; list1[i]; i++) {
- for (j=0; list2[j]; j++) {
- if (dom_sid_equal(list1[i], list2[j])) {
+ for (i=0; i < num_sids1; i++) {
+ for (j=0; j < num_sids2; j++) {
+ if (dom_sid_equal(&list1[i], &list2[j])) {
return true;
}
}
@@ -51,9 +54,10 @@ WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx,
struct ldb_message *msg,
TALLOC_CTX *mem_ctx,
const char *attr,
- const struct dom_sid ***sids,
- const struct dom_sid **additional_sids,
- unsigned int num_additional)
+ uint32_t *num_sids,
+ struct dom_sid **sids,
+ const struct dom_sid *additional_sids,
+ unsigned int num_additional)
{
struct ldb_message_element *el;
unsigned int i, j;
@@ -65,30 +69,25 @@ WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx,
}
/* Make array long enough for NULL and additional SID */
- (*sids) = talloc_array(mem_ctx, const struct dom_sid *,
- el->num_values + num_additional + 1);
+ (*sids) = talloc_array(mem_ctx, struct dom_sid,
+ el->num_values + num_additional);
W_ERROR_HAVE_NO_MEMORY(*sids);
for (i=0; i<el->num_values; i++) {
enum ndr_err_code ndr_err;
- struct dom_sid *sid;
- sid = talloc(*sids, struct dom_sid);
- W_ERROR_HAVE_NO_MEMORY(sid);
-
- ndr_err = ndr_pull_struct_blob(&el->values[i], sid, sid,
+ ndr_err = ndr_pull_struct_blob_all_noalloc(&el->values[i], &(*sids)[i],
(ndr_pull_flags_fn_t)ndr_pull_dom_sid);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return WERR_INTERNAL_DB_CORRUPTION;
}
- (*sids)[i] = sid;
}
for (j = 0; j < num_additional; j++) {
(*sids)[i++] = additional_sids[j];
}
- (*sids)[i] = NULL;
+ *num_sids = i;
return WERR_OK;
}
@@ -101,7 +100,8 @@ WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx,
struct ldb_message *msg,
TALLOC_CTX *mem_ctx,
const char *attr,
- const struct dom_sid ***sids)
+ uint32_t *num_sids,
+ struct dom_sid **sids)
{
struct ldb_message_element *el;
unsigned int i;
@@ -112,23 +112,21 @@ WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx,
return WERR_OK;
}
- (*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1);
+ (*sids) = talloc_array(mem_ctx, struct dom_sid, el->num_values + 1);
W_ERROR_HAVE_NO_MEMORY(*sids);
for (i=0; i<el->num_values; i++) {
struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, sam_ctx, &el->values[i]);
NTSTATUS status;
- struct dom_sid *sid;
+ struct dom_sid sid = { 0, };
- sid = talloc(*sids, struct dom_sid);
- W_ERROR_HAVE_NO_MEMORY(sid);
- status = dsdb_get_extended_dn_sid(dn, sid, "SID");
+ status = dsdb_get_extended_dn_sid(dn, &sid, "SID");
if (!NT_STATUS_IS_OK(status)) {
return WERR_INTERNAL_DB_CORRUPTION;
}
(*sids)[i] = sid;
}
- (*sids)[i] = NULL;
+ *num_sids = i;
return WERR_OK;
}
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c
index e458b2a99311..c7d2addd104d 100644
--- a/source4/rpc_server/drsuapi/getncchanges.c
+++ b/source4/rpc_server/drsuapi/getncchanges.c
@@ -1171,10 +1171,10 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state,
const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
struct ldb_result *rodc_res = NULL, *obj_res = NULL;
- const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
+ uint32_t num_never_reveal_sids, num_reveal_sids, num_token_sids;
+ struct dom_sid *never_reveal_sids, *reveal_sids, *token_sids;
const struct dom_sid *object_sid = NULL;
WERROR werr;
- const struct dom_sid *additional_sids[] = { NULL, NULL };
DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_SECRET extended op on %s\n",
drs_ObjectIdentifier_to_string(mem_ctx, ncRoot)));
@@ -1259,12 +1259,13 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state,
/* if the object SID is equal to the user_sid, allow */
object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
+ if (object_sid == NULL) {
+ goto failed;
+ }
if (dom_sid_equal(user_sid, object_sid)) {
goto allowed;
}
- additional_sids[0] = object_sid;
-
/*
* Must be an RODC account at this point, verify machine DN matches the
* SID account
@@ -1294,13 +1295,17 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state,
}
werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0],
- mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
+ mem_ctx, "msDS-NeverRevealGroup",
+ &num_never_reveal_sids,
+ &never_reveal_sids);
if (!W_ERROR_IS_OK(werr)) {
goto denied;
}
werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0],
- mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
+ mem_ctx, "msDS-RevealOnDemandGroup",
+ &num_reveal_sids,
+ &reveal_sids);
if (!W_ERROR_IS_OK(werr)) {
goto denied;
}
@@ -1311,19 +1316,27 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state,
* TODO determine if sIDHistory is required for this check
*/
werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0],
- mem_ctx, "tokenGroups", &token_sids,
- additional_sids, 1);
+ mem_ctx, "tokenGroups",
+ &num_token_sids,
+ &token_sids,
+ object_sid, 1);
if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
goto denied;
}
if (never_reveal_sids &&
- sid_list_match(token_sids, never_reveal_sids)) {
+ sid_list_match(num_token_sids,
+ token_sids,
+ num_never_reveal_sids,
+ never_reveal_sids)) {
goto denied;
}
if (reveal_sids &&
- sid_list_match(token_sids, reveal_sids)) {
+ sid_list_match(num_token_sids,
+ token_sids,
+ num_reveal_sids,
+ reveal_sids)) {
goto allowed;
}
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 9972138dbdef..c8dd0ceeb775 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -2850,10 +2850,10 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
struct ldb_dn *rodc_dn;
int ret;
struct ldb_result *rodc_res = NULL, *obj_res = NULL;
- const struct dom_sid *additional_sids[] = { NULL, NULL };
WERROR werr;
struct dom_sid *object_sid;
- const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
+ uint32_t num_never_reveal_sids, num_reveal_sids, num_token_sids;
+ struct dom_sid *never_reveal_sids, *reveal_sids, *token_sids;
rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
dom_sid_string(mem_ctx, user_sid));
@@ -2868,17 +2868,22 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
-
- additional_sids[0] = object_sid;
+ if (object_sid == NULL) {
+ goto denied;
+ }
werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
- mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
+ mem_ctx, "msDS-NeverRevealGroup",
+ &num_never_reveal_sids,
+ &never_reveal_sids);
if (!W_ERROR_IS_OK(werr)) {
goto denied;
}
werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
- mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
+ mem_ctx, "msDS-RevealOnDemandGroup",
+ &num_reveal_sids,
+ &reveal_sids);
if (!W_ERROR_IS_OK(werr)) {
goto denied;
}
@@ -2889,19 +2894,27 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
* TODO determine if sIDHistory is required for this check
*/
werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
- mem_ctx, "tokenGroups", &token_sids,
- additional_sids, 1);
+ mem_ctx, "tokenGroups",
+ &num_token_sids,
+ &token_sids,
+ object_sid, 1);
if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
goto denied;
}
if (never_reveal_sids &&
- sid_list_match(token_sids, never_reveal_sids)) {
+ sid_list_match(num_token_sids,
+ token_sids,
+ num_never_reveal_sids,
+ never_reveal_sids)) {
goto denied;
}
if (reveal_sids &&
- sid_list_match(token_sids, reveal_sids)) {
+ sid_list_match(num_token_sids,
+ token_sids,
+ num_reveal_sids,
+ reveal_sids)) {
goto allowed;
}
--
2.25.1