from samba.dcerpc.samr import DOMAIN_PASSWORD_STORE_CLEARTEXT
from samba.dsdb import UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
from samba.tests import delete_force
+from samba.tests.password_test import PasswordCommon
import ldb
import samba
import binascii
-import md5
+from hashlib import md5
import crypt
+from samba.compat import text_type
USER_NAME = "PasswordHashTestUser"
# Get named package from the passed supplemental credentials
#
# returns the package and it's position within the supplemental credentials
+
+
def get_package(sc, name):
if sc is None:
return None
# Calculate the MD5 password digest from the supplied user, realm and password
#
+
+
def calc_digest(user, realm, password):
data = "%s:%s:%s" % (user, realm, password)
- return binascii.hexlify(md5.new(data).digest())
+ if isinstance(data, text_type):
+ data = data.encode('utf8')
+
+ return md5(data).hexdigest()
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):
res = self.ldb.search(base=self.ldb.get_config_basedn(),
expression="ncName=%s" % self.ldb.get_default_basedn(),
attrs=["nETBIOSName"])
- self.netbios_domain = res[0]["nETBIOSName"][0]
+ self.netbios_domain = str(res[0]["nETBIOSName"][0])
self.dns_domain = self.ldb.domain_dns_name()
-
# Gets back the basedn
base_dn = self.ldb.domain_dn()
# Gets back the configuration basedn
configuration_dn = self.ldb.get_config_basedn().get_linearized()
- # Get the old "dSHeuristics" if it was set
- dsheuristics = self.ldb.get_dsheuristics()
-
- # Set the "dSHeuristics" to activate the correct "userPassword"
- # behaviour
- self.ldb.set_dsheuristics("000000001")
-
- # Reset the "dSHeuristics" as they were before
- self.addCleanup(self.ldb.set_dsheuristics, dsheuristics)
+ # permit password changes during this test
+ PasswordCommon.allow_password_changes(self, self.ldb)
- # Get the old "minPwdAge"
- minPwdAge = self.ldb.get_minPwdAge()
-
- # Set it temporarily to "0"
- self.ldb.set_minPwdAge("0")
self.base_dn = self.ldb.domain_dn()
- # Reset the "minPwdAge" as it was before
- self.addCleanup(self.ldb.set_minPwdAge, minPwdAge)
-
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
return sc
# Calculate and validate a Wdigest value
- def check_digest(self, user, realm, password, digest):
+ def check_digest(self, user, realm, password, digest):
expected = calc_digest(user, realm, password)
- actual = binascii.hexlify(bytearray(digest))
+ actual = binascii.hexlify(bytearray(digest)).decode('utf8')
error = "Digest expected[%s], actual[%s], " \
"user[%s], realm[%s], pass[%s]" % \
(expected, actual, user, realm, password)
self.check_digest(USER_NAME,
self.netbios_domain,
USER_PASS,
- digests.hashes[1-1].hash)
+ digests.hashes[1 - 1].hash)
self.check_digest(USER_NAME.lower(),
self.netbios_domain.lower(),
USER_PASS,
- digests.hashes[2-1].hash)
+ digests.hashes[2 - 1].hash)
self.check_digest(USER_NAME.upper(),
self.netbios_domain.upper(),
USER_PASS,
- digests.hashes[3-1].hash)
+ digests.hashes[3 - 1].hash)
self.check_digest(USER_NAME,
self.netbios_domain.upper(),
USER_PASS,
- digests.hashes[4-1].hash)
+ digests.hashes[4 - 1].hash)
self.check_digest(USER_NAME,
self.netbios_domain.lower(),
USER_PASS,
- digests.hashes[5-1].hash)
+ digests.hashes[5 - 1].hash)
self.check_digest(USER_NAME.upper(),
self.netbios_domain.lower(),
USER_PASS,
- digests.hashes[6-1].hash)
+ digests.hashes[6 - 1].hash)
self.check_digest(USER_NAME.lower(),
self.netbios_domain.upper(),
USER_PASS,
- digests.hashes[7-1].hash)
+ digests.hashes[7 - 1].hash)
self.check_digest(USER_NAME,
self.dns_domain,
USER_PASS,
- digests.hashes[8-1].hash)
+ digests.hashes[8 - 1].hash)
self.check_digest(USER_NAME.lower(),
self.dns_domain.lower(),
USER_PASS,
- digests.hashes[9-1].hash)
+ digests.hashes[9 - 1].hash)
self.check_digest(USER_NAME.upper(),
self.dns_domain.upper(),
USER_PASS,
- digests.hashes[10-1].hash)
+ digests.hashes[10 - 1].hash)
self.check_digest(USER_NAME,
self.dns_domain.upper(),
USER_PASS,
- digests.hashes[11-1].hash)
+ digests.hashes[11 - 1].hash)
self.check_digest(USER_NAME,
self.dns_domain.lower(),
USER_PASS,
- digests.hashes[12-1].hash)
+ digests.hashes[12 - 1].hash)
self.check_digest(USER_NAME.upper(),
self.dns_domain.lower(),
USER_PASS,
- digests.hashes[13-1].hash)
+ digests.hashes[13 - 1].hash)
self.check_digest(USER_NAME.lower(),
self.dns_domain.upper(),
USER_PASS,
- digests.hashes[14-1].hash)
+ digests.hashes[14 - 1].hash)
self.check_digest(UPN,
"",
USER_PASS,
- digests.hashes[15-1].hash)
+ digests.hashes[15 - 1].hash)
self.check_digest(UPN.lower(),
"",
USER_PASS,
- digests.hashes[16-1].hash)
+ digests.hashes[16 - 1].hash)
self.check_digest(UPN.upper(),
"",
USER_PASS,
- digests.hashes[17-1].hash)
+ digests.hashes[17 - 1].hash)
name = "%s\\%s" % (self.netbios_domain, USER_NAME)
self.check_digest(name,
"",
USER_PASS,
- digests.hashes[18-1].hash)
+ digests.hashes[18 - 1].hash)
name = "%s\\%s" % (self.netbios_domain.lower(), USER_NAME.lower())
self.check_digest(name,
"",
USER_PASS,
- digests.hashes[19-1].hash)
+ digests.hashes[19 - 1].hash)
name = "%s\\%s" % (self.netbios_domain.upper(), USER_NAME.upper())
self.check_digest(name,
"",
USER_PASS,
- digests.hashes[20-1].hash)
+ digests.hashes[20 - 1].hash)
self.check_digest(USER_NAME,
"Digest",
USER_PASS,
- digests.hashes[21-1].hash)
+ digests.hashes[21 - 1].hash)
self.check_digest(USER_NAME.lower(),
"Digest",
USER_PASS,
- digests.hashes[22-1].hash)
+ digests.hashes[22 - 1].hash)
self.check_digest(USER_NAME.upper(),
"Digest",
USER_PASS,
- digests.hashes[23-1].hash)
+ digests.hashes[23 - 1].hash)
self.check_digest(UPN,
"Digest",
USER_PASS,
- digests.hashes[24-1].hash)
+ digests.hashes[24 - 1].hash)
self.check_digest(UPN.lower(),
"Digest",
USER_PASS,
- digests.hashes[25-1].hash)
+ digests.hashes[25 - 1].hash)
self.check_digest(UPN.upper(),
"Digest",
USER_PASS,
- digests.hashes[26-1].hash)
+ digests.hashes[26 - 1].hash)
name = "%s\\%s" % (self.netbios_domain, USER_NAME)
self.check_digest(name,
"Digest",
USER_PASS,
- digests.hashes[27-1].hash)
+ digests.hashes[27 - 1].hash)
name = "%s\\%s" % (self.netbios_domain.lower(), USER_NAME.lower())
self.check_digest(name,
"Digest",
USER_PASS,
- digests.hashes[28-1].hash)
+ digests.hashes[28 - 1].hash)
name = "%s\\%s" % (self.netbios_domain.upper(), USER_NAME.upper())
self.check_digest(name,
"Digest",
USER_PASS,
- digests.hashes[29-1].hash)
+ digests.hashes[29 - 1].hash)
def checkUserPassword(self, up, expected):
for (tag, alg, rounds) in expected:
self.assertEquals(tag, up.hashes[i].scheme)
- data = up.hashes[i].value.split("$")
+ data = up.hashes[i].value.decode('utf8').split("$")
# Check we got the expected crypt algorithm
self.assertEquals(alg, data[1])
# Calculate the expected hash value
expected = crypt.crypt(USER_PASS, cmd)
- self.assertEquals(expected, up.hashes[i].value)
+ self.assertEquals(expected, up.hashes[i].value.decode('utf8'))
i += 1
# Check that the correct nt_hash was stored for userPassword