diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /source4/dsdb/tests/python/unicodepwd_encrypted.py | |
parent | Initial commit. (diff) | |
download | samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip |
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source4/dsdb/tests/python/unicodepwd_encrypted.py')
-rw-r--r-- | source4/dsdb/tests/python/unicodepwd_encrypted.py | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/source4/dsdb/tests/python/unicodepwd_encrypted.py b/source4/dsdb/tests/python/unicodepwd_encrypted.py new file mode 100644 index 0000000..768cbf8 --- /dev/null +++ b/source4/dsdb/tests/python/unicodepwd_encrypted.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import sys +import optparse + +sys.path.insert(0, "bin/python") +import samba.getopt as options +from ldb import Message, MessageElement, Dn +from ldb import LdbError, FLAG_MOD_REPLACE, ERR_UNWILLING_TO_PERFORM, SCOPE_BASE +from samba import gensec +from samba.auth import system_session +from samba.samdb import SamDB +from samba.tests import delete_force +from samba.tests.password_test import PasswordTestCase +from samba.tests.subunitrun import SubunitOptions, TestProgram + +parser = optparse.OptionParser("unicodepwd_encrypted.py [options] <host>") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +parser.add_option_group(options.VersionOptions(parser)) +# use command line creds if available +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +subunitopts = SubunitOptions(parser) +parser.add_option_group(subunitopts) +lp = sambaopts.get_loadparm() +opts, args = parser.parse_args() + +if len(args) < 1: + parser.print_usage() + sys.exit(1) + +host = args[0] +host_ldaps = f"ldaps://{host}" +host_ldap = f"ldap://{host}" + + +class UnicodePwdEncryptedConnectionTests(PasswordTestCase): + + def setUp(self): + super().setUp() + self.creds = self.insta_creds(template=credopts.get_credentials(lp)) + self.ldb = SamDB(host_ldap, credentials=self.creds, + session_info=system_session(lp), + lp=lp) + self.base_dn = self.ldb.domain_dn() + self.user_dn_str = f"cn=testuser,cn=users,{self.base_dn}" + self.user_dn = Dn(self.ldb, self.user_dn_str) + print(f"baseDN: {self.base_dn}\n") + + # permit password changes during this test + self.allow_password_changes() + + # (Re)adds the test user "testuser" with no password. + delete_force(self.ldb, str(self.user_dn)) + self.ldb.add({ + "dn": str(self.user_dn), + "objectclass": "user", + "sAMAccountName": "testuser" + }) + + # Set the test user initial password and enable account. + m = Message(self.user_dn) + m["0"] = MessageElement("Password#2", FLAG_MOD_REPLACE, "userPassword") + self.ldb.modify(m) + self.ldb.enable_account("(sAMAccountName=testuser)") + + def modify_unicode_pwd(self, ldb, password): + """Replaces user password using unicodePwd.""" + m = Message() + m.dn = self.user_dn + m["unicodePwd"] = MessageElement( + f'"{password}"'.encode('utf-16-le'), + FLAG_MOD_REPLACE, "unicodePwd" + ) + ldb.modify(m) + + def get_admin_sid(self, ldb): + res = self.ldb.search( + base="", expression="", scope=SCOPE_BASE, attrs=["tokenGroups"]) + + return self.ldb.schema_format_value( + "tokenGroups", res[0]["tokenGroups"][0]).decode("utf8") + + def test_with_seal(self): + """Test unicodePwd on connection with seal. + + This should allow unicodePwd. + """ + self.modify_unicode_pwd(self.ldb, "thatsAcomplPASS2") + + def test_without_seal(self): + """Test unicodePwd on connection without seal. + + Should not allow unicodePwd on an unencrypted connection. + + Requires --use-kerberos=required, or it automatically upgrades + to an encrypted connection. + """ + # Remove FEATURE_SEAL which gets added by insta_creds. + creds_noseal = self.insta_creds(template=credopts.get_credentials(lp)) + creds_noseal.set_gensec_features(creds_noseal.get_gensec_features() & + ~gensec.FEATURE_SEAL) + + sasl_wrap = lp.get('client ldap sasl wrapping') + self.addCleanup(lp.set, 'client ldap sasl wrapping', sasl_wrap) + lp.set('client ldap sasl wrapping', 'sign') + + # Create a second ldb connection without seal. + ldb = SamDB(host_ldap, credentials=creds_noseal, + session_info=system_session(lp), + lp=lp) + + with self.assertRaises(LdbError) as e: + self.modify_unicode_pwd(ldb, "thatsAcomplPASS2") + + # Server should not allow unicodePwd on an unencrypted connection. + self.assertEqual(e.exception.args[0], ERR_UNWILLING_TO_PERFORM) + self.assertIn( + "Password modification over LDAP must be over an encrypted connection", + e.exception.args[1] + ) + + def test_simple_bind_plain(self): + """Test unicodePwd using simple bind without encryption.""" + admin_sid = self.get_admin_sid(self.ldb) + + self.creds.set_bind_dn(admin_sid) + ldb = SamDB(url=host_ldap, credentials=self.creds, lp=lp) + + with self.assertRaises(LdbError) as e: + self.modify_unicode_pwd(ldb, "thatsAcomplPASS2") + + # Server should not allow unicodePwd on an unencrypted connection. + self.assertEqual(e.exception.args[0], ERR_UNWILLING_TO_PERFORM) + self.assertIn( + "Password modification over LDAP must be over an encrypted connection", + e.exception.args[1] + ) + + def test_simple_bind_tls(self): + """Test unicodePwd using simple bind with encryption.""" + admin_sid = self.get_admin_sid(self.ldb) + + self.creds.set_bind_dn(admin_sid) + ldb = SamDB(url=host_ldaps, credentials=self.creds, lp=lp) + + self.modify_unicode_pwd(ldb, "thatsAcomplPASS2") + + +TestProgram(module=__name__, opts=subunitopts) |