[SCM] Samba Shared Repository - branch v4-12-test updated

Karolin Seeger kseeger at samba.org
Mon Jul 6 11:45:03 UTC 2020


The branch, v4-12-test has been updated
       via  b53b7fc274e selftest: Run test of how userPassword / crypt() style passwords are stored in quicktest
       via  3b9e5cae07b selftest: Split samba.tests.samba_tool.user_virtualCryptSHA into GPG and not GPG parts
       via  6eb3fba83cd dsdb: Allow "password hash userPassword schemes = CryptSHA256" to work on RHEL7
       via  25f198a12b9 util: fix build on AIX by fixing the order of replace.h include
       via  8cffe254eda util: Reallocate larger buffer if getpwuid_r() returns ERANGE
       via  6e263432eef util: Fix build on FreeBSD by avoiding NSS_BUFLEN_PASSWD
       via  42ad8c2c480 util: Simplify input validation
       via  79f5d88663b s3: libsmb: Fix SMB2 client rename bug to a Windows server.
      from  c160cfa9922 VERSION: Bump version up to 4.12.6...

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-12-test


- Log -----------------------------------------------------------------
commit b53b7fc274e21d393613d28fb70e3fce40bace5c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jul 1 14:31:54 2020 +1200

    selftest: Run test of how userPassword / crypt() style passwords are stored in quicktest
    
    This ensures that the crypt_r()/crypt_rn()/crypt() behaviour is tested in all
    the samba-o3 builds and so is checked on RHEL7 in GitLab CI.
    
    https://bugzilla.samba.org/show_bug.cgi?id=14424
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>
    (cherry picked from commit cabf873b75b1d4d456190358bc3ed051bca16978)
    
    Autobuild-User(v4-12-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-12-test): Mon Jul  6 11:44:23 UTC 2020 on sn-devel-184

commit 3b9e5cae07ba2568175b94c47649c53f408cc3c8
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jul 1 14:30:24 2020 +1200

    selftest: Split samba.tests.samba_tool.user_virtualCryptSHA into GPG and not GPG parts
    
    This allows the userPassword (not GPG) part of the test to run on hosts without
    python3-gpg (eg RHEL7) while still testing the userPassword handling.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14424
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>
    (cherry picked from commit 2c4ecf002a3fbbe8be061814468529c8bd6bb7aa)

commit 6eb3fba83cd374103821fbc5ce72cd1956b08045
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jul 1 14:35:39 2020 +1200

    dsdb: Allow "password hash userPassword schemes = CryptSHA256" to work on RHEL7
    
    On RHEL7 crypt_r() will set errno.  This is a problem because the implementation of crypt_r()
    in RHEL8 and elsewhere in libcrypt will return non-NULL but set errno on failure.
    
    The workaround is to use crypt_rn(), provided only by libcrypt, which will return NULL
    on failure, and so avoid checking errno in the non-failure case.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14424
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>
    (cherry picked from commit 91453f110fa72062291eb59ad9d95fab0f423557)

commit 25f198a12b9898e69accbbe62cd3c4524644a57f
Author: Bjoern Jacke <bjacke at samba.org>
Date:   Mon Jun 29 12:00:46 2020 +0000

    util: fix build on AIX by fixing the order of replace.h include
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14422
    
    Signed-off-by: Bjoern Jacke <bjacke at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    (cherry picked from commit d93a6d2663a25bca072cd5623aea16e21ed650b8)

commit 8cffe254eda6c7ae843d79610eacb9a1020ef01a
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Jun 5 22:05:42 2020 +1000

    util: Reallocate larger buffer if getpwuid_r() returns ERANGE
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Bjoern Jacke <bjacke at samba.org>
    
    Autobuild-User(master): Martin Schwenke <martins at samba.org>
    Autobuild-Date(master): Tue Jun  9 21:07:24 UTC 2020 on sn-devel-184
    
    (cherry picked from commit ddac6b2eb4adaec8fc5e25ca07387d2b9417764c)

