The branch, v4-13-stable has been updated via c02edb51e7f VERSION: Disable GIT_SNAPSHOT for the 4.13.15 release. via 0bdce27ce0e WHATSNEW: Add release notes for Samba 4.13.15. via dd679ce7f44 dsdb: Use DSDB_SEARCH_SHOW_EXTENDED_DN when searching for the local replicated object via 1e27b820dff CVE-2020-25717: s3-auth: fix MIT Realm regression via 105c6a15eff CVE-2020-25717: s3:auth: Fallback to a SID/UID based mapping if the named based lookup fails via 32ba258cd75 CVE-2020-25717: tests/krb5: Add a test for idmap_nss mapping users to SIDs via a40c007fb55 CVE-2020-25717: selftest: turn ad_member_no_nss_wb into ad_member_idmap_nss via 0a56d233bfd CVE-2020-25717: nsswitch/nsstest.c: Lower 'non existent uid' to make room for new accounts via 302bb70ebc9 CVE-2020-25717: tests/krb5: Add method to automatically obtain server credentials via a6eddc3bd7a CVE-2020-25727: idmap_nss: verify that the name of the sid belongs to the configured domain via fadf4963450 IPA DC: add missing checks via b7158d4ce85 s3:winbindd: fix "allow trusted domains = no" regression via 959fb5a4c69 VERSION: Bump version up to Samba 4.13.15... from db11778b576 VERSION: Disable GIT_SNAPSHOT for the 4.13.14 release.
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-13-stable - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: VERSION | 2 +- WHATSNEW.txt | 77 +++++++- auth/gensec/schannel.c | 1 + nsswitch/nsstest.c | 2 +- python/samba/tests/krb5/kdc_base_test.py | 42 +++++ python/samba/tests/krb5/test_idmap_nss.py | 232 ++++++++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/target/Samba.pm | 2 +- selftest/target/Samba3.pm | 24 ++- source3/auth/auth_util.c | 34 +++- source3/auth/user_krb5.c | 9 + source3/rpc_server/lsa/srv_lsa_nt.c | 1 + source3/winbindd/idmap_nss.c | 26 ++- source3/winbindd/winbindd_util.c | 2 +- source4/dsdb/samdb/ldb_modules/operational.c | 2 +- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 13 +- source4/selftest/tests.py | 18 +- 17 files changed, 469 insertions(+), 19 deletions(-) create mode 100755 python/samba/tests/krb5/test_idmap_nss.py Changeset truncated at 500 lines: diff --git a/VERSION b/VERSION index 50b46ed4289..06b6f42b27a 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=13 -SAMBA_VERSION_RELEASE=14 +SAMBA_VERSION_RELEASE=15 ######################################################## # If a official release has a serious bug # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 40753b2b500..60b7c75f90b 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,77 @@ + =============================== + Release Notes for Samba 4.13.15 + December 15, 2021 + =============================== + + +This is the latest stable release of the Samba 4.13 release series. + +Important Notes +=============== + +There have been a few regressions in the security release 4.13.14: + +o CVE-2020-25717: A user on the domain can become root on domain members. + https://www.samba.org/samba/security/CVE-2020-25717.html + PLEASE [RE-]READ! + The instructions have been updated and some workarounds + initially adviced for 4.13.14 are no longer required and + should be reverted in most cases. + +o BUG-14902: User with multiple spaces (eg Fred<space><space>Nurk) become + un-deletable. While this release should fix this bug, it is + adviced to have a look at the bug report for more detailed + information, see https://bugzilla.samba.org/show_bug.cgi?id=14902. + +Changes since 4.13.14 +--------------------- + +o Andrew Bartlett <abart...@samba.org> + * BUG 14656: Spaces incorrectly collapsed in ldb attributes. + * BUG 14901: The CVE-2020-25717 username map [script] advice has undesired + side effects for the local nt token. + * BUG 14902: User with multiple spaces (eg Fred<space><space>Nurk) become un- + deletable. + +o Ralph Boehme <s...@samba.org> + * BUG 14922: Kerberos authentication on standalone server in MIT realm + broken. + +o Alexander Bokovoy <a...@samba.org> + * BUG 14903: Support for ROLE_IPA_DC is incomplete. + +o Stefan Metzmacher <me...@samba.org> + * BUG 14899: winbindd doesn't start when "allow trusted domains" is off. + * BUG 14901: The CVE-2020-25717 username map [script] advice has undesired + side effects for the local nt token. + +o Joseph Sutton <josephsut...@catalyst.net.nz> + * BUG 14901: The CVE-2020-25717 username map [script] advice has undesired + side effects for the local nt token. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the Samba 4.1 and newer product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- =============================== Release Notes for Samba 4.13.14 November 9, 2021 @@ -103,8 +177,7 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- =============================== diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c index 0cdae141ead..6ebbe8f3179 100644 --- a/auth/gensec/schannel.c +++ b/auth/gensec/schannel.c @@ -1080,6 +1080,7 @@ static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: case ROLE_ACTIVE_DIRECTORY_DC: + case ROLE_IPA_DC: return NT_STATUS_OK; default: return NT_STATUS_NOT_IMPLEMENTED; diff --git a/nsswitch/nsstest.c b/nsswitch/nsstest.c index e2ee9fbf3af..45270cdc459 100644 --- a/nsswitch/nsstest.c +++ b/nsswitch/nsstest.c @@ -466,7 +466,7 @@ static void nss_test_errors(void) printf("ERROR Non existent user gave error %d\n", last_error); } - pwd = getpwuid(0xFFF0); + pwd = getpwuid(0xFF00); if (pwd || last_error != NSS_STATUS_NOTFOUND) { total_errors++; printf("ERROR Non existent uid gave error %d\n", last_error); diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index f64bd0b206e..6e96b982167 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -1063,6 +1063,48 @@ class KDCBaseTest(RawKerberosTest): fallback_creds_fn=download_dc_creds) return c + def get_server_creds(self, + require_keys=True, + require_strongest_key=False): + if require_strongest_key: + self.assertTrue(require_keys) + + def download_server_creds(): + samdb = self.get_samdb() + + res = samdb.search(base=samdb.get_default_basedn(), + expression=(f'(|(sAMAccountName={self.host}*)' + f'(dNSHostName={self.host}))'), + scope=ldb.SCOPE_SUBTREE, + attrs=['sAMAccountName', + 'msDS-KeyVersionNumber']) + self.assertEqual(1, len(res)) + dn = res[0].dn + username = str(res[0]['sAMAccountName']) + + creds = KerberosCredentials() + creds.set_domain(self.env_get_var('DOMAIN', 'SERVER')) + creds.set_realm(self.env_get_var('REALM', 'SERVER')) + creds.set_username(username) + + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) + creds.set_dn(dn) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) + + self.creds_set_enctypes(creds) + + return creds + + c = self._get_krb5_creds(prefix='SERVER', + allow_missing_password=True, + allow_missing_keys=not require_keys, + require_strongest_key=require_strongest_key, + fallback_creds_fn=download_server_creds) + return c + def as_req(self, cname, sname, realm, etypes, padata=None, kdc_options=0): '''Send a Kerberos AS_REQ, returns the undecoded response ''' diff --git a/python/samba/tests/krb5/test_idmap_nss.py b/python/samba/tests/krb5/test_idmap_nss.py new file mode 100755 index 00000000000..d3480dbca3f --- /dev/null +++ b/python/samba/tests/krb5/test_idmap_nss.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) 2021 Catalyst.Net Ltd +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import sys +import os + +from ldb import SCOPE_SUBTREE +from samba import NTSTATUSError +from samba.credentials import DONT_USE_KERBEROS +from samba.dcerpc import security +from samba.ndr import ndr_unpack +from samba.ntstatus import ( + NT_STATUS_NO_IMPERSONATION_TOKEN, + NT_STATUS_LOGON_FAILURE +) +from samba.samba3 import libsmb_samba_internal as libsmb +from samba.samba3 import param as s3param + +from samba.tests.krb5.kdc_base_test import KDCBaseTest + +sys.path.insert(0, 'bin/python') +os.environ['PYTHONUNBUFFERED'] = '1' + +global_asn1_print = False +global_hexdump = False + + +class IdmapNssTests(KDCBaseTest): + + mappeduser_uid = 0xffff - 14 + mappeduser_sid = security.dom_sid(f'S-1-22-1-{mappeduser_uid}') + unmappeduser_uid = 0xffff - 15 + unmappeduser_sid = security.dom_sid(f'S-1-22-1-{unmappeduser_uid}') + + def get_mapped_creds(self, + allow_missing_password=False, + allow_missing_keys=True): + c = self._get_krb5_creds(prefix='MAPPED', + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) + c.set_workstation('') + return c + + def get_unmapped_creds(self, + allow_missing_password=False, + allow_missing_keys=True): + c = self._get_krb5_creds(prefix='UNMAPPED', + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) + c.set_workstation('') + return c + + def get_invalid_creds(self, + allow_missing_password=False, + allow_missing_keys=True): + c = self._get_krb5_creds(prefix='INVALID', + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) + c.set_workstation('') + return c + + # Expect a mapping to the local user SID. + def test_mapped_user_kerberos(self): + user_creds = self.get_mapped_creds() + self._run_idmap_nss_test(user_creds, use_kerberos=True, + expected_first_sid=self.mappeduser_sid, + expected_uid=self.mappeduser_uid) + + # Expect a mapping to the local user SID. + def test_mapped_user_ntlm(self): + user_creds = self.get_mapped_creds() + self._run_idmap_nss_test(user_creds, use_kerberos=False, + expected_first_sid=self.mappeduser_sid, + expected_uid=self.mappeduser_uid) + + def test_mapped_user_no_pac_kerberos(self): + user_creds = self.get_mapped_creds() + self._run_idmap_nss_test( + user_creds, use_kerberos=True, remove_pac=True, + expected_error=NT_STATUS_NO_IMPERSONATION_TOKEN) + + def test_unmapped_user_kerberos(self): + user_creds = self.get_unmapped_creds() + self._run_idmap_nss_test(user_creds, use_kerberos=True, + expected_additional_sid=self.unmappeduser_sid, + expected_uid=self.unmappeduser_uid) + + def test_unmapped_user_ntlm(self): + user_creds = self.get_unmapped_creds() + self._run_idmap_nss_test(user_creds, use_kerberos=False, + expected_additional_sid=self.unmappeduser_sid, + expected_uid=self.unmappeduser_uid) + + def test_unmapped_user_no_pac_kerberos(self): + user_creds = self.get_unmapped_creds() + self._run_idmap_nss_test( + user_creds, use_kerberos=True, remove_pac=True, + expected_error=NT_STATUS_NO_IMPERSONATION_TOKEN) + + def test_invalid_user_kerberos(self): + user_creds = self.get_invalid_creds() + self._run_idmap_nss_test(user_creds, use_kerberos=True, + expected_error=NT_STATUS_LOGON_FAILURE) + + def test_invalid_user_ntlm(self): + user_creds = self.get_invalid_creds() + self._run_idmap_nss_test(user_creds, use_kerberos=False, + expected_error=NT_STATUS_LOGON_FAILURE) + + def test_invalid_user_no_pac_kerberos(self): + user_creds = self.get_invalid_creds() + self._run_idmap_nss_test( + user_creds, use_kerberos=True, remove_pac=True, + expected_error=NT_STATUS_NO_IMPERSONATION_TOKEN) + + def _run_idmap_nss_test(self, user_creds, + use_kerberos, + remove_pac=False, + expected_error=None, + expected_first_sid=None, + expected_additional_sid=None, + expected_uid=None): + if expected_first_sid is not None: + self.assertIsNotNone(expected_uid) + if expected_additional_sid is not None: + self.assertIsNotNone(expected_uid) + if expected_uid is not None: + self.assertIsNone(expected_error) + + if not use_kerberos: + self.assertFalse(remove_pac) + + samdb = self.get_samdb() + + server_name = self.host + service = 'cifs' + share = 'tmp' + + server_creds = self.get_server_creds() + + if expected_first_sid is None: + # Retrieve the user account's SID. + user_name = user_creds.get_username() + res = samdb.search(scope=SCOPE_SUBTREE, + expression=f'(sAMAccountName={user_name})', + attrs=['objectSid']) + self.assertEqual(1, len(res)) + + expected_first_sid = ndr_unpack(security.dom_sid, + res[0].get('objectSid', idx=0)) + + if use_kerberos: + # Talk to the KDC to obtain the service ticket, which gets placed + # into the cache. The machine account name has to match the name in + # the ticket, to ensure that the krbtgt ticket doesn't also need to + # be stored. + creds, cachefile = self.create_ccache_with_user( + user_creds, + server_creds, + service, + server_name, + pac=not remove_pac) + + # Remove the cached creds file. + self.addCleanup(os.remove, cachefile.name) + + # Set the Kerberos 5 creds cache environment variable. This is + # required because the codepath that gets run (gse_krb5) looks for + # it in here and not in the creds object. + krb5_ccname = os.environ.get('KRB5CCNAME', '') + self.addCleanup(os.environ.__setitem__, 'KRB5CCNAME', krb5_ccname) + os.environ['KRB5CCNAME'] = 'FILE:' + cachefile.name + else: + creds = user_creds + creds.set_kerberos_state(DONT_USE_KERBEROS) + + # Connect to a share and retrieve the user SID. + s3_lp = s3param.get_context() + s3_lp.load(self.get_lp().configfile) + + min_protocol = s3_lp.get('client min protocol') + self.addCleanup(s3_lp.set, 'client min protocol', min_protocol) + s3_lp.set('client min protocol', 'NT1') + + max_protocol = s3_lp.get('client max protocol') + self.addCleanup(s3_lp.set, 'client max protocol', max_protocol) + s3_lp.set('client max protocol', 'NT1') + + try: + conn = libsmb.Conn(server_name, share, lp=s3_lp, creds=creds) + except NTSTATUSError as e: + enum, _ = e.args + self.assertEqual(expected_error, enum) + return + else: + self.assertIsNone(expected_error) + + uid, gid, gids, sids, guest = conn.posix_whoami() + + # Ensure that they match. + self.assertEqual(expected_first_sid, sids[0]) + self.assertNotIn(expected_first_sid, sids[1:-1]) + + if expected_additional_sid: + self.assertNotEqual(expected_additional_sid, sids[0]) + self.assertIn(expected_additional_sid, sids) + + self.assertIsNotNone(expected_uid) + self.assertEqual(expected_uid, uid) + + +if __name__ == '__main__': + global_asn1_print = False + global_hexdump = False + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 048bd1c3099..881383d6e39 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -107,6 +107,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/spn_tests.py', 'python/samba/tests/krb5/alias_tests.py', 'python/samba/tests/krb5/test_min_domain_uid.py', + 'python/samba/tests/krb5/test_idmap_nss.py', } EXCLUDE_HELP = { diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index 6caeb932e28..7ed10020aa1 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -579,7 +579,7 @@ sub get_interface($) lclnt4dc2smb1 => 55, fipsdc => 56, fipsadmember => 57, - admemnonsswb => 60, + admemidmapnss => 60, rootdnsforwarder => 64, diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 39327964569..e726b7a15df 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -238,7 +238,7 @@ sub check_env($$) ad_member_idmap_rid => ["ad_dc"], ad_member_idmap_ad => ["fl2008r2dc"], ad_member_fips => ["ad_dc_fips"], - ad_member_no_nss_wb => ["ad_dc"], + ad_member_idmap_nss => ["ad_dc"], clusteredmember_smb1 => ["nt4_dc"], ); @@ -1194,7 +1194,7 @@ sub setup_ad_member_fips 1); } -sub setup_ad_member_no_nss_wb +sub setup_ad_member_idmap_nss { my ($self, $prefix, @@ -1207,14 +1207,23 @@ sub setup_ad_member_no_nss_wb return "UNKNOWN"; } - print "PROVISIONING AD MEMBER WITHOUT NSS WINBIND..."; + print "PROVISIONING AD MEMBER WITHOUT NSS WINBIND WITH idmap_nss config..."; my $extra_member_options = " + # bob:x:65521:65531:localbob gecos:/:/bin/false + # jane:x:65520:65531:localjane gecos:/:/bin/false + idmap config $dcvars->{DOMAIN} : backend = nss + idmap config $dcvars->{DOMAIN} : range = 65520-65521 + + # Support SMB1 so that we can use posix_whoami(). + client min protocol = CORE + server min protocol = LANMAN1 + username map = $prefix/lib/username.map "; my $ret = $self->provision_ad_member($prefix, - "ADMEMNONSSWB", + "ADMEMIDMAPNSS", $dcvars, $trustvars_f, $trustvars_e, @@ -1225,6 +1234,7 @@ sub setup_ad_member_no_nss_wb open(USERMAP, ">$prefix/lib/username.map") or die("Unable to open $prefix/lib/username.map"); print USERMAP " root = $dcvars->{DOMAIN}/root +bob = $dcvars->{DOMAIN}/bob "; -- Samba Shared Repository