samba-tool tests: add tests for userPassword
authorGary Lockyer <gary@catalyst.net.nz>
Mon, 15 May 2017 00:20:58 +0000 (12:20 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 25 May 2017 00:25:12 +0000 (02:25 +0200)
Tests to ensure that precomputed SHA256 and SHA512 hashes in
'supplementalCredentials Primary:userPassword' are used correctly in the
calculation of virtualCryptSHA256 and virtualCryptSHA512

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/tests/samba_tool/user_virtualCryptSHA.py
selftest/knownfail

index d19c534eb07de0d6a30063ab651560e46d5b28e9..31c681dcfba7856331c7d4f4a445df7b0378c635 100644 (file)
@@ -34,6 +34,7 @@ import re
 
 USER_NAME = "CyyptSHATestUser"
 USER_PASS = samba.generate_random_password(32,32)
+HASH_OPTION = "password hash userPassword schemes"
 
 # Get the value of an attribute from the output string
 # Note: Does not correctly handle values spanning multiple lines,
@@ -57,12 +58,11 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
     def setUp(self):
         super(UserCmdCryptShaTestCase, self).setUp()
 
-    def add_user(self, options = None):
+    def add_user(self, hashes = ""):
         self.lp = samba.tests.env_loadparm()
-        # set any needed options
-        if options is not None:
-            for (option,value) in options:
-                self.lp.set(option, value)
+
+        # set the extra hashes to be calculated
+        self.lp.set(HASH_OPTION, hashes)
 
         self.creds = Credentials()
         self.session = system_session()
@@ -118,6 +118,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption not enabled.
     # both virtual attributes specified, no rounds option
+    # no hashes stored in supplementalCredentials
     # Should not get values
     def test_no_gpg_both_hashes_no_rounds(self):
         self.add_user()
@@ -129,6 +130,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption not enabled.
     # SHA256 specified
+    # no hashes stored in supplementalCredentials
     # No rounds
     #
     # Should not get values
@@ -142,6 +144,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption not enabled.
     # SHA512 specified
+    # no hashes stored in supplementalCredentials
     # No rounds
     #
     # Should not get values
@@ -155,6 +158,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption not enabled.
     # SHA128 specified, i.e. invalid/unknown algorithm
+    # no hashes stored in supplementalCredentials
     # No rounds
     #
     # Should not get values
@@ -168,6 +172,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption enabled.
     # both virtual attributes specified, no rounds option
+    # no hashes stored in supplementalCredentials
     # Should get values
     def test_gpg_both_hashes_no_rounds(self):
         self.add_user()
@@ -179,6 +184,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption enabled.
     # SHA256 specified
+    # no hashes stored in supplementalCredentials
     # No rounds
     #
     # Should get values
@@ -192,6 +198,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption enabled.
     # SHA512 specified
+    # no hashes stored in supplementalCredentials
     # No rounds
     #
     # Should get values
@@ -205,6 +212,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption enabled.
     # SHA128 specified, i.e. invalid/unknown algorithm
+    # no hashes stored in supplementalCredentials
     # No rounds
     #
     # Should not get values
@@ -218,6 +226,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption enabled.
     # both virtual attributes specified, no rounds option
+    # no hashes stored in supplementalCredentials
     # underlying windows password changed, so plain text password is
     # invalid.
     # Should not get values
@@ -232,6 +241,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption enabled.
     # SHA256 specified, no rounds option
+    # no hashes stored in supplementalCredentials
     # underlying windows password changed, so plain text password is
     # invalid.
     # Should not get values
@@ -246,6 +256,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption enabled.
     # SHA512 specified, no rounds option
+    # no hashes stored in supplementalCredentials
     # underlying windows password changed, so plain text password is
     # invalid.
     # Should not get values
@@ -260,6 +271,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
     # gpg decryption enabled.
     # both virtual attributes specified, rounds specified
+    # no hashes stored in supplementalCredentials
     # Should get values reflecting the requested rounds
     def test_gpg_both_hashes_both_rounds(self):
         self.add_user()
@@ -279,6 +291,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
     # gpg decryption enabled.
     # both virtual attributes specified, rounds specified
     # invalid rounds for sha256
+    # no hashes stored in supplementalCredentials
     # Should get values, no rounds for sha256, rounds for sha 512
     def test_gpg_both_hashes_sha256_rounds_invalid(self):
         self.add_user()
@@ -295,3 +308,233 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
 
         sha512 = _get_attribute(out, "virtualCryptSHA512")
         self.assertTrue(sha512.startswith("{CRYPT}$6$rounds=3125$"))
+
+    # gpg decryption not enabled.
+    # both virtual attributes specified, no rounds option
+    # both hashes stored in supplementalCredentials
+    # Should get values
+    def test_no_gpg_both_hashes_no_rounds_stored_hashes(self):
+        self.add_user("CryptSHA512 CryptSHA256")
+
+        out = self._get_password("virtualCryptSHA256,virtualCryptSHA512")
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" not in out)
+
+        # Should be using the pre computed hash in supplementalCredentials
+        # so it should not change between calls.
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+
+        out = self._get_password("virtualCryptSHA256,virtualCryptSHA512")
+        self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256"))
+        self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512"))
+
+    # gpg decryption not enabled.
+    # both virtual attributes specified, rounds specified
+    # both hashes stored in supplementalCredentials, with not rounds
+    # Should get hashes for the first matching scheme entry
+    def test_no_gpg_both_hashes_rounds_stored_hashes(self):
+        self.add_user("CryptSHA512 CryptSHA256")
+
+        out = self._get_password("virtualCryptSHA256;rounds=2561," +
+                                 "virtualCryptSHA512;rounds=5129")
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" not in out)
+
+        # Should be using the pre computed hash in supplementalCredentials
+        # so it should not change between calls.
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+
+        out = self._get_password("virtualCryptSHA256,virtualCryptSHA512")
+        self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256"))
+        self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512"))
+
+    # gpg decryption not enabled.
+    # both virtual attributes specified, rounds specified
+    # both hashes stored in supplementalCredentials, with rounds
+    # Should get values
+    def test_no_gpg_both_hashes_rounds_stored_hashes_with_rounds(self):
+        self.add_user("CryptSHA512 " +
+                      "CryptSHA256 " +
+                      "CryptSHA512:rounds=5129 " +
+                      "CryptSHA256:rounds=2561")
+
+        out = self._get_password("virtualCryptSHA256;rounds=2561," +
+                                 "virtualCryptSHA512;rounds=5129")
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" in out)
+
+        # Should be using the pre computed hash in supplementalCredentials
+        # so it should not change between calls.
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+
+        out = self._get_password("virtualCryptSHA256;rounds=2561," +
+                                 "virtualCryptSHA512;rounds=5129")
+        self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256"))
+        self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512"))
+
+        # Number of rounds should match that specified
+        self.assertTrue(sha256.startswith("{CRYPT}$5$rounds=2561"))
+        self.assertTrue(sha512.startswith("{CRYPT}$6$rounds=5129"))
+
+    # gpg decryption not enabled.
+    # both virtual attributes specified, rounds specified
+    # both hashes stored in supplementalCredentials, with rounds
+    # number of rounds stored/requested do not match
+    # Should get the precomputed hashes for CryptSHA512 and CryptSHA256
+    def test_no_gpg_both_hashes_rounds_stored_hashes_with_rounds_no_match(self):
+        self.add_user("CryptSHA512 " +
+                      "CryptSHA256 " +
+                      "CryptSHA512:rounds=5129 " +
+                      "CryptSHA256:rounds=2561")
+
+        out = self._get_password("virtualCryptSHA256;rounds=4000," +
+                                 "virtualCryptSHA512;rounds=5000")
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" not in out)
+
+        # Should be using the pre computed hash in supplementalCredentials
+        # so it should not change between calls.
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+
+        out = self._get_password("virtualCryptSHA256;rounds=4000," +
+                                 "virtualCryptSHA512;rounds=5000")
+        self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256"))
+        self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512"))
+
+        # As the number of rounds did not match, should have returned the
+        # first hash of the coresponding scheme
+        out = self._get_password("virtualCryptSHA256," +
+                                 "virtualCryptSHA512")
+        self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256"))
+        self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512"))
+
+    # gpg decryption enabled.
+    # both virtual attributes specified, no rounds option
+    # both hashes stored in supplementalCredentials
+    # Should get values
+    def test_gpg_both_hashes_no_rounds_stored_hashes(self):
+        self.add_user("CryptSHA512 CryptSHA256")
+
+        out = self._get_password("virtualCryptSHA256,virtualCryptSHA512", True)
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" not in out)
+
+        # Should be using the pre computed hash in supplementalCredentials
+        # so it should not change between calls.
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+
+        out = self._get_password("virtualCryptSHA256,virtualCryptSHA512", True)
+        self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256"))
+        self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512"))
+
+    # gpg decryption enabled.
+    # both virtual attributes specified, rounds specified
+    # both hashes stored in supplementalCredentials, with no rounds
+    # Should get calculated hashed with the correct number of rounds
+    def test_gpg_both_hashes_rounds_stored_hashes(self):
+        self.add_user("CryptSHA512 CryptSHA256")
+
+        out = self._get_password("virtualCryptSHA256;rounds=2561," +
+                                 "virtualCryptSHA512;rounds=5129",
+                                 True)
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" in out)
+
+        # Should be calculating the hashes
+        # so they should change between calls.
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+
+        out = self._get_password("virtualCryptSHA256;rounds=2561," +
+                                 "virtualCryptSHA512;rounds=5129",
+                                 True)
+        self.assertFalse(sha256 == _get_attribute(out, "virtualCryptSHA256"))
+        self.assertFalse(sha512 ==_get_attribute(out, "virtualCryptSHA512"))
+
+        # The returned hashes should specify the correct number of rounds
+        self.assertTrue(sha256.startswith("{CRYPT}$5$rounds=2561"))
+        self.assertTrue(sha512.startswith("{CRYPT}$6$rounds=5129"))
+
+    # gpg decryption enabled.
+    # both virtual attributes specified, rounds specified
+    # both hashes stored in supplementalCredentials, with rounds
+    # Should get values
+    def test_gpg_both_hashes_rounds_stored_hashes_with_rounds(self):
+        self.add_user("CryptSHA512 " +
+                      "CryptSHA256 " +
+                      "CryptSHA512:rounds=5129 " +
+                      "CryptSHA256:rounds=2561")
+
+        out = self._get_password("virtualCryptSHA256;rounds=2561," +
+                                 "virtualCryptSHA512;rounds=5129",
+                                 True)
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" in out)
+
+        # Should be using the pre computed hash in supplementalCredentials
+        # so it should not change between calls.
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+
+        out = self._get_password("virtualCryptSHA256;rounds=2561," +
+                                 "virtualCryptSHA512;rounds=5129",
+                                 True)
+        self.assertEquals(sha256, _get_attribute(out, "virtualCryptSHA256"))
+        self.assertEquals(sha512, _get_attribute(out, "virtualCryptSHA512"))
+
+        # The returned hashes should specify the correct number of rounds
+        self.assertTrue(sha256.startswith("{CRYPT}$5$rounds=2561"))
+        self.assertTrue(sha512.startswith("{CRYPT}$6$rounds=5129"))
+
+    # gpg decryption enabled.
+    # both virtual attributes specified, rounds specified
+    # both hashes stored in supplementalCredentials, with rounds
+    # number of rounds stored/requested do not match
+    # Should get calculated hashes with the correct number of rounds
+    def test_gpg_both_hashes_rounds_stored_hashes_with_rounds_no_match(self):
+        self.add_user("CryptSHA512 " +
+                      "CryptSHA256 " +
+                      "CryptSHA512:rounds=5129 " +
+                      "CryptSHA256:rounds=2561")
+
+        out = self._get_password("virtualCryptSHA256;rounds=4000," +
+                                 "virtualCryptSHA512;rounds=5000",
+                                 True)
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" in out)
+
+        # Should be calculating the hashes
+        # so they should change between calls.
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+
+        out = self._get_password("virtualCryptSHA256;rounds=4000," +
+                                 "virtualCryptSHA512;rounds=5000",
+                                 True)
+        self.assertFalse(sha256 == _get_attribute(out, "virtualCryptSHA256"))
+        self.assertFalse(sha512 == _get_attribute(out, "virtualCryptSHA512"))
+
+        # The calculated hashes should specify the correct number of rounds
+        self.assertTrue(sha256.startswith("{CRYPT}$5$rounds=4000"))
+        self.assertTrue(sha512.startswith("{CRYPT}$6$rounds=5000"))
index b16ff520e4274f693f690e306d4645f8d9f5a62c..6eb7d0fc48797cb9e8d9d9b8cc625c02a75c6983 100644 (file)
 # 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 samba-tool user command extracting CRYPT hashes from supplememtal
+# credetials, will fail until code implemented
+^samba.tests.samba_tool.user_virtualCryptSHA.samba.tests.samba_tool.user_virtualCryptSHA.UserCmdCryptShaTestCase.test_no_gpg_both_hashes_rounds_stored_hashes_with_rounds_no_match\(ad_dc:local\)
+^samba.tests.samba_tool.user_virtualCryptSHA.samba.tests.samba_tool.user_virtualCryptSHA.UserCmdCryptShaTestCase.test_no_gpg_both_hashes_rounds_stored_hashes\(ad_dc:local\)
+^samba.tests.samba_tool.user_virtualCryptSHA.samba.tests.samba_tool.user_virtualCryptSHA.UserCmdCryptShaTestCase.test_no_gpg_both_hashes_no_rounds_stored_hashes\(ad_dc:local\)
+^samba.tests.samba_tool.user_virtualCryptSHA.samba.tests.samba_tool.user_virtualCryptSHA.UserCmdCryptShaTestCase.test_no_gpg_both_hashes_rounds_stored_hashes_with_rounds\(ad_dc:local\)
+^samba.tests.samba_tool.user_virtualCryptSHA.samba.tests.samba_tool.user_virtualCryptSHA.UserCmdCryptShaTestCase.test_gpg_both_hashes_rounds_stored_hashes_with_rounds\(ad_dc:local\)
+^samba.tests.samba_tool.user_virtualCryptSHA.samba.tests.samba_tool.user_virtualCryptSHA.UserCmdCryptShaTestCase.test_gpg_both_hashes_no_rounds_stored_hashes\(ad_dc:local\)