commit 6e263432eefe0709738799242ff50ca759ce7ada
Author: Martin Schwenke <martin at meltin.net>
Date:   Fri Jun 5 21:52:23 2020 +1000

    util: Fix build on FreeBSD by avoiding NSS_BUFLEN_PASSWD
    
    NSS_BUFLEN_PASSWD is not defined on FreeBSD.  Use
    sysconf(_SC_GETPW_R_SIZE_MAX) instead, as per POSIX.
    
    Use a dynamically allocated buffer instead of trying to cram all of
    the logic into the declarations.  This will come in useful later
    anyway.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Bjoern Jacke <bjacke at samba.org>
    (cherry picked from commit 847208cd8ac68c4c7d1dae63767820db1c69292b)

commit 42ad8c2c4805b825317b8944df1c3cf1c2c3c2cc
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Jun 9 11:52:50 2020 +1000

    util: Simplify input validation
    
    It appears that snprintf(3) is being used for input validation.
    However, this seems like overkill because it causes szPath to be
    copied an extra time.  The mostly likely protections being sought
    here, according to https://cwe.mitre.org/data/definitions/20.html,
    look to be DoS attacks involving CPU and memory usage.  A simpler
    check that uses strnlen(3) can mitigate against both of these and is
    simpler.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Bjoern Jacke <bjacke at samba.org>
    (cherry picked from commit 922bce2668994dd2a5988c17060f977e9bb0c229)

commit 79f5d88663ba8e106f3c04e420478afc499afbee
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Jun 30 14:00:41 2020 -0700

    s3: libsmb: Fix SMB2 client rename bug to a Windows server.
    
    Fix bug where renaming to a target name of one
    UCS2 character (name length 2 bytes) fails to
    a Windows 10 SMB2 server.
    
    The Windows 10 SMB2 server has a minimum length
    for a SMB2_FILE_RENAME_INFORMATION buffer of
    24 bytes. It returns NT_STATUS_INFO_LENGTH_MISMATCH
    if the length is less. This isn't an alignment
    issue as Windows client happily 2-byte align
    for larget target name sizes. Also the Windows 10
    SMB1 server doesn't have this restriction.
    
    If the name length is too short, pad out with
    zeros to 24 bytes.
    
    Hard to add a test for this as we don't want to
    add this silly restriction to the Samba server
    as it would break all non-Windows clients.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14403
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Wed Jul  1 18:59:53 UTC 2020 on sn-devel-184
    
    (cherry picked from commit f59490dc2d07107d32d6e888f2814011ab2845b7)

-----------------------------------------------------------------------

Summary of changes:
 lib/replace/wscript                                |   1 +
 lib/util/tests/test_util_paths.c                   |   2 +-
 lib/util/util_paths.c                              |  47 +++-
 .../tests/samba_tool/user_virtualCryptSHA_base.py  | 118 ++++++++++
 .../tests/samba_tool/user_virtualCryptSHA_gpg.py   | 261 +++++++++++++++++++++
 .../user_virtualCryptSHA_userPassword.py           | 185 +++++++++++++++
 selftest/quick                                     |   3 +
 source3/libsmb/cli_smb2_fnum.c                     |  26 +-
 source4/dsdb/samdb/ldb_modules/password_hash.c     |  37 ++-
 source4/selftest/tests.py                          |   3 +-
 10 files changed, 663 insertions(+), 20 deletions(-)
 create mode 100644 python/samba/tests/samba_tool/user_virtualCryptSHA_base.py
 create mode 100644 python/samba/tests/samba_tool/user_virtualCryptSHA_gpg.py
 create mode 100644 python/samba/tests/samba_tool/user_virtualCryptSHA_userPassword.py


Changeset truncated at 500 lines:

diff --git a/lib/replace/wscript b/lib/replace/wscript
index ab2b3c043af..55c8903f1c8 100644
--- a/lib/replace/wscript
+++ b/lib/replace/wscript
@@ -661,6 +661,7 @@ def configure(conf):
 
     conf.CHECK_FUNCS_IN('crypt', 'crypt', checklibc=True)
     conf.CHECK_FUNCS_IN('crypt_r', 'crypt', checklibc=True)
