[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Mon Mar 20 10:54:01 UTC 2023


The branch, master has been updated
       via  f3fad5a189f libcli/security: prepare sddl machine/forest_sid handling
       via  bd327f7d7a0 libcli/security: simplify sddl_encode_sid()
       via  8f4aced3653 libcli/security: simplify rid-based SDDL sid strings
       via  7d466a913f2 libcli/security: introduce struct sddl_transition_state
      from  3e2eb1b0236 s4:kdc: Add client claims blob if it is present

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit f3fad5a189f73615360510ac61266c9fffa58edc
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jan 14 11:02:10 2016 +0100

    libcli/security: prepare sddl machine/forest_sid handling
    
    In future we need to pass in 3 sids to sddl_encode()
    
    Once we pass in a machine_sid from the caller we need to
    have a test on a Windows member if the .machine_rid values
    really belong to the local machine sid.
    At least [MS-DTYP] 2.4.2.4 Well-Known SID Structures
    pretents "LA" and "LG" are relative to the local machine sid.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Mon Mar 20 10:53:41 UTC 2023 on atb-devel-224

commit bd327f7d7a0d5f3377129ceb7f74e9dcf40587f3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 25 14:23:45 2022 +0100

    libcli/security: simplify sddl_encode_sid()
    
    We should walk the sid_codes array just once.
    This makes further changes easier...
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>

commit 8f4aced365381cae70fa33f9f0641f33ab3db1fb
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 25 13:28:48 2022 +0100

    libcli/security: simplify rid-based SDDL sid strings
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>

commit 7d466a913f2c0038b30424403a7355db849fee7a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Apr 30 19:49:12 2020 +0200

    libcli/security: introduce struct sddl_transition_state
    
    In future we'll need more than 'domain_sid' in order
    to do the correct transition of SDDL to/from security_descriptor.
    
    In the end we most likely add an
    sddl_transition_{create,encode,decode}() api in order
    to allow the caller to create an sddl_transition_state
    once and then pass it to multiple calls to encode/decode.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>

-----------------------------------------------------------------------

Summary of changes:
 libcli/security/sddl.c | 186 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 127 insertions(+), 59 deletions(-)


Changeset truncated at 500 lines:

diff --git a/libcli/security/sddl.c b/libcli/security/sddl.c
index 076f040cfb8..dad5ce8f413 100644
--- a/libcli/security/sddl.c
+++ b/libcli/security/sddl.c
@@ -25,6 +25,12 @@
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "system/locale.h"
 
+struct sddl_transition_state {
+	const struct dom_sid *machine_sid;
+	const struct dom_sid *domain_sid;
+	const struct dom_sid *forest_sid;
+};
+
 struct flag_map {
 	const char *name;
 	uint32_t flag;
@@ -87,7 +93,9 @@ static bool sddl_map_flags(const struct flag_map *map, const char *str,
 static const struct {
 	const char *code;
 	const char *sid;
-	uint32_t rid;
+	uint32_t machine_rid;
+	uint32_t domain_rid;
+	uint32_t forest_rid;
 } sid_codes[] = {
 	{ .code = "WD", .sid = SID_WORLD },
 
@@ -147,28 +155,28 @@ static const struct {
 	{ .code = "AS", .sid = SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY },
 	{ .code = "SS", .sid = SID_SERVICE_ASSERTED_IDENTITY },
 
-	{ .code = "RO", .sid = NULL, .rid = DOMAIN_RID_ENTERPRISE_READONLY_DCS },
+	{ .code = "RO", .forest_rid = DOMAIN_RID_ENTERPRISE_READONLY_DCS },
 
-	{ .code = "LA", .sid = NULL, .rid = DOMAIN_RID_ADMINISTRATOR },
-	{ .code = "LG", .sid = NULL, .rid = DOMAIN_RID_GUEST },
+	{ .code = "LA", .machine_rid = DOMAIN_RID_ADMINISTRATOR },
+	{ .code = "LG", .machine_rid = DOMAIN_RID_GUEST },
 
-	{ .code = "DA", .sid = NULL, .rid = DOMAIN_RID_ADMINS },
-	{ .code = "DU", .sid = NULL, .rid = DOMAIN_RID_USERS },
-	{ .code = "DG", .sid = NULL, .rid = DOMAIN_RID_GUESTS },
-	{ .code = "DC", .sid = NULL, .rid = DOMAIN_RID_DOMAIN_MEMBERS },
-	{ .code = "DD", .sid = NULL, .rid = DOMAIN_RID_DCS },
-	{ .code = "CA", .sid = NULL, .rid = DOMAIN_RID_CERT_ADMINS },
-	{ .code = "SA", .sid = NULL, .rid = DOMAIN_RID_SCHEMA_ADMINS },
-	{ .code = "EA", .sid = NULL, .rid = DOMAIN_RID_ENTERPRISE_ADMINS },
-	{ .code = "PA", .sid = NULL, .rid = DOMAIN_RID_POLICY_ADMINS },
+	{ .code = "DA", .domain_rid = DOMAIN_RID_ADMINS },
+	{ .code = "DU", .domain_rid = DOMAIN_RID_USERS },
+	{ .code = "DG", .domain_rid = DOMAIN_RID_GUESTS },
+	{ .code = "DC", .domain_rid = DOMAIN_RID_DOMAIN_MEMBERS },
+	{ .code = "DD", .domain_rid = DOMAIN_RID_DCS },
+	{ .code = "CA", .domain_rid = DOMAIN_RID_CERT_ADMINS },
+	{ .code = "SA", .forest_rid = DOMAIN_RID_SCHEMA_ADMINS },
+	{ .code = "EA", .forest_rid = DOMAIN_RID_ENTERPRISE_ADMINS },
+	{ .code = "PA", .domain_rid = DOMAIN_RID_POLICY_ADMINS },
 
-	{ .code = "CN", .sid = NULL, .rid = DOMAIN_RID_CLONEABLE_CONTROLLERS },
+	{ .code = "CN", .domain_rid = DOMAIN_RID_CLONEABLE_CONTROLLERS },
 
-	{ .code = "AP", .sid = NULL, .rid = DOMAIN_RID_PROTECTED_USERS },
-	{ .code = "KA", .sid = NULL, .rid = DOMAIN_RID_KEY_ADMINS },
-	{ .code = "EK", .sid = NULL, .rid = DOMAIN_RID_ENTERPRISE_KEY_ADMINS },
+	{ .code = "AP", .domain_rid = DOMAIN_RID_PROTECTED_USERS },
+	{ .code = "KA", .domain_rid = DOMAIN_RID_KEY_ADMINS },
+	{ .code = "EK", .forest_rid = DOMAIN_RID_ENTERPRISE_KEY_ADMINS },
 
-	{ .code = "RS", .sid = NULL, .rid = DOMAIN_RID_RAS_SERVERS }
+	{ .code = "RS", .domain_rid = DOMAIN_RID_RAS_SERVERS }
 };
 
 /*
@@ -176,7 +184,7 @@ static const struct {
   It can either be a special 2 letter code, or in S-* format
 */
 static struct dom_sid *sddl_decode_sid(TALLOC_CTX *mem_ctx, const char **sddlp,
-				       const struct dom_sid *domain_sid)
+				       struct sddl_transition_state *state)
 {
 	const char *sddl = (*sddlp);
 	size_t i;
@@ -207,8 +215,20 @@ static struct dom_sid *sddl_decode_sid(TALLOC_CTX *mem_ctx, const char **sddlp,
 
 	(*sddlp) += 2;
 
-	if (sid_codes[i].sid == NULL) {
-		return dom_sid_add_rid(mem_ctx, domain_sid, sid_codes[i].rid);
+
+	if (sid_codes[i].machine_rid != 0) {
+		return dom_sid_add_rid(mem_ctx, state->machine_sid,
+				       sid_codes[i].machine_rid);
+	}
+
+	if (sid_codes[i].domain_rid != 0) {
+		return dom_sid_add_rid(mem_ctx, state->domain_sid,
+				       sid_codes[i].domain_rid);
+	}
+
+	if (sid_codes[i].forest_rid != 0) {
+		return dom_sid_add_rid(mem_ctx, state->forest_sid,
+				       sid_codes[i].forest_rid);
 	}
 
 	return dom_sid_parse_talloc(mem_ctx, sid_codes[i].sid);
@@ -305,7 +325,7 @@ static bool sddl_decode_access(const char *str, uint32_t *pmask)
   note that this routine modifies the string
 */
 static bool sddl_decode_ace(TALLOC_CTX *mem_ctx, struct security_ace *ace, char *str,
-			    const struct dom_sid *domain_sid)
+			    struct sddl_transition_state *state)
 {
 	const char *tok[6];
 	const char *s;
@@ -366,7 +386,7 @@ static bool sddl_decode_ace(TALLOC_CTX *mem_ctx, struct security_ace *ace, char
 
 	/* trustee */
 	s = tok[5];
-	sid = sddl_decode_sid(mem_ctx, &s, domain_sid);
+	sid = sddl_decode_sid(mem_ctx, &s, state);
 	if (sid == NULL) {
 		return false;
 	}
@@ -388,7 +408,7 @@ static const struct flag_map acl_flags[] = {
 */
 static struct security_acl *sddl_decode_acl(struct security_descriptor *sd,
 					    const char **sddlp, uint32_t *flags,
-					    const struct dom_sid *domain_sid)
+					    struct sddl_transition_state *state)
 {
 	const char *sddl = *sddlp;
 	struct security_acl *acl;
@@ -428,7 +448,7 @@ static struct security_acl *sddl_decode_acl(struct security_descriptor *sd,
 			return NULL;
 		}
 		if (!sddl_decode_ace(acl->aces, &acl->aces[acl->num_aces],
-				     astr, domain_sid)) {
+				     astr, state)) {
 			talloc_free(acl);
 			return NULL;
 		}
@@ -457,6 +477,16 @@ static struct security_acl *sddl_decode_acl(struct security_descriptor *sd,
 struct security_descriptor *sddl_decode(TALLOC_CTX *mem_ctx, const char *sddl,
 					const struct dom_sid *domain_sid)
 {
+	struct sddl_transition_state state = {
+		/*
+		 * TODO: verify .machine_rid values really belong to
+		 * to the machine_sid on a member, once
+		 * we pass machine_sid from the caller...
+		 */
+		.machine_sid = domain_sid,
+		.domain_sid = domain_sid,
+		.forest_sid = domain_sid,
+	};
 	struct security_descriptor *sd;
 	sd = talloc_zero(mem_ctx, struct security_descriptor);
 
@@ -472,13 +502,13 @@ struct security_descriptor *sddl_decode(TALLOC_CTX *mem_ctx, const char *sddl,
 		switch (c) {
 		case 'D':
 			if (sd->dacl != NULL) goto failed;
-			sd->dacl = sddl_decode_acl(sd, &sddl, &flags, domain_sid);
+			sd->dacl = sddl_decode_acl(sd, &sddl, &flags, &state);
 			if (sd->dacl == NULL) goto failed;
 			sd->type |= flags | SEC_DESC_DACL_PRESENT;
 			break;
 		case 'S':
 			if (sd->sacl != NULL) goto failed;
-			sd->sacl = sddl_decode_acl(sd, &sddl, &flags, domain_sid);
+			sd->sacl = sddl_decode_acl(sd, &sddl, &flags, &state);
 			if (sd->sacl == NULL) goto failed;
 			/* this relies on the SEC_DESC_SACL_* flags being
 			   1 bit shifted from the SEC_DESC_DACL_* flags */
@@ -486,12 +516,12 @@ struct security_descriptor *sddl_decode(TALLOC_CTX *mem_ctx, const char *sddl,
 			break;
 		case 'O':
 			if (sd->owner_sid != NULL) goto failed;
-			sd->owner_sid = sddl_decode_sid(sd, &sddl, domain_sid);
+			sd->owner_sid = sddl_decode_sid(sd, &sddl, &state);
 			if (sd->owner_sid == NULL) goto failed;
 			break;
 		case 'G':
 			if (sd->group_sid != NULL) goto failed;
-			sd->group_sid = sddl_decode_sid(sd, &sddl, domain_sid);
+			sd->group_sid = sddl_decode_sid(sd, &sddl, &state);
 			if (sd->group_sid == NULL) goto failed;
 			break;
 		}
@@ -547,45 +577,57 @@ failed:
   encode a sid in SDDL format
 */
 static char *sddl_encode_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
-			     const struct dom_sid *domain_sid)
+			     struct sddl_transition_state *state)
 {
+	bool in_machine = dom_sid_in_domain(state->machine_sid, sid);
+	bool in_domain = dom_sid_in_domain(state->domain_sid, sid);
+	bool in_forest = dom_sid_in_domain(state->forest_sid, sid);
+	struct dom_sid_buf buf;
+	const char *sidstr = dom_sid_str_buf(sid, &buf);
+	uint32_t rid = 0;
 	size_t i;
-	char *sidstr;
 
-	sidstr = dom_sid_string(mem_ctx, sid);
-	if (sidstr == NULL) return NULL;
+	if (sid->num_auths > 1) {
+		rid = sid->sub_auths[sid->num_auths-1];
+	}
+
+	for (i=0;i<ARRAY_SIZE(sid_codes);i++) {
+		/* seen if its a well known sid */
+		if (sid_codes[i].sid != NULL) {
+			int cmp;
+
+			cmp = strcmp(sidstr, sid_codes[i].sid);
+			if (cmp != 0) {
+				continue;
+			}
 
-	/* seen if its a well known sid */
-	for (i=0;sid_codes[i].sid;i++) {
-		if (strcmp(sidstr, sid_codes[i].sid) == 0) {
-			talloc_free(sidstr);
 			return talloc_strdup(mem_ctx, sid_codes[i].code);
 		}
-	}
 
-	/* or a well known rid in our domain */
-	if (dom_sid_in_domain(domain_sid, sid)) {
-		uint32_t rid = sid->sub_auths[sid->num_auths-1];
-		for (;i<ARRAY_SIZE(sid_codes);i++) {
-			if (rid == sid_codes[i].rid) {
-				talloc_free(sidstr);
-				return talloc_strdup(mem_ctx, sid_codes[i].code);
-			}
+		if (rid == 0) {
+			continue;
 		}
-	}
 
-	talloc_free(sidstr);
+		if (in_machine && sid_codes[i].machine_rid == rid) {
+			return talloc_strdup(mem_ctx, sid_codes[i].code);
+		}
+		if (in_domain && sid_codes[i].domain_rid == rid) {
+			return talloc_strdup(mem_ctx, sid_codes[i].code);
+		}
+		if (in_forest && sid_codes[i].forest_rid == rid) {
+			return talloc_strdup(mem_ctx, sid_codes[i].code);
+		}
+	}
 
-	/* TODO: encode well known sids as two letter codes */
-	return dom_sid_string(mem_ctx, sid);
+	return talloc_strdup(mem_ctx, sidstr);
 }
 
 
 /*
   encode an ACE in SDDL format
 */
-char *sddl_encode_ace(TALLOC_CTX *mem_ctx, const struct security_ace *ace,
-		      const struct dom_sid *domain_sid)
+static char *sddl_transition_encode_ace(TALLOC_CTX *mem_ctx, const struct security_ace *ace,
+					struct sddl_transition_state *state)
 {
 	char *sddl = NULL;
 	TALLOC_CTX *tmp_ctx;
@@ -639,7 +681,7 @@ char *sddl_encode_ace(TALLOC_CTX *mem_ctx, const struct security_ace *ace,
 		}
 	}
 
-	sddl_trustee = sddl_encode_sid(tmp_ctx, &ace->trustee, domain_sid);
+	sddl_trustee = sddl_encode_sid(tmp_ctx, &ace->trustee, state);
 	if (sddl_trustee == NULL) {
 		goto failed;
 	}
@@ -653,11 +695,27 @@ failed:
 	return sddl;
 }
 
+char *sddl_encode_ace(TALLOC_CTX *mem_ctx, const struct security_ace *ace,
+		      const struct dom_sid *domain_sid)
+{
+	struct sddl_transition_state state = {
+		/*
+		 * TODO: verify .machine_rid values really belong to
+		 * to the machine_sid on a member, once
+		 * we pass machine_sid from the caller...
+		 */
+		.machine_sid = domain_sid,
+		.domain_sid = domain_sid,
+		.forest_sid = domain_sid,
+	};
+	return sddl_transition_encode_ace(mem_ctx, ace, &state);
+}
+
 /*
   encode an ACL in SDDL format
 */
 static char *sddl_encode_acl(TALLOC_CTX *mem_ctx, const struct security_acl *acl,
-			     uint32_t flags, const struct dom_sid *domain_sid)
+			     uint32_t flags, struct sddl_transition_state *state)
 {
 	char *sddl;
 	uint32_t i;
@@ -668,7 +726,7 @@ static char *sddl_encode_acl(TALLOC_CTX *mem_ctx, const struct security_acl *acl
 
 	/* now the ACEs, encoded in braces */
 	for (i=0;i<acl->num_aces;i++) {
-		char *ace = sddl_encode_ace(sddl, &acl->aces[i], domain_sid);
+		char *ace = sddl_transition_encode_ace(sddl, &acl->aces[i], state);
 		if (ace == NULL) goto failed;
 		sddl = talloc_asprintf_append_buffer(sddl, "(%s)", ace);
 		if (sddl == NULL) goto failed;
@@ -689,6 +747,16 @@ failed:
 char *sddl_encode(TALLOC_CTX *mem_ctx, const struct security_descriptor *sd,
 		  const struct dom_sid *domain_sid)
 {
+	struct sddl_transition_state state = {
+		/*
+		 * TODO: verify .machine_rid values really belong to
+		 * to the machine_sid on a member, once
+		 * we pass machine_sid from the caller...
+		 */
+		.machine_sid = domain_sid,
+		.domain_sid = domain_sid,
+		.forest_sid = domain_sid,
+	};
 	char *sddl;
 	TALLOC_CTX *tmp_ctx;
 
@@ -699,28 +767,28 @@ char *sddl_encode(TALLOC_CTX *mem_ctx, const struct security_descriptor *sd,
 	tmp_ctx = talloc_new(mem_ctx);
 
 	if (sd->owner_sid != NULL) {
-		char *sid = sddl_encode_sid(tmp_ctx, sd->owner_sid, domain_sid);
+		char *sid = sddl_encode_sid(tmp_ctx, sd->owner_sid, &state);
 		if (sid == NULL) goto failed;
 		sddl = talloc_asprintf_append_buffer(sddl, "O:%s", sid);
 		if (sddl == NULL) goto failed;
 	}
 
 	if (sd->group_sid != NULL) {
-		char *sid = sddl_encode_sid(tmp_ctx, sd->group_sid, domain_sid);
+		char *sid = sddl_encode_sid(tmp_ctx, sd->group_sid, &state);
 		if (sid == NULL) goto failed;
 		sddl = talloc_asprintf_append_buffer(sddl, "G:%s", sid);
 		if (sddl == NULL) goto failed;
 	}
 
 	if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl != NULL) {
-		char *acl = sddl_encode_acl(tmp_ctx, sd->dacl, sd->type, domain_sid);
+		char *acl = sddl_encode_acl(tmp_ctx, sd->dacl, sd->type, &state);
 		if (acl == NULL) goto failed;
 		sddl = talloc_asprintf_append_buffer(sddl, "D:%s", acl);
 		if (sddl == NULL) goto failed;
 	}
 
 	if ((sd->type & SEC_DESC_SACL_PRESENT) && sd->sacl != NULL) {
-		char *acl = sddl_encode_acl(tmp_ctx, sd->sacl, sd->type>>1, domain_sid);
+		char *acl = sddl_encode_acl(tmp_ctx, sd->sacl, sd->type>>1, &state);
 		if (acl == NULL) goto failed;
 		sddl = talloc_asprintf_append_buffer(sddl, "S:%s", acl);
 		if (sddl == NULL) goto failed;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list