>From cc7de250b0748f954769d20873f10e75e56b00c2 Mon Sep 17 00:00:00 2001 From: Rowland Penny Date: Thu, 5 May 2016 09:21:46 +0100 Subject: [PATCH] Subject: [PATCH] Make 'Samba-tool domain provision' more friendly Signed-off-by: Rowland Penny --- python/samba/netcmd/domain.py | 151 ++++++++++++++++++++++++++++++----------- 1 file changed, 111 insertions(+), 40 deletions(-) diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py index 68775ec..bf72ac1 100644 --- a/python/samba/netcmd/domain.py +++ b/python/samba/netcmd/domain.py @@ -33,6 +33,7 @@ import tempfile import logging import subprocess from getpass import getpass +import re from samba.net import Net, LIBNET_JOIN_AUTOMATIC import samba.ntacls from samba.join import join_RODC, join_DC, join_subdomain @@ -128,6 +129,52 @@ else: net = Net(None, lp) net.export_keytab(keytab=keytab, principal=principal) +def password_check(password): + """ + Verify the strength of 'password' + Returns True or False + A password must be at least 8 characters long + A password is considered strong if it contains 3 of the following: + 1 uppercase letter or more + 1 lowercase letter or more + 1 digit or more + 1 symbol or more + """ + + # calculating the length + if len(password) <= 7: + return False + + counter = 0 + # searching for digits + digit_error = re.search(r"\d", password) is None + if not digit_error: + # contains at least one digit + counter = counter + 1 + + # searching for uppercase + uppercase_error = re.search(r"[A-Z]", password) is None + if not uppercase_error: + # contains at least one uppercase character + counter = counter + 1 + + # searching for lowercase + lowercase_error = re.search(r"[a-z]", password) is None + if not lowercase_error: + # contains at least one lowercase character + counter = counter + 1 + + # searching for symbols + symbol_error = re.search(r"\W", password) is None + if not symbol_error: + # contains at least one symbol character + counter = counter + 1 + + if counter >= 3: + return True + else: + return False + class cmd_domain_info(Command): """Print basic info about a domain and the DC passed as parameter.""" @@ -161,9 +208,39 @@ class cmd_domain_info(Command): class cmd_domain_provision(Command): - """Provision a domain.""" + """Provision a domain. + +This command provisions a new Active Directory domain. You must supply the +Realm name and the NetBIOS domain name. + +You can run the command interactively or supply options with the command. + +Example1: +samba-tool domain provision SAMBA.EXAMPLE.COM SAMBA --use-rfc2307 \ +--use-xattrs=yes --adminpass=P4$$word + +Example1 will provision a new domain, using the realm name 'SAMBA.EXAMPLE.COM' +and the NetBIOS (workgroup) name 'SAMBA', it will also use RFC2307 attributes +and ACLs. It will use the default 2008_R2 function level and the internal +DNS server. + +Example2: +samba-tool domain provision SAMBA.EXAMPLE.COM SAMBA --use-rfc2307 \ +--use-xattrs=yes --dns-backend= BIND9_DLZ --adminpass=P4$$word + +Example2 will provision a new domain, using the realm name 'SAMBA.EXAMPLE.COM' +and the NetBIOS (workgroup) name 'SAMBA', it will also use RFC2307 attributes +and ACLs. It will use the default 2008_R2 function level and Bind9 for the +DNS server. + +Example3: +samba-tool domain provision SAMBA.EXAMPLE.COM SAMBA --interactive +Example3 will provision a new domain, using the realm name 'SAMBA.EXAMPLE.COM' +and the NetBIOS (workgroup) name 'SAMBA', it will ask for further information +via the command line.""" - synopsis = "%prog [options]" + + synopsis = "%prog [options]" takes_optiongroups = { "sambaopts": options.SambaOptions, @@ -172,8 +249,6 @@ class cmd_domain_provision(Command): takes_options = [ Option("--interactive", help="Ask for names", action="store_true"), - Option("--domain", type="string", metavar="DOMAIN", - help="set domain"), Option("--domain-guid", type="string", metavar="GUID", help="set domainguid (otherwise random)"), Option("--domain-sid", type="string", metavar="SID", @@ -219,10 +294,6 @@ class cmd_domain_provision(Command): Option("--ldap-backend-type", type="choice", metavar="LDAP-BACKEND-TYPE", help="Test initialisation support for unsupported LDAP backend type (fedora-ds or openldap) DO NOT USE", choices=["fedora-ds", "openldap"]), - Option("--server-role", type="choice", metavar="ROLE", - choices=["domain controller", "dc", "member server", "member", "standalone"], - help="The server role (domain controller | dc | member server | member | standalone). Default is dc.", - default="domain controller"), Option("--function-level", type="choice", metavar="FOR-FUN-LEVEL", choices=["2000", "2003", "2008", "2008_R2"], help="The domain and forest function level (2000 | 2003 | 2008 | 2008_R2 - always native). Default is (Windows) 2008_R2 Native.", @@ -261,11 +332,11 @@ class cmd_domain_provision(Command): if samba.is_ntvfs_fileserver_built(): takes_options.extend(ntvfs_options) - takes_args = [] + takes_args = ["krbrealm", "domain"] - def run(self, sambaopts=None, versionopts=None, + def run(self, krbrealm, domain, + sambaopts=None, versionopts=None, interactive=None, - domain=None, domain_guid=None, domain_sid=None, ntds_guid=None, @@ -287,7 +358,6 @@ class cmd_domain_provision(Command): quiet=None, blank=None, ldap_backend_type=None, - server_role=None, function_level=None, next_rid=None, partitions_only=None, @@ -311,6 +381,9 @@ class cmd_domain_provision(Command): lp = sambaopts.get_loadparm() smbconf = lp.configfile + if krbrealm == domain: + raise CommandError("The NetBIOS domain name cannot be the same as the realm") + if dns_forwarder is not None: suggested_forwarder = dns_forwarder else: @@ -321,6 +394,8 @@ class cmd_domain_provision(Command): if len(self.raw_argv) == 1: interactive = True + server_role = "dc" + if interactive: from getpass import getpass import socket @@ -332,24 +407,6 @@ class cmd_domain_provision(Command): print "%s: " % (prompt,), return sys.stdin.readline().rstrip("\n") or default - try: - default = socket.getfqdn().split(".", 1)[1].upper() - except IndexError: - default = None - realm = ask("Realm", default) - if realm in (None, ""): - raise CommandError("No realm set!") - - try: - default = realm.split(".")[0] - except IndexError: - default = None - domain = ask("Domain", default) - if domain is None: - raise CommandError("No domain set!") - - server_role = ask("Server Role (dc, member, standalone)", "dc") - dns_backend = ask("DNS backend (SAMBA_INTERNAL, BIND9_FLATFILE, BIND9_DLZ, NONE)", "SAMBA_INTERNAL") if dns_backend in (None, ''): raise CommandError("No DNS backend set!") @@ -360,6 +417,18 @@ class cmd_domain_provision(Command): suggested_forwarder = None dns_forwarder = None + function_level = ask("Function level (2000, 2003, 2008, 2008_R2)", "2008_R2") + if function_level in (None, ''): + raise CommandError("No Function level set!") + + use_xattrs = ask("Use xattrs (yes, no, auto)", "auto") + if use_xattrs in (None, ''): + raise CommandError("Use xattrs not set!") + + use_rfc2307 = ask("Use AD to store posix attributes (yes, no)", "no") + if use_rfc2307 in (None, ''): + raise CommandError("Use xattrs not set!") + while True: adminpassplain = getpass("Administrator password: ") if not adminpassplain: @@ -370,17 +439,19 @@ class cmd_domain_provision(Command): self.errf.write("Sorry, passwords do not match.\n") else: adminpass = adminpassplain - break + passcheck = password_check(adminpass) + if passcheck == True: + break + else: + self.errf.write("The supplied admin password is not complex enough\n") else: - realm = sambaopts._lp.get('realm') - if realm is None: - raise CommandError("No realm set!") - if domain is None: - raise CommandError("No domain set!") - - if not adminpass: - self.logger.info("Administrator password will be set randomly!") + if not adminpass: + self.logger.info("Administrator password will be set randomly!") + else: + passcheck = password_check(adminpass) + if passcheck == False: + raise CommandError("The supplied admin password is not complex enough") if function_level == "2000": dom_for_fun_level = DS_DOMAIN_FUNCTION_2000 @@ -441,7 +512,7 @@ class cmd_domain_provision(Command): try: result = provision(self.logger, session, smbconf=smbconf, targetdir=targetdir, - samdb_fill=samdb_fill, realm=realm, domain=domain, + samdb_fill=samdb_fill, realm=krbrealm, domain=domain, domainguid=domain_guid, domainsid=domain_sid, hostname=host_name, hostip=host_ip, hostip6=host_ip6, -- 1.7.10.4