1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

tests password_hash: add tests for Primary:userPassword

Add tests to verify the generation and storage of sha256 and sha512
    password hashes in suplementalCredentials Primary:userPassword

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Gary Lockyer 2017-04-12 09:12:56 +12:00 committed by Andrew Bartlett
parent 79f027a610
commit de5299d155
5 changed files with 343 additions and 2 deletions

View File

@ -33,6 +33,7 @@ import ldb
import samba
import binascii
import md5
import crypt
USER_NAME = "PasswordHashTestUser"
@ -287,3 +288,36 @@ class PassWordHashTests(TestCase):
"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)

View File

@ -36,13 +36,14 @@ from samba.dcerpc import drsblobs
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()
@ -69,8 +70,50 @@ class PassWordHashFl2003Tests(PassWordHashTests):
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()
@ -95,6 +138,7 @@ class PassWordHashFl2003Tests(PassWordHashTests):
self.assertEquals(4, pos)
self.assertEquals("Primary:CLEARTEXT", ct_package.name)
# Check that the WDigest values are correct.
#
digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
@ -105,3 +149,53 @@ class PassWordHashFl2003Tests(PassWordHashTests):
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,
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}", "6",10000 )])
self.checkNtHash(USER_PASS, up.current_nt_hash.hash)

View File

@ -71,6 +71,50 @@ class PassWordHashFl2008Tests(PassWordHashTests):
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)
@ -110,3 +154,57 @@ class PassWordHashFl2008Tests(PassWordHashTests):
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)

View File

@ -124,3 +124,109 @@ class PassWordHashGpgmeTests(PassWordHashTests):
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)

View File

@ -330,3 +330,12 @@
# 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\)