From 043db6c8d3a5e44b853c0df8a6f961b51344e46c Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Fri, 3 Jun 2022 14:01:36 +0200 Subject: [PATCH 1/4] Revert "s3:auth: Fix user_in_list() for UNIX groups" This partly reverts commit 6dc463d3e2eb229df1c4f620cfcaf22ac71738d4. Reverted to allow next revert commits to apply cleanly. Do not recreate selftest/knownfail.d/usernamemap file. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15087 Signed-off-by: Samuel Cabrero Reviewed-by: Jeremy Allison (cherry picked from commit dbf3d217e3424fae64d9bd00e4762dc4d2bda6c2) --- source3/auth/user_util.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/source3/auth/user_util.c b/source3/auth/user_util.c index aa765c2a692..70b4f320c5e 100644 --- a/source3/auth/user_util.c +++ b/source3/auth/user_util.c @@ -143,11 +143,11 @@ bool user_in_list(TALLOC_CTX *ctx, const char *user, const char * const *list) return false; } + DBG_DEBUG("Checking user %s in list\n", user); + while (*list) { const char *p = *list; - bool check_unix_group = false; - - DBG_DEBUG("Checking user '%s' in list '%s'.\n", user, *list); + bool ok; /* Check raw username */ if (strequal(user, p)) { @@ -155,13 +155,11 @@ bool user_in_list(TALLOC_CTX *ctx, const char *user, const char * const *list) } while (*p == '@' || *p == '&' || *p == '+') { - if (*p == '@' || *p == '+') { - check_unix_group = true; - } p++; } - if (check_unix_group && user_in_group(user, p)) { + ok = user_in_group(user, p); + if (ok) { return true; } -- 2.36.1 From 74b64b3c99e6dae33037ffb9763cdecc738f6537 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Fri, 3 Jun 2022 14:12:01 +0200 Subject: [PATCH 2/4] Revert "docs-xml: Update documentation for removal of NIS support" This partly reverts commit a72bc3e15d3ed62e9ad2c0a97ce5d6d653abb048. Revert only the chunks related to netgroups and skip NIS related ones. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15087 Signed-off-by: Samuel Cabrero Reviewed-by: Jeremy Allison (cherry picked from commit f74e284a9d7fa8dc45f22b70dcea27f1aa8bd232) --- docs-xml/smbdotconf/security/hostsallow.xml | 7 +++++++ docs-xml/smbdotconf/security/invalidusers.xml | 15 ++++++++++++++- docs-xml/smbdotconf/security/usernamemap.xml | 5 +++++ docs-xml/smbdotconf/security/validusers.xml | 7 +++---- docs-xml/smbdotconf/winbind/winbindseparator.xml | 4 ++-- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/docs-xml/smbdotconf/security/hostsallow.xml b/docs-xml/smbdotconf/security/hostsallow.xml index a052e7f79cd..8b4b62268a3 100644 --- a/docs-xml/smbdotconf/security/hostsallow.xml +++ b/docs-xml/smbdotconf/security/hostsallow.xml @@ -41,6 +41,13 @@ hosts allow = lapland, arvidsjaur + Example 4: allow only hosts in NIS netgroup "foonet", but + deny access from one particular host + + hosts allow = @foonet + + hosts deny = pirate + Note that access still requires suitable user-level passwords. See testparm diff --git a/docs-xml/smbdotconf/security/invalidusers.xml b/docs-xml/smbdotconf/security/invalidusers.xml index 268cdfad560..b2fb2b9d293 100644 --- a/docs-xml/smbdotconf/security/invalidusers.xml +++ b/docs-xml/smbdotconf/security/invalidusers.xml @@ -7,8 +7,21 @@ to login to this service. This is really a paranoid check to absolutely ensure an improper setting does not breach your security. + + A name starting with a '@' is interpreted as an NIS + netgroup first (if your system supports NIS), and then as a UNIX + group if the name was not found in the NIS netgroup database. - A name starting with a '@' is interpreted UNIX group. + A name starting with '+' is interpreted only + by looking in the UNIX group database via the NSS getgrnam() interface. A name starting with + '&' is interpreted only by looking in the NIS netgroup database + (this requires NIS to be working on your system). The characters + '+' and '&' may be used at the start of the name in either order + so the value +&group means check the + UNIX group database, followed by the NIS netgroup database, and + the value &+group means check the NIS + netgroup database, followed by the UNIX group database (the + same as the '@' prefix). The current servicename is substituted for %S. This is useful in the [homes] section. diff --git a/docs-xml/smbdotconf/security/usernamemap.xml b/docs-xml/smbdotconf/security/usernamemap.xml index eab72bb8672..809a54c1e2f 100644 --- a/docs-xml/smbdotconf/security/usernamemap.xml +++ b/docs-xml/smbdotconf/security/usernamemap.xml @@ -58,6 +58,11 @@ + + If your system supports the NIS NETGROUP option then the netgroup database is checked before the /etc/group database for matching groups. + + You can map Windows usernames that have spaces in them by using double quotes around the name. For example: diff --git a/docs-xml/smbdotconf/security/validusers.xml b/docs-xml/smbdotconf/security/validusers.xml index 6b0bacfd78a..0b681a1fef5 100644 --- a/docs-xml/smbdotconf/security/validusers.xml +++ b/docs-xml/smbdotconf/security/validusers.xml @@ -4,10 +4,9 @@ xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> - This is a list of users that should be allowed to login to this service. - Names starting with an '@' are interpreted using the same rules as - described in the - invalid users parameter. + This is a list of users that should be allowed to login to this service. Names starting with + '@', '+' and '&' are interpreted using the same rules as described in the + invalid users parameter. diff --git a/docs-xml/smbdotconf/winbind/winbindseparator.xml b/docs-xml/smbdotconf/winbind/winbindseparator.xml index 9be46109cd6..eda14f4e03a 100644 --- a/docs-xml/smbdotconf/winbind/winbindseparator.xml +++ b/docs-xml/smbdotconf/winbind/winbindseparator.xml @@ -10,9 +10,9 @@ and nss_winbind.so modules for UNIX services. - Please note that setting this parameter to + can cause problems + Please note that setting this parameter to + causes problems with group membership at least on glibc systems, as the character + - was used as a special character for NIS in /etc/group. + is used as a special character for NIS in /etc/group. \ -- 2.36.1 From 60b6c00182ebbc890c11024116c5934f627f8d39 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Fri, 3 Jun 2022 15:07:18 +0200 Subject: [PATCH 3/4] Revert "s3:smbd: Remove NIS support" This partly reverts commit edda7a329e5bed442418de9782cec9f567092aae. Revert the chunks related to netgroups and skip NIS support related ones. Use getdomainname() from glibc instead of yp_get_default_domain() from libnsl to get the NIS domain name. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15087 Signed-off-by: Samuel Cabrero Reviewed-by: Jeremy Allison (cherry picked from commit 21796ef8f807d88e01627dc993b757e251788980) --- selftest/target/Samba3.pm | 4 + source3/auth/user_util.c | 141 ++++++++++++++++++---- source3/script/tests/test_smbclient_s3.sh | 13 ++ source3/smbd/share_access.c | 21 ++-- source3/wscript | 4 + 5 files changed, 154 insertions(+), 29 deletions(-) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 8d309f9c99a..ba0ebb58b2f 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -767,6 +767,10 @@ sub provision_ad_member path = $share_dir valid users = \"+$dcvars->{DOMAIN}/domain users\" +[valid_users_nis_group] + path = $share_dir + valid users = \"&$dcvars->{DOMAIN}/domain users\" + [valid_users_unix_nis_group] path = $share_dir valid users = \"+&$dcvars->{DOMAIN}/domain users\" diff --git a/source3/auth/user_util.c b/source3/auth/user_util.c index 70b4f320c5e..f40123e246a 100644 --- a/source3/auth/user_util.c +++ b/source3/auth/user_util.c @@ -129,44 +129,141 @@ static void store_map_in_gencache(TALLOC_CTX *ctx, const char *from, const char } /**************************************************************************** - Check if a user is in a user list - - We removed NIS support in 2021, but need to keep configs working. - - TOOD FIXME: Remove this funciton + Check if a user is in a netgroup user list. If at first we don't succeed, + try lower case. ****************************************************************************/ -bool user_in_list(TALLOC_CTX *ctx, const char *user, const char * const *list) +bool user_in_netgroup(TALLOC_CTX *ctx, const char *user, const char *ngname) { +#ifdef HAVE_NETGROUP + char nis_domain_buf[256]; + const char *nis_domain = NULL; + char *lowercase_user = NULL; + + if (getdomainname(nis_domain_buf, sizeof(nis_domain_buf)) == 0) { + nis_domain = &nis_domain_buf[0]; + } else { + DEBUG(5,("Unable to get default yp domain, " + "let's try without specifying it\n")); + nis_domain = NULL; + } + + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", + user, nis_domain ? nis_domain : "(ANY)", ngname)); + + if (innetgr(ngname, NULL, user, nis_domain)) { + DEBUG(5,("user_in_netgroup: Found\n")); + return true; + } + + /* + * Ok, innetgr is case sensitive. Try once more with lowercase + * just in case. Attempt to fix #703. JRA. + */ + lowercase_user = talloc_strdup(ctx, user); + if (!lowercase_user) { + return false; + } + if (!strlower_m(lowercase_user)) { + return false; + } - if (list == NULL || *list == NULL) { + if (strcmp(user,lowercase_user) == 0) { + /* user name was already lower case! */ return false; } - DBG_DEBUG("Checking user %s in list\n", user); + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", + lowercase_user, nis_domain ? nis_domain : "(ANY)", ngname)); + + if (innetgr(ngname, NULL, lowercase_user, nis_domain)) { + DEBUG(5,("user_in_netgroup: Found\n")); + return true; + } +#endif /* HAVE_NETGROUP */ + return false; +} + +/**************************************************************************** + Check if a user is in a user list - can check combinations of UNIX + and netgroup lists. +****************************************************************************/ + +bool user_in_list(TALLOC_CTX *ctx, const char *user, const char * const *list) +{ + if (!list || !*list) + return False; + + DEBUG(10,("user_in_list: checking user %s in list\n", user)); while (*list) { - const char *p = *list; - bool ok; - /* Check raw username */ - if (strequal(user, p)) { - return true; - } + DEBUG(10,("user_in_list: checking user |%s| against |%s|\n", + user, *list)); + + /* + * Check raw username. + */ + if (strequal(user, *list)) + return(True); + + /* + * Now check to see if any combination + * of UNIX and netgroups has been specified. + */ + + if(**list == '@') { + /* + * Old behaviour. Check netgroup list + * followed by UNIX list. + */ + if(user_in_netgroup(ctx, user, *list +1)) + return True; + if(user_in_group(user, *list +1)) + return True; + } else if (**list == '+') { - while (*p == '@' || *p == '&' || *p == '+') { - p++; - } + if((*(*list +1)) == '&') { + /* + * Search UNIX list followed by netgroup. + */ + if(user_in_group(user, *list +2)) + return True; + if(user_in_netgroup(ctx, user, *list +2)) + return True; + + } else { - ok = user_in_group(user, p); - if (ok) { - return true; + /* + * Just search UNIX list. + */ + + if(user_in_group(user, *list +1)) + return True; + } + + } else if (**list == '&') { + + if(*(*list +1) == '+') { + /* + * Search netgroup list followed by UNIX list. + */ + if(user_in_netgroup(ctx, user, *list +2)) + return True; + if(user_in_group(user, *list +2)) + return True; + } else { + /* + * Just search netgroup list. + */ + if(user_in_netgroup(ctx, user, *list +1)) + return True; + } } list++; } - - return false; + return(False); } bool map_username(TALLOC_CTX *ctx, const char *user_in, char **p_user_out) diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh index 3da37e699e6..4d03b97f476 100755 --- a/source3/script/tests/test_smbclient_s3.sh +++ b/source3/script/tests/test_smbclient_s3.sh @@ -1965,6 +1965,19 @@ EOF return 1 fi + # User not in NIS group in "valid users" can't login to service + cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_users_nis_group $ADDARGS < $tmpfile 2>&1' + eval echo "$cmd" + out=`eval $cmd` + echo "$out" | grep 'NT_STATUS_ACCESS_DENIED' + ret=$? + + if [ $ret -ne 0 ] ; then + echo "$out" + echo "test_valid_users:valid_users_nis_group 'User not in NIS group in 'valid users' can't login to service' failed - $ret" + return 1 + fi + # Check user in UNIX, then in NIS group in "valid users" can login to service cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$DC_USERNAME%$DC_PASSWORD //$SERVER/valid_users_unix_nis_group $ADDARGS < $tmpfile 2>&1' eval echo "$cmd" diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index c44c4bd8c69..45928144693 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -26,21 +26,23 @@ #include "source3/lib/substitute.h" /* - * We dropped NIS support in 2021, but need to keep configs working. - * - * TODO FIXME: Remove me in future + * 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 = "+"; + *pattern = "&+"; *name += 1; return True; } if (((*name)[0] == '+') && ((*name)[1] == '&')) { - *pattern = "+"; + *pattern = "+&"; *name += 2; return True; } @@ -52,13 +54,13 @@ static bool do_group_checks(const char **name, const char **pattern) } if (((*name)[0] == '&') && ((*name)[1] == '+')) { - *pattern = "+"; + *pattern = "&+"; *name += 2; return True; } if ((*name)[0] == '&') { - *pattern = "+"; + *pattern = "&"; *name += 1; return True; } @@ -146,6 +148,11 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx, 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"); diff --git a/source3/wscript b/source3/wscript index 8ec9ed1d9b9..b664b6fe9e9 100644 --- a/source3/wscript +++ b/source3/wscript @@ -139,6 +139,7 @@ def configure(conf): conf.CHECK_FUNCS('lutimes utimensat futimens') conf.CHECK_FUNCS('mlock munlock mlockall munlockall') conf.CHECK_FUNCS('memalign posix_memalign hstrerror') + conf.CHECK_FUNCS('getdomainname') conf.CHECK_FUNCS_IN('dn_expand _dn_expand __dn_expand', 'resolv') conf.CHECK_FUNCS_IN('dn_expand', 'inet') conf.CHECK_DECLS('readahead', reverse=True, headers='fcntl.h') @@ -628,6 +629,9 @@ msg.msg_accrightslen = sizeof(fd); headers='unistd.h sys/types.h dirent.h', define='HAVE_DIRENT_D_OFF') + if (conf.CONFIG_SET('HAVE_GETDOMAINNAME')): + conf.DEFINE('HAVE_NETGROUP', '1') + # Look for CUPS if Options.options.with_cups: conf.find_program('cups-config', var='CUPS_CONFIG') -- 2.36.1 From 7097ddb4be0f9aa34bee1427b7c94cc31e8ac040 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Fri, 3 Jun 2022 17:48:21 +0200 Subject: [PATCH 4/4] Revert "lib:util: Remove NIS support from string_match()" This partly reverts commit 620de975f147ac9427b51ea0e1e3eabda443d4b6. Drop chunk including system/nis.h, drop wscript_build modifications, use getdomainname() from glibc instead of yp_get_default_domain() from libnsl. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15087 Signed-off-by: Samuel Cabrero Reviewed-by: Jeremy Allison (cherry picked from commit b3034f1209a6c45873882415c4291dde7eee76db) --- lib/util/access.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/lib/util/access.c b/lib/util/access.c index 5b53894b2ce..b1b4bffaeaa 100644 --- a/lib/util/access.c +++ b/lib/util/access.c @@ -114,6 +114,62 @@ static bool string_match(const char *tok,const char *s) && strequal_m(tok, s + str_len - tok_len)) { return true; } + } else if (tok[0] == '@') { /* netgroup: look it up */ +#ifdef HAVE_NETGROUP + DATA_BLOB tmp; + char *mydomain = NULL; + char *hostname = NULL; + bool netgroup_ok = false; + char nis_domain_buf[256]; + + if (memcache_lookup( + NULL, SINGLETON_CACHE, + data_blob_string_const_null("yp_default_domain"), + &tmp)) { + + SMB_ASSERT(tmp.length > 0); + mydomain = (tmp.data[0] == '\0') + ? NULL : (char *)tmp.data; + } else { + if (getdomainname(nis_domain_buf, + sizeof(nis_domain_buf)) == 0) { + mydomain = &nis_domain_buf[0]; + memcache_add(NULL, + SINGLETON_CACHE, + data_blob_string_const_null( + "yp_default_domain"), + data_blob_string_const_null( + mydomain)); + } else { + mydomain = NULL; + } + } + + if (!mydomain) { + DEBUG(0,("Unable to get default yp domain. " + "Try without it.\n")); + } + if (!(hostname = smb_xstrdup(s))) { + DEBUG(1,("out of memory for strdup!\n")); + return false; + } + + netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain); + + DBG_INFO("%s %s of domain %s in netgroup %s\n", + netgroup_ok ? "Found" : "Could not find", + hostname, + mydomain?mydomain:"(ANY)", + tok+1); + + SAFE_FREE(hostname); + + if (netgroup_ok) + return true; +#else + DEBUG(0,("access: netgroup support is not configured\n")); + return false; +#endif } else if (strequal_m(tok, "ALL")) { /* all: match any */ return true; } else if (strequal_m(tok, "FAIL")) { /* fail: match any */ -- 2.36.1