From 02e7c70ab3198f72c988327200cfa90da0096253 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 7 Feb 2024 08:46:43 +0100 Subject: [PATCH] smbd: move token_contains_name() to util_namearray.c and make it public Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher --- source3/include/proto.h | 6 ++ source3/lib/util_namearray.c | 139 +++++++++++++++++++++++++++++++++++ source3/smbd/share_access.c | 138 ---------------------------------- 3 files changed, 145 insertions(+), 138 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index b25b1177841..6ec4b802eac 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -318,6 +318,12 @@ const char *readdirname(DIR *p); bool is_in_path(const char *name, struct name_compare_entry *namelist, bool case_sensitive); +bool token_contains_name(TALLOC_CTX *mem_ctx, + const char *username, + const char *domain, + const char *sharename, + const struct security_token *token, + const char *name); void set_namearray(TALLOC_CTX *mem_ctx, const char *namelist, struct name_compare_entry **_name_array); diff --git a/source3/lib/util_namearray.c b/source3/lib/util_namearray.c index 43cf3e24536..0054ecbfac7 100644 --- a/source3/lib/util_namearray.c +++ b/source3/lib/util_namearray.c @@ -19,6 +19,145 @@ #include "includes.h" #include "lib/util/strv.h" +#include "libcli/security/security.h" +#include "source3/lib/substitute.h" +#include "passdb/lookup_sid.h" +#include "auth.h" + +/* + * No prefix means direct username + * @name means netgroup first, then unix group + * &name means netgroup + * +name means unix group + * + and & may be combined + */ + +static bool do_group_checks(const char **name, const char **pattern) +{ + if ((*name)[0] == '@') { + *pattern = "&+"; + *name += 1; + return True; + } + + if (((*name)[0] == '+') && ((*name)[1] == '&')) { + *pattern = "+&"; + *name += 2; + return True; + } + + if ((*name)[0] == '+') { + *pattern = "+"; + *name += 1; + return True; + } + + if (((*name)[0] == '&') && ((*name)[1] == '+')) { + *pattern = "&+"; + *name += 2; + return True; + } + + if ((*name)[0] == '&') { + *pattern = "&"; + *name += 1; + return True; + } + + return False; +} + +bool token_contains_name(TALLOC_CTX *mem_ctx, + const char *username, + const char *domain, + const char *sharename, + const struct security_token *token, + const char *name) +{ + const char *prefix; + struct dom_sid sid; + enum lsa_SidType type; + + if (username != NULL) { + size_t domain_len = domain != NULL ? strlen(domain) : 0; + + /* Check if username starts with domain name */ + if (domain_len > 0) { + const char *sep = lp_winbind_separator(); + int cmp = strncasecmp_m(username, domain, domain_len); + if (cmp == 0 && sep[0] == username[domain_len]) { + /* Move after the winbind separator */ + domain_len += 1; + } else { + domain_len = 0; + } + } + name = talloc_sub_basic(mem_ctx, + username + domain_len, + domain, + name); + } + if (sharename != NULL) { + name = talloc_string_sub(mem_ctx, name, "%S", sharename); + } + + if (name == NULL) { + /* This is too security sensitive, better panic than return a + * result that might be interpreted in a wrong way. */ + smb_panic("substitutions failed"); + } + + if ( string_to_sid( &sid, name ) ) { + DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name)); + return nt_token_check_sid( &sid, token ); + } + + if (!do_group_checks(&name, &prefix)) { + if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL, + NULL, NULL, &sid, &type)) { + DEBUG(5, ("lookup_name %s failed\n", name)); + return False; + } + if (type != SID_NAME_USER) { + DEBUG(5, ("%s is a %s, expected a user\n", + name, sid_type_lookup(type))); + return False; + } + return nt_token_check_sid(&sid, token); + } + + for (/* initialized above */ ; *prefix != '\0'; prefix++) { + if (*prefix == '+') { + if (!lookup_name_smbconf(mem_ctx, name, + LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, + NULL, NULL, &sid, &type)) { + DEBUG(5, ("lookup_name %s failed\n", name)); + return False; + } + if ((type != SID_NAME_DOM_GRP) && + (type != SID_NAME_ALIAS) && + (type != SID_NAME_WKN_GRP)) { + DEBUG(5, ("%s is a %s, expected a group\n", + name, sid_type_lookup(type))); + return False; + } + if (nt_token_check_sid(&sid, token)) { + return True; + } + continue; + } + if (*prefix == '&') { + if (username) { + if (user_in_netgroup(mem_ctx, username, name)) { + return True; + } + } + continue; + } + smb_panic("got invalid prefix from do_groups_check"); + } + return False; +} /******************************************************************* Strip a '/' separated list into an array of diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index 45928144693..ef7c0c1f932 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -21,144 +21,6 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "../libcli/security/security.h" -#include "passdb/lookup_sid.h" -#include "auth.h" -#include "source3/lib/substitute.h" - -/* - * No prefix means direct username - * @name means netgroup first, then unix group - * &name means netgroup - * +name means unix group - * + and & may be combined - */ - -static bool do_group_checks(const char **name, const char **pattern) -{ - if ((*name)[0] == '@') { - *pattern = "&+"; - *name += 1; - return True; - } - - if (((*name)[0] == '+') && ((*name)[1] == '&')) { - *pattern = "+&"; - *name += 2; - return True; - } - - if ((*name)[0] == '+') { - *pattern = "+"; - *name += 1; - return True; - } - - if (((*name)[0] == '&') && ((*name)[1] == '+')) { - *pattern = "&+"; - *name += 2; - return True; - } - - if ((*name)[0] == '&') { - *pattern = "&"; - *name += 1; - return True; - } - - return False; -} - -static bool token_contains_name(TALLOC_CTX *mem_ctx, - const char *username, - const char *domain, - const char *sharename, - const struct security_token *token, - const char *name) -{ - const char *prefix; - struct dom_sid sid; - enum lsa_SidType type; - - if (username != NULL) { - size_t domain_len = domain != NULL ? strlen(domain) : 0; - - /* Check if username starts with domain name */ - if (domain_len > 0) { - const char *sep = lp_winbind_separator(); - int cmp = strncasecmp_m(username, domain, domain_len); - if (cmp == 0 && sep[0] == username[domain_len]) { - /* Move after the winbind separator */ - domain_len += 1; - } else { - domain_len = 0; - } - } - name = talloc_sub_basic(mem_ctx, - username + domain_len, - domain, - name); - } - if (sharename != NULL) { - name = talloc_string_sub(mem_ctx, name, "%S", sharename); - } - - if (name == NULL) { - /* This is too security sensitive, better panic than return a - * result that might be interpreted in a wrong way. */ - smb_panic("substitutions failed"); - } - - if ( string_to_sid( &sid, name ) ) { - DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name)); - return nt_token_check_sid( &sid, token ); - } - - if (!do_group_checks(&name, &prefix)) { - if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL, - NULL, NULL, &sid, &type)) { - DEBUG(5, ("lookup_name %s failed\n", name)); - return False; - } - if (type != SID_NAME_USER) { - DEBUG(5, ("%s is a %s, expected a user\n", - name, sid_type_lookup(type))); - return False; - } - return nt_token_check_sid(&sid, token); - } - - for (/* initialized above */ ; *prefix != '\0'; prefix++) { - if (*prefix == '+') { - if (!lookup_name_smbconf(mem_ctx, name, - LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, - NULL, NULL, &sid, &type)) { - DEBUG(5, ("lookup_name %s failed\n", name)); - return False; - } - if ((type != SID_NAME_DOM_GRP) && - (type != SID_NAME_ALIAS) && - (type != SID_NAME_WKN_GRP)) { - DEBUG(5, ("%s is a %s, expected a group\n", - name, sid_type_lookup(type))); - return False; - } - if (nt_token_check_sid(&sid, token)) { - return True; - } - continue; - } - if (*prefix == '&') { - if (username) { - if (user_in_netgroup(mem_ctx, username, name)) { - return True; - } - } - continue; - } - smb_panic("got invalid prefix from do_groups_check"); - } - return False; -} /* * Check whether a user is contained in the list provided. -- 2.47.3