+    conf.CHECK_FUNCS_IN('crypt_rn', 'crypt', checklibc=True)
 
     conf.CHECK_VARIABLE('rl_event_hook', define='HAVE_DECL_RL_EVENT_HOOK', always=True,
                         headers='readline.h readline/readline.h readline/history.h')
diff --git a/lib/util/tests/test_util_paths.c b/lib/util/tests/test_util_paths.c
index b89abf0aea1..4dfe11c1445 100644
--- a/lib/util/tests/test_util_paths.c
+++ b/lib/util/tests/test_util_paths.c
@@ -23,9 +23,9 @@
 #include <setjmp.h>
 #include <cmocka.h>
 
+#include "lib/replace/replace.h"
 #include <talloc.h>
 
-#include "lib/replace/replace.h"
 #include "lib/util/util_paths.c"
 
 static int setup(void **state)
diff --git a/lib/util/util_paths.c b/lib/util/util_paths.c
index c0ee5c32c30..72cc0aab8de 100644
--- a/lib/util/util_paths.c
+++ b/lib/util/util_paths.c
@@ -68,25 +68,54 @@ static char *get_user_home_dir(TALLOC_CTX *mem_ctx)
 {
 	struct passwd pwd = {0};
 	struct passwd *pwdbuf = NULL;
-	char buf[NSS_BUFLEN_PASSWD] = {0};
+	char *buf = NULL;
+	char *out = NULL;
+	long int initlen;
+	size_t len;
 	int rc;
 
-	rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
+	initlen = sysconf(_SC_GETPW_R_SIZE_MAX);
+	if (initlen == -1) {
+		len = 1024;
+	} else {
+		len = (size_t)initlen;
+	}
+	buf = talloc_size(mem_ctx, len);
+	if (buf == NULL) {
+		return NULL;
+	}
+
+	rc = getpwuid_r(getuid(), &pwd, buf, len, &pwdbuf);
+	while (rc == ERANGE) {
+		size_t newlen = 2 * len;
+		if (newlen < len) {
+			/* Overflow */
+			goto done;
+		}
+		len = newlen;
+		buf = talloc_realloc_size(mem_ctx, buf, len);
+		if (buf == NULL) {
+			goto done;
+		}
+		rc = getpwuid_r(getuid(), &pwd, buf, len, &pwdbuf);
+	}
 	if (rc != 0 || pwdbuf == NULL ) {
-		int len_written;
 		const char *szPath = getenv("HOME");
 		if (szPath == NULL) {
-			return NULL;
+			goto done;
 		}
-		len_written = snprintf(buf, sizeof(buf), "%s", szPath);
-		if (len_written >= sizeof(buf) || len_written < 0) {
-			/* Output was truncated or an error. */
+		len = strnlen(szPath, PATH_MAX);
+		if (len >= PATH_MAX) {
 			return NULL;
 		}
-		return talloc_strdup(mem_ctx, buf);
+		out = talloc_strdup(mem_ctx, szPath);
+		goto done;
 	}
 
-	return talloc_strdup(mem_ctx, pwd.pw_dir);
+	out = talloc_strdup(mem_ctx, pwd.pw_dir);
+done:
+	TALLOC_FREE(buf);
+	return out;
 }
 
 char *path_expand_tilde(TALLOC_CTX *mem_ctx, const char *d)
diff --git a/python/samba/tests/samba_tool/user_virtualCryptSHA_base.py b/python/samba/tests/samba_tool/user_virtualCryptSHA_base.py
new file mode 100644
index 00000000000..e32f8d7343c
--- /dev/null
+++ b/python/samba/tests/samba_tool/user_virtualCryptSHA_base.py
@@ -0,0 +1,118 @@
+# Tests for the samba-tool user sub command reading Primary:userPassword
+#
+# Copyright (C) Andrew Bartlett <abartlet at samba.org> 2017
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import time
+import base64
+import ldb
+import samba
+from samba.tests.samba_tool.base import SambaToolCmdTest
+from samba.credentials import Credentials
+from samba.samdb import SamDB
+from samba.auth import system_session
+from samba.ndr import ndr_unpack
+from samba.dcerpc import drsblobs
+from samba import dsdb
+import re
+
+USER_NAME = "CryptSHATestUser"
+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,
+#       which is acceptable for it's usage in these tests.
+
+
+def _get_attribute(out, name):
+    p = re.compile("^" + name + ":\s+(\S+)")
+    for line in out.split("\n"):
+        m = p.match(line)
+        if m:
+            return m.group(1)
+    return ""
+
+
+class UserCmdCryptShaTestCase(SambaToolCmdTest):
+    """
+    Tests for samba-tool user subcommands generation of the virtualCryptSHA256
+    and virtualCryptSHA512 attributes
+    """
+    users = []
+    samdb = None
+
+    def setUp(self):
+        super(UserCmdCryptShaTestCase, self).setUp()
+
+    def add_user(self, hashes=""):
+        self.lp = samba.tests.env_loadparm()
+
+        # set the extra hashes to be calculated
+        self.lp.set(HASH_OPTION, hashes)
+
+        self.creds = Credentials()
+        self.session = system_session()
+        self.ldb = SamDB(
+            session_info=self.session,
+            credentials=self.creds,
+            lp=self.lp)
+
+        password = self.random_password()
+        self.runsubcmd("user",
+                       "create",
+                       USER_NAME,
+                       password)
+
+    def tearDown(self):
+        super(UserCmdCryptShaTestCase, self).tearDown()
+        self.runsubcmd("user", "delete", USER_NAME)
+
+    def _get_password(self, attributes, decrypt=False):
+        command = ["user",
+                   "getpassword",
+                   USER_NAME,
+                   "--attributes",
+                   attributes]
+        if decrypt:
+            command.append("--decrypt-samba-gpg")
+
+        (result, out, err) = self.runsubcmd(*command)
+        self.assertCmdSuccess(result,
+                              out,
+                              err,
+                              "Ensure getpassword runs")
+        self.assertEqual(err, "", "getpassword")
+        self.assertMatch(out,
+                         "Got password OK",
+                         "getpassword out[%s]" % out)
+        return out
+
+    # Change the just the NT password hash, as would happen if the password
+    # was updated by Windows, the userPassword values are now obsolete.
+    #
+    def _change_nt_hash(self):
+        res = self.ldb.search(expression = "cn=%s" % USER_NAME,
+                              scope      = ldb.SCOPE_SUBTREE)
+        msg = ldb.Message()
+        msg.dn = res[0].dn
+        msg["unicodePwd"] = ldb.MessageElement(b"ABCDEF1234567890",
+                                               ldb.FLAG_MOD_REPLACE,
+                                               "unicodePwd")
+        self.ldb.modify(
+            msg,
+            controls=["local_oid:%s:0" %
+                      dsdb.DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID])
diff --git a/python/samba/tests/samba_tool/user_virtualCryptSHA_gpg.py b/python/samba/tests/samba_tool/user_virtualCryptSHA_gpg.py
new file mode 100644
index 00000000000..25c02d9ac2a
--- /dev/null
+++ b/python/samba/tests/samba_tool/user_virtualCryptSHA_gpg.py
@@ -0,0 +1,261 @@
+# Tests for the samba-tool user sub command reading Primary:userPassword
+#
+# Copyright (C) Andrew Bartlett <abartlet at samba.org> 2017
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.tests.samba_tool.user_virtualCryptSHA_base import UserCmdCryptShaTestCase, _get_attribute
+
+class UserCmdCryptShaTestCaseGPG(UserCmdCryptShaTestCase):
+    """
+    Tests for samba-tool user subcommands generation of the virtualCryptSHA256
+    and virtualCryptSHA512 attributes
+    """
+
+    # 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()
+        out = self._get_password("virtualCryptSHA256,virtualCryptSHA512", True)
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" not in out)
+
+    # gpg decryption enabled.
+    # SHA256 specified
+    # no hashes stored in supplementalCredentials
+    # No rounds
+    #
+    # Should get values
+    def test_gpg_sha256_no_rounds(self):
+        self.add_user()
+        out = self._get_password("virtualCryptSHA256", True)
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" not in out)
+        self.assertTrue("rounds=" not in out)
+
+    # gpg decryption enabled.
+    # SHA512 specified
+    # no hashes stored in supplementalCredentials
+    # No rounds
+    #
+    # Should get values
+    def test_gpg_sha512_no_rounds(self):
+        self.add_user()
+        out = self._get_password("virtualCryptSHA512", True)
+
+        self.assertTrue("virtualCryptSHA256:" not in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+        self.assertTrue("rounds=" not in out)
+
+    # gpg decryption enabled.
+    # SHA128 specified, i.e. invalid/unknown algorithm
+    # no hashes stored in supplementalCredentials
+    # No rounds
+    #
+    # Should not get values
+    def test_gpg_invalid_alg_no_rounds(self):
+        self.add_user()
+        out = self._get_password("virtualCryptSHA128", True)
+
+        self.assertTrue("virtualCryptSHA256:" not in out)
+        self.assertTrue("virtualCryptSHA512:" not in out)
+        self.assertTrue("rounds=" not in out)
+
+    # 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
+    def test_gpg_both_hashes_no_rounds_pwd_changed(self):
+        self.add_user()
+        self._change_nt_hash()
+        out = self._get_password("virtualCryptSHA256,virtualCryptSHA512", True)
+
+        self.assertTrue("virtualCryptSHA256:" not in out)
+        self.assertTrue("virtualCryptSHA512:" not in out)
+        self.assertTrue("rounds=" not in out)
+
+    # 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
+    def test_gpg_sha256_no_rounds_pwd_changed(self):
+        self.add_user()
+        self._change_nt_hash()
+        out = self._get_password("virtualCryptSHA256", True)
+
+        self.assertTrue("virtualCryptSHA256:" not in out)
+        self.assertTrue("virtualCryptSHA512:" not in out)
+        self.assertTrue("rounds=" not in out)
+
+    # 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
+    def test_gpg_sha512_no_rounds_pwd_changed(self):
+        self.add_user()
+        self._change_nt_hash()
+        out = self._get_password("virtualCryptSHA256", True)
+
+        self.assertTrue("virtualCryptSHA256:" not in out)
+        self.assertTrue("virtualCryptSHA512:" not in out)
+        self.assertTrue("rounds=" not in out)
+
+    # 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()
+        out = self._get_password(
+            "virtualCryptSHA256;rounds=10123,virtualCryptSHA512;rounds=10456",
+            True)
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        self.assertTrue(sha256.startswith("{CRYPT}$5$rounds=10123$"))
+
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+        self.assertTrue(sha512.startswith("{CRYPT}$6$rounds=10456$"))
+
+    # 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()
+        out = self._get_password(
+            "virtualCryptSHA256;rounds=invalid,virtualCryptSHA512;rounds=3125",
+            True)
+
+        self.assertTrue("virtualCryptSHA256:" in out)
+        self.assertTrue("virtualCryptSHA512:" in out)
+
+        sha256 = _get_attribute(out, "virtualCryptSHA256")
+        self.assertTrue(sha256.startswith("{CRYPT}$5$"))
+        self.assertTrue("rounds" not in sha256)
+
+        sha512 = _get_attribute(out, "virtualCryptSHA512")
+        self.assertTrue(sha512.startswith("{CRYPT}$6$rounds=3125$"))
+
+    # 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"))
diff --git a/python/samba/tests/samba_tool/user_virtualCryptSHA_userPassword.py b/python/samba/tests/samba_tool/user_virtualCryptSHA_userPassword.py
new file mode 100644
index 00000000000..6c1c6295b85
--- /dev/null
+++ b/python/samba/tests/samba_tool/user_virtualCryptSHA_userPassword.py
@@ -0,0 +1,185 @@
+# Tests for the samba-tool user sub command reading Primary:userPassword
+#
+# Copyright (C) Andrew Bartlett <abartlet at samba.org> 2017
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.


-- 
Samba Shared Repository



More information about the samba-cvs mailing list