From 823dec9d166b3fbe2caacdb699173601603c1101 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Mon, 7 May 2018 17:33:51 +1200 Subject: [PATCH] tests: Add a test case for msDS-PasswordReversibleEncryptionEnabled Add a test for the 'msDS-PasswordReversibleEncryptionEnabled' attribute on the PSO. The Effective-PasswordReversibleEncryptionEnabled is based on the PSO setting (if one applies) or else the DOMAIN_PASSWORD_STORE_CLEARTEXT bit for the domain's pwdProperties. This indicates whether the user's cleartext password is to be stored in the supplementalCredentials attribute (as 'Primary:CLEARTEXT'). The password_hash tests already text the cleartext behaviour, so I've added an additional test case for PSOs. Note that supplementary- credential information is not returned over LDAP (the password_hash test uses a local LDB connection), so it made more sense to extend the password_hash tests than to check this behaviour as part of the PSO tests (i.e. rather than in password_settings.py). Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam Signed-off-by: Tim Beale --- python/samba/tests/password_hash.py | 20 +++++-- python/samba/tests/password_hash_gpgme.py | 67 ++++++++++++++++++++++- selftest/knownfail.d/password_hash_gpgme | 2 + 3 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 selftest/knownfail.d/password_hash_gpgme diff --git a/python/samba/tests/password_hash.py b/python/samba/tests/password_hash.py index 0a295d57c0d..4c4dbcf2fd7 100644 --- a/python/samba/tests/password_hash.py +++ b/python/samba/tests/password_hash.py @@ -70,6 +70,17 @@ class PassWordHashTests(TestCase): self.lp = samba.tests.env_loadparm() super(PassWordHashTests, self).setUp() + def set_store_cleartext(self, cleartext): + # get the current pwdProperties + pwdProperties = self.ldb.get_pwdProperties() + # update the clear-text properties flag + props = int(pwdProperties) + if cleartext: + props |= DOMAIN_PASSWORD_STORE_CLEARTEXT + else: + props &= ~DOMAIN_PASSWORD_STORE_CLEARTEXT + self.ldb.set_pwdProperties(str(props)) + # Add a user to ldb, this will exercise the password_hash code # and calculate the appropriate supplemental credentials def add_user(self, options=None, clear_text=False, ldb=None): @@ -109,14 +120,11 @@ class PassWordHashTests(TestCase): account_control = 0 if clear_text: - # get the current pwdProperties + # Restore the current domain setting on exit. pwdProperties = self.ldb.get_pwdProperties() - # enable clear text properties - props = int(pwdProperties) - props |= DOMAIN_PASSWORD_STORE_CLEARTEXT - self.ldb.set_pwdProperties(str(props)) - # Restore the value on exit. self.addCleanup(self.ldb.set_pwdProperties, pwdProperties) + # Update the domain setting + self.set_store_cleartext(clear_text) account_control |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED # (Re)adds the test user USER_NAME with password USER_PASS diff --git a/python/samba/tests/password_hash_gpgme.py b/python/samba/tests/password_hash_gpgme.py index 25a8a0c7916..6dafaa81aca 100644 --- a/python/samba/tests/password_hash_gpgme.py +++ b/python/samba/tests/password_hash_gpgme.py @@ -28,12 +28,14 @@ kerberos newer keys are generated. from samba.tests.password_hash import ( PassWordHashTests, get_package, - USER_PASS + USER_PASS, + USER_NAME ) from samba.ndr import ndr_unpack from samba.dcerpc import drsblobs import binascii - +from samba.tests.pso import PasswordSettings +import samba class PassWordHashGpgmeTests(PassWordHashTests): @@ -125,6 +127,67 @@ class PassWordHashGpgmeTests(PassWordHashTests): binascii.a2b_hex(ct_package.data)) self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext) + def assert_cleartext(self, expect_cleartext, password=None): + """Checks cleartext is (or isn't) returned as expected""" + sc = self.get_supplemental_creds() + if expect_cleartext: + (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT") + self.assertTrue(ct_package != None, "Failed to retrieve cleartext") + + # Check the clear-text value is correct. + ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob, + binascii.a2b_hex(ct_package.data)) + self.assertEquals(password.encode('utf-16-le'), ct.cleartext) + else: + ct_package = get_package(sc, "Primary:CLEARTEXT") + self.assertTrue(ct_package == None, + "Got cleartext when we shouldn't have") + + def test_supplementalCredentials_cleartext_pso(self): + """Checks that a PSO's cleartext setting can override the domain's""" + + # create a user that stores plain-text passwords + self.add_user(clear_text=True) + + # check that clear-text is present in the supplementary-credentials + self.assert_cleartext(expect_cleartext=True, password=USER_PASS) + + # create a PSO overriding the plain-text setting & apply it to the user + no_plaintext_pso = PasswordSettings("no-plaintext-PSO", self.ldb, + precedence=200, + store_plaintext=False) + self.addCleanup(self.ldb.delete, no_plaintext_pso.dn) + userdn = "cn=" + USER_NAME + ",cn=users," + self.base_dn + no_plaintext_pso.apply_to(userdn) + + # set the password to update the cleartext password stored + new_password = samba.generate_random_password(32, 32) + self.ldb.setpassword("(sAMAccountName=%s)" % USER_NAME, new_password) + + # this time cleartext shouldn't be in the supplementary creds + self.assert_cleartext(expect_cleartext=False) + + # unapply PSO, update password, and check we get the cleartext again + no_plaintext_pso.unapply(userdn) + new_password = samba.generate_random_password(32, 32) + self.ldb.setpassword("(sAMAccountName=%s)" % USER_NAME, new_password) + self.assert_cleartext(expect_cleartext=True, password=new_password) + + # Now update the domain setting and check we no longer get cleartext + self.set_store_cleartext(False) + new_password = samba.generate_random_password(32, 32) + self.ldb.setpassword("(sAMAccountName=%s)" % USER_NAME, new_password) + self.assert_cleartext(expect_cleartext=False) + + # create a PSO overriding the domain setting & apply it to the user + plaintext_pso = PasswordSettings("plaintext-PSO", self.ldb, + precedence=100, store_plaintext=True) + self.addCleanup(self.ldb.delete, plaintext_pso.dn) + plaintext_pso.apply_to(userdn) + new_password = samba.generate_random_password(32, 32) + self.ldb.setpassword("(sAMAccountName=%s)" % USER_NAME, new_password) + self.assert_cleartext(expect_cleartext=True, password=new_password) + def test_userPassword_multiple_hashes(self): self.add_user(options=[( "password hash userPassword schemes", diff --git a/selftest/knownfail.d/password_hash_gpgme b/selftest/knownfail.d/password_hash_gpgme new file mode 100644 index 00000000000..a382714e5a8 --- /dev/null +++ b/selftest/knownfail.d/password_hash_gpgme @@ -0,0 +1,2 @@ +samba.tests.password_hash_gpgme.samba.tests.password_hash_gpgme.PassWordHashGpgmeTests.test_supplementalCredentials_cleartext_pso\(ad_dc:local\) +