1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-10 01:18:15 +03:00
samba-mirror/python/samba/tests/samba_tool/user_wdigest.py
Douglas Bagnall f0860de5bb python compat: remove text_type
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Noel Power <npower@samba.org>
2020-08-11 16:37:35 +00:00

467 lines
16 KiB
Python

# Tests for the samba-tool user sub command reading Primary:WDigest
#
# Copyright (C) Andrew Bartlett <abartlet@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 import (
credentials,
nttime2unix,
dsdb
)
from samba.ndr import ndr_unpack
from samba.dcerpc import drsblobs
from hashlib import md5
import random
import string
USER_NAME = "WdigestTestUser"
# Create a random 32 character password, containing only letters and
# digits to avoid issues when used on the command line.
USER_PASS = ''.join(random.choice(string.ascii_uppercase +
string.ascii_lowercase +
string.digits) for _ in range(32))
# 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)
if isinstance(data, str):
data = data.encode('utf8')
return "%s:%s:%s" % (user, realm, md5(data).hexdigest())
class UserCmdWdigestTestCase(SambaToolCmdTest):
"""Tests for samba-tool user subcommands extraction of the wdigest values
Test results validated against Windows Server 2012 R2.
NOTE: That as at 22-05-2017 the values Documented at
3.1.1.8.11.3.1 WDIGEST_CREDENTIALS Construction
are incorrect.
"""
users = []
samdb = None
def setUp(self):
super(UserCmdWdigestTestCase, self).setUp()
self.lp = samba.tests.env_loadparm()
self.samdb = self.getSamDB(
"-H", "ldap://%s" % os.environ["DC_SERVER"],
"-U%s%%%s" % (os.environ["DC_USERNAME"],
os.environ["DC_PASSWORD"]))
self.dns_domain = self.samdb.domain_dns_name()
res = self.samdb.search(
base=self.samdb.get_config_basedn(),
expression="ncName=%s" % self.samdb.get_default_basedn(),
attrs=["nETBIOSName"])
self.netbios_domain = str(res[0]["nETBIOSName"][0])
self.runsubcmd("user",
"create",
USER_NAME,
USER_PASS,
"-H",
"ldap://%s" % os.environ["DC_SERVER"],
"-U%s%%%s" % (
os.environ["DC_USERNAME"],
os.environ["DC_PASSWORD"]))
def tearDown(self):
super(UserCmdWdigestTestCase, self).tearDown()
self.runsubcmd("user", "delete", USER_NAME)
def _testWDigest(self, attribute, expected, missing=False):
(result, out, err) = self.runsubcmd("user",
"getpassword",
USER_NAME,
"--attributes",
attribute)
self.assertCmdSuccess(result,
out,
err,
"Ensure getpassword runs")
self.assertEqual(err, "", "getpassword")
self.assertMatch(out,
"Got password OK",
"getpassword out[%s]" % out)
if missing:
self.assertTrue(attribute not in out)
else:
self.assertMatch(out.replace('\n ', ''),
"%s: %s" % (attribute, expected))
def test_Wdigest_no_suffix(self):
attribute = "virtualWDigest"
self._testWDigest(attribute, None, True)
def test_Wdigest_non_numeric_suffix(self):
attribute = "virtualWDigestss"
self._testWDigest(attribute, None, True)
def test_Wdigest00(self):
attribute = "virtualWDigest00"
self._testWDigest(attribute, None, True)
# Hash01 MD5(sAMAccountName,
# NETBIOSDomainName,
# password)
#
def test_Wdigest01(self):
attribute = "virtualWDigest01"
expected = calc_digest(USER_NAME,
self.netbios_domain,
USER_PASS)
self._testWDigest(attribute, expected)
# Hash02 MD5(LOWER(sAMAccountName),
# LOWER(NETBIOSDomainName),
# password)
#
def test_Wdigest02(self):
attribute = "virtualWDigest02"
expected = calc_digest(USER_NAME.lower(),
self.netbios_domain.lower(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash03 MD5(UPPER(sAMAccountName),
# UPPER(NETBIOSDomainName),
# password)
#
def test_Wdigest03(self):
attribute = "virtualWDigest03"
expected = calc_digest(USER_NAME.upper(),
self.netbios_domain.upper(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash04 MD5(sAMAccountName,
# UPPER(NETBIOSDomainName),
# password)
#
def test_Wdigest04(self):
attribute = "virtualWDigest04"
expected = calc_digest(USER_NAME,
self.netbios_domain.upper(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash05 MD5(sAMAccountName,
# LOWER(NETBIOSDomainName),
# password)
#
def test_Wdigest05(self):
attribute = "virtualWDigest05"
expected = calc_digest(USER_NAME,
self.netbios_domain.lower(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash06 MD5(UPPER(sAMAccountName),
# LOWER(NETBIOSDomainName),
# password)
#
def test_Wdigest06(self):
attribute = "virtualWDigest06"
expected = calc_digest(USER_NAME.upper(),
self.netbios_domain.lower(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash07 MD5(LOWER(sAMAccountName),
# UPPER(NETBIOSDomainName),
# password)
#
def test_Wdigest07(self):
attribute = "virtualWDigest07"
expected = calc_digest(USER_NAME.lower(),
self.netbios_domain.upper(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash08 MD5(sAMAccountName,
# DNSDomainName,
# password)
#
# Note: Samba lowercases the DNSDomainName at provision time,
# Windows preserves the case. This means that the WDigest08 values
# calculated byt Samba and Windows differ.
#
def test_Wdigest08(self):
attribute = "virtualWDigest08"
expected = calc_digest(USER_NAME,
self.dns_domain,
USER_PASS)
self._testWDigest(attribute, expected)
# Hash09 MD5(LOWER(sAMAccountName),
# LOWER(DNSDomainName),
# password)
#
def test_Wdigest09(self):
attribute = "virtualWDigest09"
expected = calc_digest(USER_NAME.lower(),
self.dns_domain.lower(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash10 MD5(UPPER(sAMAccountName),
# UPPER(DNSDomainName),
# password)
#
def test_Wdigest10(self):
attribute = "virtualWDigest10"
expected = calc_digest(USER_NAME.upper(),
self.dns_domain.upper(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash11 MD5(sAMAccountName,
# UPPER(DNSDomainName),
# password)
#
def test_Wdigest11(self):
attribute = "virtualWDigest11"
expected = calc_digest(USER_NAME,
self.dns_domain.upper(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash12 MD5(sAMAccountName,
# LOWER(DNSDomainName),
# password)
#
def test_Wdigest12(self):
attribute = "virtualWDigest12"
expected = calc_digest(USER_NAME,
self.dns_domain.lower(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash13 MD5(UPPER(sAMAccountName),
# LOWER(DNSDomainName),
# password)
#
def test_Wdigest13(self):
attribute = "virtualWDigest13"
expected = calc_digest(USER_NAME.upper(),
self.dns_domain.lower(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash14 MD5(LOWER(sAMAccountName),
# UPPER(DNSDomainName),
# password)
#
def test_Wdigest14(self):
attribute = "virtualWDigest14"
expected = calc_digest(USER_NAME.lower(),
self.dns_domain.upper(),
USER_PASS)
self._testWDigest(attribute, expected)
# Hash15 MD5(userPrincipalName,
# password)
#
def test_Wdigest15(self):
attribute = "virtualWDigest15"
name = "%s@%s" % (USER_NAME, self.dns_domain)
expected = calc_digest(name,
"",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash16 MD5(LOWER(userPrincipalName),
# password)
#
def test_Wdigest16(self):
attribute = "virtualWDigest16"
name = "%s@%s" % (USER_NAME.lower(), self.dns_domain.lower())
expected = calc_digest(name,
"",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash17 MD5(UPPER(userPrincipalName),
# password)
#
def test_Wdigest17(self):
attribute = "virtualWDigest17"
name = "%s@%s" % (USER_NAME.upper(), self.dns_domain.upper())
expected = calc_digest(name,
"",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash18 MD5(NETBIOSDomainName\sAMAccountName,
# password)
#
def test_Wdigest18(self):
attribute = "virtualWDigest18"
name = "%s\\%s" % (self.netbios_domain, USER_NAME)
expected = calc_digest(name,
"",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash19 MD5(LOWER(NETBIOSDomainName\sAMAccountName),
# password)
#
def test_Wdigest19(self):
attribute = "virtualWDigest19"
name = "%s\\%s" % (self.netbios_domain, USER_NAME)
expected = calc_digest(name.lower(),
"",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash20 MD5(UPPER(NETBIOSDomainName\sAMAccountName),
# password)
#
def test_Wdigest20(self):
attribute = "virtualWDigest20"
name = "%s\\%s" % (self.netbios_domain, USER_NAME)
expected = calc_digest(name.upper(),
"",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash21 MD5(sAMAccountName,
# "Digest",
# password)
#
def test_Wdigest21(self):
attribute = "virtualWDigest21"
expected = calc_digest(USER_NAME,
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash22 MD5(LOWER(sAMAccountName),
# "Digest",
# password)
#
def test_Wdigest22(self):
attribute = "virtualWDigest22"
expected = calc_digest(USER_NAME.lower(),
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash23 MD5(UPPER(sAMAccountName),
# "Digest",
# password)
#
def test_Wdigest23(self):
attribute = "virtualWDigest23"
expected = calc_digest(USER_NAME.upper(),
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash24 MD5(userPrincipalName),
# "Digest",
# password)
#
def test_Wdigest24(self):
attribute = "virtualWDigest24"
name = "%s@%s" % (USER_NAME, self.dns_domain)
expected = calc_digest(name,
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash25 MD5(LOWER(userPrincipalName),
# "Digest",
# password)
#
def test_Wdigest25(self):
attribute = "virtualWDigest25"
name = "%s@%s" % (USER_NAME, self.dns_domain.lower())
expected = calc_digest(name.lower(),
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash26 MD5(UPPER(userPrincipalName),
# "Digest",
# password)
#
def test_Wdigest26(self):
attribute = "virtualWDigest26"
name = "%s@%s" % (USER_NAME, self.dns_domain.lower())
expected = calc_digest(name.upper(),
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash27 MD5(NETBIOSDomainName\sAMAccountName,
# "Digest",
# password)
#
def test_Wdigest27(self):
attribute = "virtualWDigest27"
name = "%s\\%s" % (self.netbios_domain, USER_NAME)
expected = calc_digest(name,
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash28 MD5(LOWER(NETBIOSDomainName\sAMAccountName),
# "Digest",
# password)
#
def test_Wdigest28(self):
attribute = "virtualWDigest28"
name = "%s\\%s" % (self.netbios_domain.lower(), USER_NAME.lower())
expected = calc_digest(name,
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
# Hash29 MD5(UPPER(NETBIOSDomainName\sAMAccountName),
# "Digest",
# password)
#
def test_Wdigest29(self):
attribute = "virtualWDigest29"
name = "%s\\%s" % (self.netbios_domain.upper(), USER_NAME.upper())
expected = calc_digest(name,
"Digest",
USER_PASS)
self._testWDigest(attribute, expected)
def test_Wdigest30(self):
attribute = "virtualWDigest30"
self._testWDigest(attribute, None, True)
# Check digest calculation against an known htdigest value
def test_calc_digest(self):
htdigest = "gary:fred:2204fcc247cb47ded249ef2fe0013255"
digest = calc_digest("gary", "fred", "password")
self.assertEqual(htdigest, digest)