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 <me...@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 <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Mon Mar 20 10:53:41 UTC 2023 on atb-devel-224 commit bd327f7d7a0d5f3377129ceb7f74e9dcf40587f3 Author: Stefan Metzmacher <me...@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 <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> commit 8f4aced365381cae70fa33f9f0641f33ab3db1fb Author: Stefan Metzmacher <me...@samba.org> Date: Fri Mar 25 13:28:48 2022 +0100 libcli/security: simplify rid-based SDDL sid strings Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> commit 7d466a913f2c0038b30424403a7355db849fee7a Author: Stefan Metzmacher <me...@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 <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@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