import samba
import binascii
import md5
+import crypt
USER_NAME = "PasswordHashTestUser"
"Digest",
USER_PASS,
digests.hashes[28].hash)
+
+
+ def checkUserPassword(self, up, expected):
+
+ # Check we've received the correct number of hashes
+ self.assertEquals(len(expected), up.num_hashes)
+
+ i = 0
+ for (tag, alg, rounds) in expected:
+ self.assertEquals(tag, up.hashes[i].scheme)
+
+ data = up.hashes[i].value.split("$")
+ # Check we got the expected crypt algorithm
+ self.assertEquals(alg, data[1])
+
+ if rounds is None:
+ cmd = "$%s$%s" % (alg, data[2])
+ else:
+ cmd = "$%s$rounds=%d$%s" % (alg, rounds, data[3])
+
+ # Calculate the expected hash value
+ expected = crypt.crypt(USER_PASS, cmd)
+ self.assertEquals(expected, up.hashes[i].value)
+ i += 1
+
+ # Check that the correct nt_hash was stored for userPassword
+ def checkNtHash(self, password, nt_hash):
+ creds = Credentials()
+ creds.set_anonymous()
+ creds.set_password(password)
+ expected = creds.get_nt_hash()
+ actual = bytearray(nt_hash)
+ self.assertEquals(expected, actual)
import binascii
+
class PassWordHashFl2003Tests(PassWordHashTests):
def setUp(self):
super(PassWordHashFl2003Tests, self).setUp()
def test_default_supplementalCredentials(self):
- self.add_user()
+ self.add_user(options=[("password hash userPassword schemes", "")])
sc = self.get_supplemental_creds()
binascii.a2b_hex(package.data))
self.check_wdigests(digests)
+ def test_userPassword_sha256(self):
+ self.add_user(options=[("password hash userPassword schemes",
+ "CryptSHA256")])
+
+ sc = self.get_supplemental_creds()
+
+ # Check that we got all the expected supplemental credentials
+ # And they are in the expected order.
+ size = len(sc.sub.packages)
+ self.assertEquals(4, size)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos")
+ self.assertEquals(1, pos)
+ self.assertEquals("Primary:Kerberos", package.name)
+
+ (pos, wd_package) = get_package(sc, "Primary:WDigest")
+ self.assertEquals(2, pos)
+ self.assertEquals("Primary:WDigest", wd_package.name)
+
+ (pos, package) = get_package(sc, "Packages")
+ self.assertEquals(3, pos)
+ self.assertEquals("Packages", package.name)
+
+ (pos, up_package) = get_package(sc, "Primary:userPassword")
+ self.assertEquals(4, pos)
+ self.assertEquals("Primary:userPassword", up_package.name)
+
+ # Check that the WDigest values are correct.
+ #
+ digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
+ binascii.a2b_hex(wd_package.data))
+ self.check_wdigests(digests)
+
+ # Check that the userPassword hashes are computed correctly
+ #
+ up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob,
+ binascii.a2b_hex(up_package.data))
+
+ self.checkUserPassword(up, [("{CRYPT}", "5", None)])
+ self.checkNtHash(USER_PASS, up.current_nt_hash.hash)
+
def test_supplementalCredentials_cleartext(self):
- self.add_user(clear_text=True)
+ self.add_user(clear_text=True,
+ options=[("password hash userPassword schemes", "")])
sc = self.get_supplemental_creds()
self.assertEquals(4, pos)
self.assertEquals("Primary:CLEARTEXT", ct_package.name)
+
+ # Check that the WDigest values are correct.
+ #
+ digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
+ binascii.a2b_hex(wd_package.data))
+ self.check_wdigests(digests)
+
+ # Check the clear text value is correct.
+ ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob,
+ binascii.a2b_hex(ct_package.data))
+ self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext)
+
+ def test_userPassword_cleartext_sha512(self):
+ self.add_user(clear_text=True,
+ options=[("password hash userPassword schemes",
+ "CryptSHA512:rounds=10000")])
+
+ sc = self.get_supplemental_creds()
+
+ # Check that we got all the expected supplemental credentials
+ # And they are in the expected order.
+ size = len(sc.sub.packages)
+ self.assertEquals(5, size)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos")
+ self.assertEquals(1, pos)
+ self.assertEquals("Primary:Kerberos", package.name)
+
+ (pos, wd_package) = get_package(sc, "Primary:WDigest")
+ self.assertEquals(2, pos)
+ self.assertEquals("Primary:WDigest", wd_package.name)
+
+ (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT")
+ self.assertEquals(3, pos)
+ self.assertEquals("Primary:CLEARTEXT", ct_package.name)
+
+ (pos, package) = get_package(sc, "Packages")
+ self.assertEquals(4, pos)
+ self.assertEquals("Packages", package.name)
+
+ (pos, up_package) = get_package(sc, "Primary:userPassword")
+ self.assertEquals(5, pos)
+ self.assertEquals("Primary:userPassword", up_package.name)
+
# Check that the WDigest values are correct.
#
digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob,
binascii.a2b_hex(ct_package.data))
self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext)
+
+ # Check that the userPassword hashes are computed correctly
+ #
+ up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob,
+ binascii.a2b_hex(up_package.data))
+ self.checkUserPassword(up, [("{CRYPT}", "6",10000 )])
+ self.checkNtHash(USER_PASS, up.current_nt_hash.hash)
binascii.a2b_hex(package.data))
self.check_wdigests(digests)
+ def test_userPassword_sha512(self):
+ self.add_user(options=[("password hash userPassword schemes",
+ "CryptSHA512")])
+
+ sc = self.get_supplemental_creds()
+
+ # Check that we got all the expected supplemental credentials
+ # And they are in the expected order.
+ size = len(sc.sub.packages)
+ self.assertEquals(5, size)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys")
+ self.assertEquals(1, pos)
+ self.assertEquals("Primary:Kerberos-Newer-Keys", package.name)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos")
+ self.assertEquals(2, pos)
+ self.assertEquals("Primary:Kerberos", package.name)
+
+ (pos, wp_package) = get_package(sc, "Primary:WDigest")
+ self.assertEquals(3, pos)
+ self.assertEquals("Primary:WDigest", wp_package.name)
+
+ (pos, package) = get_package(sc, "Packages")
+ self.assertEquals(4, pos)
+ self.assertEquals("Packages", package.name)
+
+ (pos, up_package) = get_package(sc, "Primary:userPassword")
+ self.assertEquals(5, pos)
+ self.assertEquals("Primary:userPassword", up_package.name)
+
+ # Check that the WDigest values are correct.
+ #
+ digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
+ binascii.a2b_hex(wp_package.data))
+ self.check_wdigests(digests)
+
+ # Check that the userPassword hashes are computed correctly
+ #
+ up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob,
+ binascii.a2b_hex(up_package.data))
+ self.checkUserPassword(up, [("{CRYPT}", "6",None)])
+ self.checkNtHash(USER_PASS, up.current_nt_hash.hash)
+
def test_supplementalCredentials_cleartext(self):
self.add_user(clear_text=True)
ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob,
binascii.a2b_hex(ct_package.data))
self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext)
+
+ def test_userPassword_cleartext_sha256(self):
+ self.add_user(clear_text=True,
+ options=[("password hash userPassword schemes",
+ "CryptSHA256:rounds=100")])
+
+ sc = self.get_supplemental_creds()
+
+ # Check that we got all the expected supplemental credentials
+ # And they are in the expected order.
+ size = len(sc.sub.packages)
+ self.assertEquals(6, size)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys")
+ self.assertEquals(1, pos)
+ self.assertEquals("Primary:Kerberos-Newer-Keys", package.name)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos")
+ self.assertEquals(2, pos)
+ self.assertEquals("Primary:Kerberos", package.name)
+
+ (pos, wd_package) = get_package(sc, "Primary:WDigest")
+ self.assertEquals(3, pos)
+ self.assertEquals("Primary:WDigest", wd_package.name)
+
+ (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT")
+ self.assertEquals(4, pos)
+ self.assertEquals("Primary:CLEARTEXT", ct_package.name)
+
+ (pos, package) = get_package(sc, "Packages")
+ self.assertEquals(5, pos)
+ self.assertEquals("Packages", package.name)
+
+ (pos, up_package) = get_package(sc, "Primary:userPassword")
+ self.assertEquals(6, pos)
+ self.assertEquals("Primary:userPassword", up_package.name)
+
+ # Check that the WDigest values are correct.
+ #
+ digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
+ binascii.a2b_hex(wd_package.data))
+ self.check_wdigests(digests)
+
+ # Check the clear text value is correct.
+ ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob,
+ binascii.a2b_hex(ct_package.data))
+ self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext)
+
+ # Check that the userPassword hashes are computed correctly
+ #
+ up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob,
+ binascii.a2b_hex(up_package.data))
+ self.checkUserPassword(up, [("{CRYPT}", "5",100 )])
+ self.checkNtHash(USER_PASS, up.current_nt_hash.hash)
ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob,
binascii.a2b_hex(ct_package.data))
self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext)
+
+ def test_userPassword_multiple_hashes(self):
+ self.add_user(options=[(
+ "password hash userPassword schemes",
+ "CryptSHA512 CryptSHA256 CryptSHA512")])
+
+ sc = self.get_supplemental_creds()
+
+ # Check that we got all the expected supplemental credentials
+ # And they are in the expected order.
+ size = len(sc.sub.packages)
+ self.assertEquals(6, size)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys")
+ self.assertEquals(1, pos)
+ self.assertEquals("Primary:Kerberos-Newer-Keys", package.name)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos")
+ self.assertEquals(2, pos)
+ self.assertEquals("Primary:Kerberos", package.name)
+
+ (pos, wp_package) = get_package(sc, "Primary:WDigest")
+ self.assertEquals(3, pos)
+ self.assertEquals("Primary:WDigest", wp_package.name)
+
+ (pos, up_package) = get_package(sc, "Primary:userPassword")
+ self.assertEquals(4, pos)
+ self.assertEquals("Primary:userPassword", up_package.name)
+
+ (pos, package) = get_package(sc, "Packages")
+ self.assertEquals(5, pos)
+ self.assertEquals("Packages", package.name)
+
+ (pos, package) = get_package(sc, "Primary:SambaGPG")
+ self.assertEquals(6, pos)
+ self.assertEquals("Primary:SambaGPG", package.name)
+
+ # Check that the WDigest values are correct.
+ #
+ digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
+ binascii.a2b_hex(wp_package.data))
+ self.check_wdigests(digests)
+
+ # Check that the userPassword hashes are computed correctly
+ # Expect three hashes to be calculated
+ up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob,
+ binascii.a2b_hex(up_package.data))
+ self.checkUserPassword(up, [
+ ("{CRYPT}", "6", None),
+ ("{CRYPT}", "5", None),
+ ("{CRYPT}", "6", None)
+ ])
+ self.checkNtHash(USER_PASS, up.current_nt_hash.hash)
+
+ def test_userPassword_multiple_hashes_rounds_specified(self):
+ self.add_user(options=[(
+ "password hash userPassword schemes",
+ "CryptSHA512:rounds=5120 CryptSHA256:rounds=2560 CryptSHA512:rounds=5122")])
+
+ sc = self.get_supplemental_creds()
+
+ # Check that we got all the expected supplemental credentials
+ # And they are in the expected order.
+ size = len(sc.sub.packages)
+ self.assertEquals(6, size)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys")
+ self.assertEquals(1, pos)
+ self.assertEquals("Primary:Kerberos-Newer-Keys", package.name)
+
+ (pos, package) = get_package(sc, "Primary:Kerberos")
+ self.assertEquals(2, pos)
+ self.assertEquals("Primary:Kerberos", package.name)
+
+ (pos, wp_package) = get_package(sc, "Primary:WDigest")
+ self.assertEquals(3, pos)
+ self.assertEquals("Primary:WDigest", wp_package.name)
+
+ (pos, up_package) = get_package(sc, "Primary:userPassword")
+ self.assertEquals(4, pos)
+ self.assertEquals("Primary:userPassword", up_package.name)
+
+ (pos, package) = get_package(sc, "Packages")
+ self.assertEquals(5, pos)
+ self.assertEquals("Packages", package.name)
+
+ (pos, package) = get_package(sc, "Primary:SambaGPG")
+ self.assertEquals(6, pos)
+ self.assertEquals("Primary:SambaGPG", package.name)
+
+ # Check that the WDigest values are correct.
+ #
+ digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
+ binascii.a2b_hex(wp_package.data))
+ self.check_wdigests(digests)
+
+ # Check that the userPassword hashes are computed correctly
+ # Expect three hashes to be calculated
+ up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob,
+ binascii.a2b_hex(up_package.data))
+ self.checkUserPassword(up, [
+ ("{CRYPT}", "6", 5120),
+ ("{CRYPT}", "5", 2560),
+ ("{CRYPT}", "6", 5122)
+ ])
+ self.checkNtHash(USER_PASS, up.current_nt_hash.hash)
# We currently don't send referrals for LDAP modify of non-replicated attrs
^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.*
^samba4.ldap.rodc_rwdc.python.*.__main__.RodcRwdcTests.test_change_password_reveal_on_demand_kerberos
+# Tests for password hash supplemental credentials, userPassword hashes
+# Will fail as the implementation has not been written
+#
+^samba.tests.password_hash_gpgme.samba.tests.password_hash_gpgme.PassWordHashGpgmeTests.test_userPassword_multiple_hashes\(ad_dc:local\)
+^samba.tests.password_hash_gpgme.samba.tests.password_hash_gpgme.PassWordHashGpgmeTests.test_userPassword_multiple_hashes_rounds_specified\(ad_dc:local\)
+^samba.tests.password_hash_fl2008.samba.tests.password_hash_fl2008.PassWordHashFl2008Tests.test_userPassword_cleartext_sha256\(ad_dc_ntvfs:local\)
+^samba.tests.password_hash_fl2008.samba.tests.password_hash_fl2008.PassWordHashFl2008Tests.test_userPassword_sha512\(ad_dc_ntvfs:local\)
+^samba.tests.password_hash_fl2003.samba.tests.password_hash_fl2003.PassWordHashFl2003Tests.test_userPassword_cleartext_sha512\(fl2003dc:local\)
+^samba.tests.password_hash_fl2003.samba.tests.password_hash_fl2003.PassWordHashFl2003Tests.test_userPassword_sha256\(fl2003dc:local\)