summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2010-04-08 18:57:09 +0200
committerJelmer Vernooij <jelmer@samba.org>2010-04-08 23:20:36 +0200
commitd7a46ee129c455cba95126e9c0f409522127894e (patch)
treef8355e158e7b679320509ec6a2c459d45e0581b0 /source4
parentbe4b68817544b87d12a1dcd7d8b5c5d778872418 (diff)
downloadsamba-d7a46ee129c455cba95126e9c0f409522127894e.tar.gz
samba-d7a46ee129c455cba95126e9c0f409522127894e.tar.bz2
samba-d7a46ee129c455cba95126e9c0f409522127894e.zip
s4-python: Simplify code, improve formatting.
Diffstat (limited to 'source4')
-rwxr-xr-xsource4/scripting/bin/upgradeprovision42
-rw-r--r--source4/scripting/python/samba/netcmd/domainlevel.py2
-rw-r--r--source4/scripting/python/samba/netcmd/dsacl.py21
-rw-r--r--source4/scripting/python/samba/provision.py89
-rw-r--r--source4/scripting/python/samba/provisionbackend.py190
-rw-r--r--source4/scripting/python/samba/provisionexceptions.py38
-rwxr-xr-xsource4/scripting/python/samba/upgradehelpers.py48
-rwxr-xr-xsource4/setup/provision13
8 files changed, 208 insertions, 235 deletions
diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision
index 234152b002..a900728ed4 100755
--- a/source4/scripting/bin/upgradeprovision
+++ b/source4/scripting/bin/upgradeprovision
@@ -40,8 +40,7 @@ from ldb import SCOPE_SUBTREE, SCOPE_BASE, \
MessageElement, Message, Dn
from samba import param
from samba.misc import messageEltFlagToString
-from samba.provision import find_setup_dir, get_domain_descriptor, get_config_descriptor, secretsdb_self_join,set_gpo_acl,getpolicypath,create_gpo_struct
-from samba.provisionexceptions import ProvisioningError
+from samba.provision import find_setup_dir, get_domain_descriptor, get_config_descriptor, secretsdb_self_join,set_gpo_acl,getpolicypath,create_gpo_struct, ProvisioningError
from samba.schema import get_linked_attributes, Schema, get_schema_descriptor
from samba.dcerpc import security
from samba.ndr import ndr_unpack
@@ -321,16 +320,22 @@ def handle_special_case(att, delta, new, old, ischema):
def update_secrets(newpaths, paths, creds, session):
"""Update secrets.ldb
- :param newpaths: a list of paths for different provision objects from the reference provision
- :param paths: a list of paths for different provision objects from the upgraded provision
+ :param newpaths: a list of paths for different provision objects from the
+ reference provision
+ :param paths: a list of paths for different provision objects from the
+ upgraded provision
:param creds: credential for the authentification
:param session: session for connexion"""
message(SIMPLE,"update secrets.ldb")
- newsecrets_ldb = Ldb(newpaths.secrets, session_info=session, credentials=creds,lp=lp)
- secrets_ldb = Ldb(paths.secrets, session_info=session, credentials=creds,lp=lp, options=["modules:samba_secrets"])
- reference = newsecrets_ldb.search(expression="dn=@MODULES",base="", scope=SCOPE_SUBTREE)
- current = secrets_ldb.search(expression="dn=@MODULES",base="", scope=SCOPE_SUBTREE)
+ newsecrets_ldb = Ldb(newpaths.secrets, session_info=session,
+ credentials=creds,lp=lp)
+ secrets_ldb = Ldb(paths.secrets, session_info=session,
+ credentials=creds,lp=lp, options=["modules:samba_secrets"])
+ reference = newsecrets_ldb.search(expression="dn=@MODULES",base="",
+ scope=SCOPE_SUBTREE)
+ current = secrets_ldb.search(expression="dn=@MODULES",base="",
+ scope=SCOPE_SUBTREE)
delta = secrets_ldb.msg_diff(current[0],reference[0])
delta.dn = current[0].dn
secrets_ldb.modify(delta)
@@ -449,7 +454,8 @@ def handle_special_add(sam_ldb,dn,names):
message(CHANGE,"Existing object %s must be replaced by %s, removing old object"%(dntoremove,str(dn)))
sam_ldb.delete(res[0]["dn"])
-def check_dn_nottobecreated(hash,index,listdn):
+
+def check_dn_nottobecreated(hash, index, listdn):
"""Check if one of the DN present in the list has a creation order greater than the current.
Hash is indexed by dn to be created, with each key is associated the creation order
@@ -780,22 +786,22 @@ def update_basesamdb(newpaths, paths, names):
shutil.copy(newpaths.samdb,paths.samdb)
message(SIMPLE,"Update partitions filename if needed")
- schemaldb=os.path.join(paths.private_dir,"schema.ldb")
- configldb=os.path.join(paths.private_dir,"configuration.ldb")
- usersldb=os.path.join(paths.private_dir,"users.ldb")
- samldbdir=os.path.join(paths.private_dir,"sam.ldb.d")
+ schemaldb = os.path.join(paths.private_dir, "schema.ldb")
+ configldb = os.path.join(paths.private_dir, "configuration.ldb")
+ usersldb = os.path.join(paths.private_dir, "users.ldb")
+ samldbdir = os.path.join(paths.private_dir, "sam.ldb.d")
if not os.path.isdir(samldbdir):
os.mkdir(samldbdir)
os.chmod(samldbdir,0700)
if os.path.isfile(schemaldb):
- shutil.copy(schemaldb, os.path.join(samldbdir, "%s.ldb"%str(names.schemadn).upper()))
+ shutil.copy(schemaldb, os.path.join(samldbdir, "%s.ldb" % str(names.schemadn).upper()))
os.remove(schemaldb)
if os.path.isfile(usersldb):
- shutil.copy(usersldb, os.path.join(samldbdir, "%s.ldb"%str(names.rootdn).upper()))
+ shutil.copy(usersldb, os.path.join(samldbdir, "%s.ldb" % str(names.rootdn).upper()))
os.remove(usersldb)
if os.path.isfile(configldb):
- shutil.copy(configldb, os.path.join(samldbdir, "%s.ldb"%str(names.configdn).upper()))
+ shutil.copy(configldb, os.path.join(samldbdir, "%s.ldb" % str(names.configdn).upper()))
os.remove(configldb)
@@ -834,7 +840,8 @@ def update_machine_account_password(paths, creds, session, names):
:param session: Session for connexion
:param names: List of key provision parameters"""
- secrets_ldb = Ldb(paths.secrets, session_info=session, credentials=creds,lp=lp)
+ secrets_ldb = Ldb(paths.secrets, session_info=session,
+ credentials=creds,lp=lp)
secrets_ldb.transaction_start()
secrets_msg = secrets_ldb.search(expression=("samAccountName=%s$" % names.netbiosname), attrs=["secureChannelType"])
sam_ldb = Ldb(paths.samdb, session_info=session, credentials=creds,lp=lp)
@@ -885,6 +892,7 @@ def update_gpo(paths,creds,session,names):
set_gpo_acl(paths.sysvol, names.dnsdomain, names.domainsid,
names.domaindn, samdb, lp)
+
def updateOEMInfo(paths, creds, session,names):
sam_ldb = Ldb(paths.samdb, session_info=session, credentials=creds, lp=lp,
options=["modules:samba_dsdb"])
diff --git a/source4/scripting/python/samba/netcmd/domainlevel.py b/source4/scripting/python/samba/netcmd/domainlevel.py
index c97ed7bad6..1874191e1f 100644
--- a/source4/scripting/python/samba/netcmd/domainlevel.py
+++ b/source4/scripting/python/samba/netcmd/domainlevel.py
@@ -114,7 +114,7 @@ class cmd_domainlevel(Command):
raise CommandError("Could not retrieve the actual domain, forest level and/or lowest DC function level!")
if subcommand == "show":
- self.message("Domain and forest function level for domain '" + domain_dn + "'")
+ self.message("Domain and forest function level for domain '%s'" % domain_dn)
if level_forest < DS_DOMAIN_FUNCTION_2003:
self.message("\nATTENTION: You run SAMBA 4 on a forest function level lower than Windows 2003 (Native). This isn't supported! Please raise!")
if level_domain < DS_DOMAIN_FUNCTION_2003:
diff --git a/source4/scripting/python/samba/netcmd/dsacl.py b/source4/scripting/python/samba/netcmd/dsacl.py
index 58fb9c611a..17982b8119 100644
--- a/source4/scripting/python/samba/netcmd/dsacl.py
+++ b/source4/scripting/python/samba/netcmd/dsacl.py
@@ -57,7 +57,8 @@ class cmd_ds_acl_set(Command):
}
takes_options = [
- Option("--host", help="LDB URL for database or target server", type=str),
+ Option("--host", help="LDB URL for database or target server",
+ type=str),
Option("--car", type="choice", choices=["change-rid",
"change-pdc",
"change-infrastructure",
@@ -74,12 +75,15 @@ class cmd_ds_acl_set(Command):
help=car_help),
Option("--action", type="choice", choices=["allow", "deny"],
help="""Deny or allow access"""),
- Option("--objectdn", help="DN of the object whose SD to modify", type="string"),
- Option("--trusteedn", help="DN of the entity that gets access", type="string"),
+ Option("--objectdn", help="DN of the object whose SD to modify",
+ type="string"),
+ Option("--trusteedn", help="DN of the entity that gets access",
+ type="string"),
]
def find_trustee_sid(self, samdb, trusteedn):
- res = samdb.search(base=trusteedn, expression="(objectClass=*)", scope=SCOPE_BASE)
+ res = samdb.search(base=trusteedn, expression="(objectClass=*)",
+ scope=SCOPE_BASE)
assert(len(res) == 1)
return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
@@ -93,18 +97,20 @@ class cmd_ds_acl_set(Command):
samdb.modify(m)
def read_descriptor(self, samdb, object_dn):
- res = samdb.search(base=object_dn, scope=SCOPE_BASE, attrs=["nTSecurityDescriptor"])
+ res = samdb.search(base=object_dn, scope=SCOPE_BASE,
+ attrs=["nTSecurityDescriptor"])
# we should theoretically always have an SD
assert(len(res) == 1)
desc = res[0]["nTSecurityDescriptor"][0]
return ndr_unpack(security.descriptor, desc)
def get_domain_sid(self, samdb):
- res = samdb.search(base=SamDB.domain_dn(samdb), expression="(objectClass=*)", scope=SCOPE_BASE)
+ res = samdb.search(base=SamDB.domain_dn(samdb),
+ expression="(objectClass=*)", scope=SCOPE_BASE)
return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
- #add new ace explicitly
def add_ace(self, samdb, object_dn, new_ace):
+ """Add new ace explicitly."""
desc = self.read_descriptor(samdb, object_dn)
desc_sddl = desc.as_sddl(self.get_domain_sid(samdb))
#TODO add bindings for descriptor manipulation and get rid of this
@@ -164,6 +170,7 @@ class cmd_ds_acl_set(Command):
self.add_ace(samdb, objectdn, new_ace)
self.print_new_acl(samdb, objectdn)
+
class cmd_ds_acl(SuperCommand):
"""DS ACLs manipulation"""
diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py
index 4bef0ed7d4..eb89ee9f3a 100644
--- a/source4/scripting/python/samba/provision.py
+++ b/source4/scripting/python/samba/provision.py
@@ -2,7 +2,7 @@
# Unix SMB/CIFS implementation.
# backend code for provisioning a Samba4 server
-# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008-2009
# Copyright (C) Oliver Liebel <oliver@itc.li> 2008-2009
#
@@ -53,7 +53,6 @@ from samba.schema import Schema
from samba.samdb import SamDB
from ms_display_specifiers import read_ms_ldif
from samba.provisionbackend import LDBBackend, ExistingBackend, FDSBackend, OpenLDAPBackend
-from provisionexceptions import ProvisioningError, InvalidNetbiosName
__docformat__ = "restructuredText"
@@ -150,9 +149,8 @@ def get_domain_descriptor(domain_sid):
DEFAULTSITE = "Default-First-Site-Name"
-# Exception classes
-
class ProvisionPaths(object):
+
def __init__(self):
self.shareconf = None
self.hklm = None
@@ -172,6 +170,7 @@ class ProvisionPaths(object):
class ProvisionNames(object):
+
def __init__(self):
self.rootdn = None
self.domaindn = None
@@ -188,12 +187,14 @@ class ProvisionNames(object):
class ProvisionResult(object):
+
def __init__(self):
self.paths = None
self.domaindn = None
self.lp = None
self.samdb = None
+
def check_install(lp, session_info, credentials):
"""Check whether the current install seems ok.
@@ -203,9 +204,9 @@ def check_install(lp, session_info, credentials):
"""
if lp.get("realm") == "":
raise Exception("Realm empty")
- ldb = Ldb(lp.get("sam database"), session_info=session_info,
+ samdb = Ldb(lp.get("sam database"), session_info=session_info,
credentials=credentials, lp=lp)
- if len(ldb.search("(cn=Administrator)")) != 1:
+ if len(samdb.search("(cn=Administrator)")) != 1:
raise ProvisioningError("No administrator account found")
@@ -825,6 +826,7 @@ def create_gpo_struct(policy_path):
os.makedirs(os.path.join(policy_path, "MACHINE"), 0755)
os.makedirs(os.path.join(policy_path, "USER"), 0755)
+
def setup_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid)
create_gpo_struct(policy_path)
@@ -832,6 +834,7 @@ def setup_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid_dc)
create_gpo_struct(policy_path)
+
def setup_samdb(path, setup_path, session_info, provision_backend, lp,
names, message,
domainsid, domainguid, policyguid, policyguid_dc,
@@ -851,7 +854,8 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
if dom_for_fun_level is None:
dom_for_fun_level = DS_DOMAIN_FUNCTION_2003
if dom_for_fun_level < DS_DOMAIN_FUNCTION_2003:
- message("You want to run SAMBA 4 on a domain and forest function level lower than Windows 2003 (Native). This is not recommended")
+ message("You want to run SAMBA 4 on a domain and forest function level"
+ " lower than Windows 2003 (Native). This is not recommended")
if dom_for_fun_level > domainControllerFunctionality:
raise ProvisioningError("You want to run SAMBA 4 on a domain and forest function level which itself is higher than its actual DC function level (2008). This won't work!")
@@ -864,7 +868,7 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
provision_backend=provision_backend, session_info=session_info,
names=names, serverrole=serverrole, schema=schema)
- if (schema == None):
+ if schema is None:
schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn)
# Load the database, but importantly, use Ldb not SamDB as we don't want to
@@ -1033,7 +1037,6 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
names.ntdsguid = samdb.searchone(basedn=ntds_dn,
attribute="objectGUID", expression="", scope=ldb.SCOPE_BASE)
assert isinstance(names.ntdsguid, str)
-
except:
samdb.transaction_cancel()
raise
@@ -1066,9 +1069,11 @@ def set_gpo_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp):
attrs=["cn","nTSecurityDescriptor"],
expression="", scope=ldb.SCOPE_ONELEVEL)
for policy in res:
- acl = ndr_unpack(security.descriptor,str(policy["nTSecurityDescriptor"])).as_sddl()
+ acl = ndr_unpack(security.descriptor,
+ str(policy["nTSecurityDescriptor"])).as_sddl()
policy_path = getpolicypath(sysvol,dnsdomain,str(policy["cn"]))
- set_dir_acl(policy_path,dsacl2fsacl(acl,str(domainsid)),lp,str(domainsid))
+ set_dir_acl(policy_path, dsacl2fsacl(acl, str(domainsid)), lp,
+ str(domainsid))
def setsysvolacl(samdb, netlogon, sysvol, gid, domainsid, dnsdomain, domaindn,
lp):
@@ -1177,8 +1182,8 @@ def provision(setup_dir, message, session_info,
data = open(smbconf, 'r').read()
data = data.lstrip()
if data is None or data == "":
- make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
- targetdir, sid_generator, useeadb)
+ make_smbconf(smbconf, setup_path, hostname, domain, realm,
+ serverrole, targetdir, sid_generator, useeadb)
else:
make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
targetdir, sid_generator, useeadb)
@@ -1229,7 +1234,8 @@ def provision(setup_dir, message, session_info,
ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
- schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn)
+ schema = Schema(setup_path, domainsid, schemadn=names.schemadn,
+ serverdn=names.serverdn)
if backend_type == "ldb":
provision_backend = LDBBackend(backend_type,
@@ -1275,7 +1281,7 @@ def provision(setup_dir, message, session_info,
ol_mmr_urls=ol_mmr_urls,
nosync=nosync)
else:
- raise ProvisioningError("Unknown LDAP backend type selected")
+ raise ValueError("Unknown LDAP backend type selected")
provision_backend.init()
provision_backend.start()
@@ -1290,8 +1296,8 @@ def provision(setup_dir, message, session_info,
message("Setting up secrets.ldb")
secrets_ldb = setup_secretsdb(paths.secrets, setup_path,
- session_info=session_info,
- backend_credentials=provision_backend.secrets_credentials, lp=lp)
+ session_info=session_info,
+ backend_credentials=provision_backend.secrets_credentials, lp=lp)
message("Setting up the registry")
setup_registry(paths.hklm, setup_path, session_info,
@@ -1322,15 +1328,15 @@ def provision(setup_dir, message, session_info,
if paths.netlogon is None:
message("Existing smb.conf does not have a [netlogon] share, but you are configuring a DC.")
message("Please either remove %s or see the template at %s" %
- ( paths.smbconf, setup_path("provision.smb.conf.dc")))
- assert(paths.netlogon is not None)
+ (paths.smbconf, setup_path("provision.smb.conf.dc")))
+ assert paths.netlogon is not None
if paths.sysvol is None:
- message("Existing smb.conf does not have a [sysvol] share, but you are configuring a DC.")
+ message("Existing smb.conf does not have a [sysvol] share, but you"
+ " are configuring a DC.")
message("Please either remove %s or see the template at %s" %
(paths.smbconf, setup_path("provision.smb.conf.dc")))
- assert(paths.sysvol is not None)
-
+ assert paths.sysvol is not None
if not os.path.isdir(paths.netlogon):
os.makedirs(paths.netlogon, 0755)
@@ -1342,8 +1348,9 @@ def provision(setup_dir, message, session_info,
if serverrole == "domain controller":
# Set up group policies (domain policy and domain controller policy)
- setup_gpo(paths.sysvol,names.dnsdomain,policyguid,policyguid_dc)
- setsysvolacl(samdb,paths.netlogon,paths.sysvol,wheel_gid,domainsid,names.dnsdomain,names.domaindn,lp)
+ setup_gpo(paths.sysvol, names.dnsdomain, policyguid, policyguid_dc)
+ setsysvolacl(samdb, paths.netlogon, paths.sysvol, wheel_gid,
+ domainsid, names.dnsdomain, names.domaindn, lp)
message("Setting up sam.ldb rootDSE marking as synchronized")
setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"))
@@ -1368,11 +1375,10 @@ def provision(setup_dir, message, session_info,
# Only make a zone file on the first DC, it should be replicated
# with DNS replication
- create_zone_file(lp, message, paths, targetdir, setup_path, dnsdomain=names.dnsdomain,
- hostip=hostip,
- hostip6=hostip6, hostname=names.hostname,
- realm=names.realm,
- domainguid=domainguid, ntdsguid=names.ntdsguid)
+ create_zone_file(lp, message, paths, targetdir, setup_path,
+ dnsdomain=names.dnsdomain, hostip=hostip, hostip6=hostip6,
+ hostname=names.hostname, realm=names.realm,
+ domainguid=domainguid, ntdsguid=names.ntdsguid)
create_named_conf(paths, setup_path, realm=names.realm,
dnsdomain=names.dnsdomain, private_dir=paths.private_dir)
@@ -1381,12 +1387,14 @@ def provision(setup_dir, message, session_info,
dnsdomain=names.dnsdomain, private_dir=paths.private_dir,
keytab_name=paths.dns_keytab)
message("See %s for an example configuration include file for BIND" % paths.namedconf)
- message("and %s for further documentation required for secure DNS updates" % paths.namedtxt)
+ message("and %s for further documentation required for secure DNS "
+ "updates" % paths.namedtxt)
create_krb5_conf(paths.krb5conf, setup_path,
dnsdomain=names.dnsdomain, hostname=names.hostname,
realm=names.realm)
- message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf)
+ message("A Kerberos configuration suitable for Samba 4 has been "
+ "generated at %s" % paths.krb5conf)
if serverrole == "domain controller":
create_dns_update_list(lp, message, paths, setup_path)
@@ -1407,7 +1415,8 @@ def provision(setup_dir, message, session_info,
os.chmod(dns_keytab_path, 0640)
os.chown(dns_keytab_path, -1, paths.bind_gid)
except OSError:
- message("Failed to chown %s to bind gid %u" % (dns_keytab_path, paths.bind_gid))
+ message("Failed to chown %s to bind gid %u" % (dns_keytab_path,
+ paths.bind_gid))
message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
@@ -1443,7 +1452,6 @@ def provision(setup_dir, message, session_info,
return result
-
def provision_become_dc(setup_dir=None,
smbconf=None, targetdir=None, realm=None,
rootdn=None, domaindn=None, schemadn=None,
@@ -1622,7 +1630,6 @@ def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
:param hostname: Local hostname
:param realm: Realm name
"""
-
setup_file(setup_path("krb5.conf"), path, {
"DNSDOMAIN": dnsdomain,
"HOSTNAME": hostname,
@@ -1630,3 +1637,17 @@ def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
})
+class ProvisioningError(Exception):
+ """A generic provision error."""
+
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return "ProvisioningError: " + self.value
+
+
+class InvalidNetbiosName(Exception):
+ """A specified name was not a valid NetBIOS name."""
+ def __init__(self, name):
+ super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
diff --git a/source4/scripting/python/samba/provisionbackend.py b/source4/scripting/python/samba/provisionbackend.py
index 479d965f27..e5d4d8e1b1 100644
--- a/source4/scripting/python/samba/provisionbackend.py
+++ b/source4/scripting/python/samba/provisionbackend.py
@@ -26,6 +26,7 @@
"""Functions for setting up a Samba configuration (LDB and LDAP backends)."""
from base64 import b64encode
+import errno
import ldb
import os
import sys
@@ -40,11 +41,21 @@ from ldb import SCOPE_BASE, SCOPE_ONELEVEL, LdbError, timestring
from samba import Ldb, read_and_sub_file, setup_file
from samba.credentials import Credentials, DONT_USE_KERBEROS
from samba.schema import Schema
-from samba.provisionexceptions import ProvisioningError
+
+
+class SlapdAlreadyRunning(Exception):
+
+ def __init__(self, uri):
+ self.ldapi_uri = uri
+ super(SlapdAlreadyRunning, self).__init__("Another slapd Instance "
+ "seems already running on this host, listening to %s." %
+ self.ldapi_uri)
+
class ProvisionBackend(object):
- def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
- names=None, message=None):
+
+ def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+ credentials=None, names=None, message=None):
"""Provision a backend for samba4"""
self.paths = paths
self.setup_path = setup_path
@@ -72,15 +83,6 @@ class ProvisionBackend(object):
class LDBBackend(ProvisionBackend):
- def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
- names=None, message=None):
-
- super(LDBBackend, self).__init__(
- backend_type=backend_type,
- paths=paths, setup_path=setup_path,
- lp=lp, credentials=credentials,
- names=names,
- message=message)
def init(self):
self.credentials = None
@@ -91,49 +93,40 @@ class LDBBackend(ProvisionBackend):
class ExistingBackend(ProvisionBackend):
- def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
- names=None, message=None,
- ldapi_uri=None):
- super(ExistingBackend, self).__init__(
- backend_type=backend_type,
- paths=paths, setup_path=setup_path,
- lp=lp, credentials=credentials,
- names=names,
- message=message)
+ def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+ credentials=None, names=None, message=None, ldapi_uri=None):
+
+ super(ExistingBackend, self).__init__(backend_type=backend_type,
+ paths=paths, setup_path=setup_path, lp=lp,
+ credentials=credentials, names=names, message=message)
self.ldapi_uri = ldapi_uri
def init(self):
- #Check to see that this 'existing' LDAP backend in fact exists
+ # Check to see that this 'existing' LDAP backend in fact exists
ldapi_db = Ldb(self.ldapi_uri, credentials=self.credentials)
ldapi_db.search(base="", scope=SCOPE_BASE,
- expression="(objectClass=OpenLDAProotDSE)")
+ expression="(objectClass=OpenLDAProotDSE)")
- # If we have got here, then we must have a valid connection to the LDAP server, with valid credentials supplied
- # This caused them to be set into the long-term database later in the script.
+ # If we have got here, then we must have a valid connection to the LDAP
+ # server, with valid credentials supplied This caused them to be set
+ # into the long-term database later in the script.
self.secrets_credentials = self.credentials
- self.ldap_backend_type = "openldap" #For now, assume existing backends at least emulate OpenLDAP
+ self.ldap_backend_type = "openldap" # For now, assume existing backends at least emulate OpenLDAP
class LDAPBackend(ProvisionBackend):
- def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
- names=None, message=None,
- domainsid=None,
- schema=None,
- hostname=None,
- ldapadminpass=None,
- slapd_path=None,
- ldap_backend_extra_port=None,
- ldap_dryrun_mode=False):
-
- super(LDAPBackend, self).__init__(
- backend_type=backend_type,
- paths=paths, setup_path=setup_path,
- lp=lp, credentials=credentials,
- names=names,
- message=message)
+
+ def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+ credentials=None, names=None, message=None, domainsid=None,
+ schema=None, hostname=None, ldapadminpass=None, slapd_path=None,
+ ldap_backend_extra_port=None, ldap_dryrun_mode=False):
+
+ super(LDAPBackend, self).__init__(backend_type=backend_type,
+ paths=paths, setup_path=setup_path, lp=lp,
+ credentials=credentials, names=names, message=message)
self.domainsid = domainsid
self.schema = schema
@@ -156,23 +149,26 @@ class LDAPBackend(ProvisionBackend):
os.mkdir(self.ldapdir)
def init(self):
- # we will shortly start slapd with ldapi for final provisioning. first check with ldapsearch -> rootDSE via self.ldapi_uri
- # if another instance of slapd is already running
+ from samba.provision import ProvisioningError
+ # we will shortly start slapd with ldapi for final provisioning. first
+ # check with ldapsearch -> rootDSE via self.ldapi_uri if another
+ # instance of slapd is already running
try:
ldapi_db = Ldb(self.ldapi_uri)
ldapi_db.search(base="", scope=SCOPE_BASE,
expression="(objectClass=OpenLDAProotDSE)")
try:
f = open(self.slapd_pid, "r")
+ except IOError, err:
+ if err != errno.ENOENT:
+ raise
+ else:
p = f.read()
f.close()
self.message("Check for slapd Process with PID: " + str(p) + " and terminate it manually.")
- except:
- pass
-
- raise ProvisioningError("Warning: Another slapd Instance seems already running on this host, listening to " + self.ldapi_uri + ". Please shut it down before you continue. ")
-
+ raise SlapdAlreadyRunning(self.ldapi_uri)
except LdbError:
+ # XXX: We should never be catching all Ldb errors
pass
# Try to print helpful messages when the user has not specified the path to slapd
@@ -216,13 +212,15 @@ class LDAPBackend(ProvisionBackend):
pass
def start(self):
+ from samba.provision import ProvisioningError
self.slapd_command_escaped = "\'" + "\' \'".join(self.slapd_command) + "\'"
- open(self.ldapdir + "/ldap_backend_startup.sh", 'w').write("#!/bin/sh\n" + self.slapd_command_escaped + "\n")
+ open(os.path.join(self.ldapdir, "ldap_backend_startup.sh"), 'w').write("#!/bin/sh\n" + self.slapd_command_escaped + "\n")
# Now start the slapd, so we can provision onto it. We keep the
# subprocess context around, to kill this off at the successful
# end of the script
- self.slapd = subprocess.Popen(self.slapd_provision_command, close_fds=True, shell=False)
+ self.slapd = subprocess.Popen(self.slapd_provision_command,
+ close_fds=True, shell=False)
while self.slapd.poll() is None:
# Wait until the socket appears
@@ -253,29 +251,18 @@ class LDAPBackend(ProvisionBackend):
class OpenLDAPBackend(LDAPBackend):
- def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
- names=None, message=None,
- domainsid=None,
- schema=None,
- hostname=None,
- ldapadminpass=None,
- slapd_path=None,
- ldap_backend_extra_port=None,
- ldap_dryrun_mode=False,
- ol_mmr_urls=None,
- nosync=False):
-
- super(OpenLDAPBackend, self).__init__(
- backend_type=backend_type,
- paths=paths, setup_path=setup_path,
- lp=lp, credentials=credentials,
- names=names,
- message=message,
- domainsid=domainsid,
- schema=schema,
- hostname=hostname,
- ldapadminpass=ldapadminpass,
- slapd_path=slapd_path,
+
+ def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+ credentials=None, names=None, message=None, domainsid=None,
+ schema=None, hostname=None, ldapadminpass=None, slapd_path=None,
+ ldap_backend_extra_port=None, ldap_dryrun_mode=False,
+ ol_mmr_urls=None, nosync=False):
+
+ super(OpenLDAPBackend, self).__init__( backend_type=backend_type,
+ paths=paths, setup_path=setup_path, lp=lp,
+ credentials=credentials, names=names, message=message,
+ domainsid=domainsid, schema=schema, hostname=hostname,
+ ldapadminpass=ldapadminpass, slapd_path=slapd_path,
ldap_backend_extra_port=ldap_backend_extra_port,
ldap_dryrun_mode=ldap_dryrun_mode)
@@ -290,11 +277,8 @@ class OpenLDAPBackend(LDAPBackend):
self.olcdir = os.path.join(self.ldapdir, "slapd.d")
self.olcseedldif = os.path.join(self.ldapdir, "olc_seed.ldif")
- self.schema = Schema(
- self.setup_path,
- self.domainsid,
- schemadn=self.names.schemadn,
- serverdn=self.names.serverdn,
+ self.schema = Schema(self.setup_path, self.domainsid,
+ schemadn=self.names.schemadn, serverdn=self.names.serverdn,
files=[setup_path("schema_samba4.ldif")])
def setup_db_config(self, dbdir):
@@ -307,10 +291,11 @@ class OpenLDAPBackend(LDAPBackend):
if not os.path.isdir(os.path.join(dbdir, "tmp")):
os.makedirs(os.path.join(dbdir, "tmp"), 0700)
- setup_file(self.setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"),
- {"LDAPDBDIR": dbdir})
+ setup_file(self.setup_path("DB_CONFIG"),
+ os.path.join(dbdir, "DB_CONFIG"), {"LDAPDBDIR": dbdir})
def provision(self):
+ from samba.provision import ProvisioningError
# Wipe the directories so we can start
shutil.rmtree(os.path.join(self.ldapdir, "db"), True)
@@ -350,7 +335,6 @@ class OpenLDAPBackend(LDAPBackend):
mmr_syncrepl_schema_config = ""
mmr_syncrepl_config_config = ""
mmr_syncrepl_user_config = ""
-
if self.ol_mmr_urls is not None:
# For now, make these equal
@@ -485,7 +469,8 @@ class OpenLDAPBackend(LDAPBackend):
if self.ol_mmr_urls is None:
server_port_string = "ldap://0.0.0.0:%d" % self.ldap_backend_extra_port
else:
- server_port_string = "ldap://" + self.names.hostname + "." + self.names.dnsdomain +":%d" % self.ldap_backend_extra_port
+ server_port_string = "ldap://%s.%s:%d" (self.names.hostname,
+ self.names.dnsdomain, self.ldap_backend_extra_port)
else:
server_port_string = ""
@@ -537,29 +522,18 @@ class OpenLDAPBackend(LDAPBackend):
class FDSBackend(LDAPBackend):
- def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
- names=None, message=None,
- domainsid=None,
- schema=None,
- hostname=None,
- ldapadminpass=None,
- slapd_path=None,
- ldap_backend_extra_port=None,
- ldap_dryrun_mode=False,
- root=None,
- setup_ds_path=None):
-
- super(FDSBackend, self).__init__(
- backend_type=backend_type,
- paths=paths, setup_path=setup_path,
- lp=lp, credentials=credentials,
- names=names,
- message=message,
- domainsid=domainsid,
- schema=schema,
- hostname=hostname,
- ldapadminpass=ldapadminpass,
- slapd_path=slapd_path,
+
+ def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+ credentials=None, names=None, message=None, domainsid=None,
+ schema=None, hostname=None, ldapadminpass=None, slapd_path=None,
+ ldap_backend_extra_port=None, ldap_dryrun_mode=False, root=None,
+ setup_ds_path=None):
+
+ super(FDSBackend, self).__init__(backend_type=backend_type,
+ paths=paths, setup_path=setup_path, lp=lp,
+ credentials=credentials, names=names, message=message,
+ domainsid=domainsid, schema=schema, hostname=hostname,
+ ldapadminpass=ldapadminpass, slapd_path=slapd_path,
ldap_backend_extra_port=ldap_backend_extra_port,
ldap_dryrun_mode=ldap_dryrun_mode)
@@ -600,6 +574,7 @@ class FDSBackend(LDAPBackend):
prefixmap=["1000:1.3.6.1.4.1.7165.2.1", "1001:1.3.6.1.4.1.7165.2.2"])
def provision(self):
+ from samba.provision import ProvisioningError
if self.ldap_backend_extra_port is not None:
serverport = "ServerPort=%d" % self.ldap_backend_extra_port
else:
@@ -616,7 +591,8 @@ class FDSBackend(LDAPBackend):
"LDAPMANAGERPASS": self.ldapadminpass,
"SERVERPORT": serverport})
- setup_file(self.setup_path("fedorads-partitions.ldif"), self.partitions_ldif,
+ setup_file(self.setup_path("fedorads-partitions.ldif"),
+ self.partitions_ldif,
{"CONFIGDN": self.names.configdn,
"SCHEMADN": self.names.schemadn,
"SAMBADN": self.sambadn,
diff --git a/source4/scripting/python/samba/provisionexceptions.py b/source4/scripting/python/samba/provisionexceptions.py
deleted file mode 100644
index 6159a02e95..0000000000
--- a/source4/scripting/python/samba/provisionexceptions.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Unix SMB/CIFS implementation.
-# backend code for provisioning a Samba4 server
-
-# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
-# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008-2009
-# Copyright (C) Oliver Liebel <oliver@itc.li> 2008-2009
-#
-# Based on the original in EJS:
-# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
-#
-# 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/>.
-#
-
-class ProvisioningError(Exception):
- """A generic provision error."""
- def __init__(self, value):
- self.value = value
- def __str__(self):
- return "ProvisioningError: " + self.value
-
-class InvalidNetbiosName(ProvisioningError):
- """A specified name was not a valid NetBIOS name."""
- def __init__(self, name):
- super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
-
-
diff --git a/source4/scripting/python/samba/upgradehelpers.py b/source4/scripting/python/samba/upgradehelpers.py
index 25d1d7fe29..3da739b139 100755
--- a/source4/scripting/python/samba/upgradehelpers.py
+++ b/source4/scripting/python/samba/upgradehelpers.py
@@ -31,8 +31,8 @@ from samba import Ldb
from samba.dsdb import DS_DOMAIN_FUNCTION_2000
from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE
import ldb
-from samba.provision import ProvisionNames, provision_paths_from_lp, FILL_FULL, provision
-from samba.provisionexceptions import ProvisioningError
+from samba.provision import (ProvisionNames, provision_paths_from_lp,
+ FILL_FULL, provision, ProvisioningError)
from samba.dcerpc import misc, security
from samba.ndr import ndr_unpack
@@ -61,7 +61,8 @@ def get_paths(param, targetdir=None, smbconf=None):
return paths
-def find_provision_key_parameters(param, credentials, session_info, paths, smbconf):
+def find_provision_key_parameters(param, credentials, session_info, paths,
+ smbconf):
"""Get key provision parameters (realm, domain, ...) from a given provision
:param param: Param object
@@ -82,10 +83,10 @@ def find_provision_key_parameters(param, credentials, session_info, paths, smbco
names.dnsdomain = names.realm
names.realm = string.upper(names.realm)
# netbiosname
- secrets_ldb = Ldb(paths.secrets, session_info=session_info, credentials=credentials,lp=lp, options=["modules:samba_secrets"])
+ secrets_ldb = Ldb(paths.secrets, session_info=session_info,
+ credentials=credentials,lp=lp, options=["modules:samba_secrets"])
# Get the netbiosname first (could be obtained from smb.conf in theory)
- attrs = ["sAMAccountName"]
- res = secrets_ldb.search(expression="(flatname=%s)"%names.domain,base="CN=Primary Domains", scope=SCOPE_SUBTREE, attrs=attrs)
+ res = secrets_ldb.search(expression="(flatname=%s)"%names.domain,base="CN=Primary Domains", scope=SCOPE_SUBTREE, attrs=["sAMAccountName"])
names.netbiosname = str(res[0]["sAMAccountName"]).replace("$","")
names.smbconf = smbconf
@@ -96,8 +97,7 @@ def find_provision_key_parameters(param, credentials, session_info, paths, smbco
# That's a bit simplistic but it's ok as long as we have only 3
# partitions
- attrs2 = ["defaultNamingContext", "schemaNamingContext","configurationNamingContext","rootDomainNamingContext"]
- current = samdb.search(expression="(objectClass=*)",base="", scope=SCOPE_BASE, attrs=attrs2)
+ current = samdb.search(expression="(objectClass=*)",base="", scope=SCOPE_BASE, attrs=["defaultNamingContext", "schemaNamingContext","configurationNamingContext","rootDomainNamingContext"])
names.configdn = current[0]["configurationNamingContext"]
configdn = str(names.configdn)
@@ -108,27 +108,28 @@ def find_provision_key_parameters(param, credentials, session_info, paths, smbco
names.domaindn=current[0]["defaultNamingContext"]
names.rootdn=current[0]["rootDomainNamingContext"]
# default site name
- attrs3 = ["cn"]
- res3= samdb.search(expression="(objectClass=*)",base="CN=Sites,"+configdn, scope=SCOPE_ONELEVEL, attrs=attrs3)
+ res3= samdb.search(expression="(objectClass=*)",base="CN=Sites,"+configdn, scope=SCOPE_ONELEVEL, attrs=["cn"])
names.sitename = str(res3[0]["cn"])
# dns hostname and server dn
- attrs4 = ["dNSHostName"]
res4= samdb.search(expression="(CN=%s)"%names.netbiosname,base="OU=Domain Controllers,"+basedn, \
- scope=SCOPE_ONELEVEL, attrs=attrs4)
+ scope=SCOPE_ONELEVEL, attrs=["dNSHostName"])
names.hostname = str(res4[0]["dNSHostName"]).replace("."+names.dnsdomain,"")
server_res = samdb.search(expression="serverReference=%s"%res4[0].dn, attrs=[], base=configdn)
names.serverdn = server_res[0].dn
# invocation id/objectguid
- res5 = samdb.search(expression="(objectClass=*)",base="CN=NTDS Settings,%s" % str(names.serverdn), scope=SCOPE_BASE, attrs=["invocationID","objectGUID"])
- names.invocation = str(ndr_unpack( misc.GUID,res5[0]["invocationId"][0]))
- names.ntdsguid = str(ndr_unpack( misc.GUID,res5[0]["objectGUID"][0]))
+ res5 = samdb.search(expression="(objectClass=*)",
+ base="CN=NTDS Settings,%s" % str(names.serverdn), scope=SCOPE_BASE,
+ attrs=["invocationID", "objectGUID"])
+ names.invocation = str(ndr_unpack(misc.GUID, res5[0]["invocationId"][0]))
+ names.ntdsguid = str(ndr_unpack(misc.GUID, res5[0]["objectGUID"][0]))
# domain guid/sid
- attrs6 = ["objectGUID", "objectSid","msDS-Behavior-Version" ]
- res6 = samdb.search(expression="(objectClass=*)",base=basedn, scope=SCOPE_BASE, attrs=attrs6)
+ res6 = samdb.search(expression="(objectClass=*)",base=basedn,
+ scope=SCOPE_BASE, attrs=["objectGUID",
+ "objectSid","msDS-Behavior-Version" ])
names.domainguid = str(ndr_unpack( misc.GUID,res6[0]["objectGUID"][0]))
names.domainsid = ndr_unpack( security.dom_sid,res6[0]["objectSid"][0])
if res6[0].get("msDS-Behavior-Version") == None or int(res6[0]["msDS-Behavior-Version"][0]) < DS_DOMAIN_FUNCTION_2000:
@@ -137,14 +138,12 @@ def find_provision_key_parameters(param, credentials, session_info, paths, smbco
names.domainlevel = int(res6[0]["msDS-Behavior-Version"][0])
# policy guid
- attrs7 = ["cn","displayName"]
res7 = samdb.search(expression="(displayName=Default Domain Policy)",base="CN=Policies,CN=System,"+basedn, \
- scope=SCOPE_ONELEVEL, attrs=attrs7)
+ scope=SCOPE_ONELEVEL, attrs=["cn","displayName"])
names.policyid = str(res7[0]["cn"]).replace("{","").replace("}","")
# dc policy guid
- attrs8 = ["cn","displayName"]
res8 = samdb.search(expression="(displayName=Default Domain Controllers Policy)",base="CN=Policies,CN=System,"+basedn, \
- scope=SCOPE_ONELEVEL, attrs=attrs8)
+ scope=SCOPE_ONELEVEL, attrs=["cn","displayName"])
if len(res8) == 1:
names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
else:
@@ -194,9 +193,12 @@ def newprovision(names,setup_dir,creds,session,smbconf,provdir,messagefunc):
def dn_sort(x,y):
- """Sorts two DNs in the lexicographical order it and put higher level DN before.
+ """Sorts two DNs in the lexicographical order it and put higher level DN
+ before.
+
+ So given the dns cn=bar,cn=foo and cn=foo the later will be return as
+ smaller
- So given the dns cn=bar,cn=foo and cn=foo the later will be return as smaller
:param x: First object to compare
:param y: Second object to compare
"""
diff --git a/source4/setup/provision b/source4/setup/provision
index bbd6298dc3..d0d35f807e 100755
--- a/source4/setup/provision
+++ b/source4/setup/provision
@@ -34,13 +34,12 @@ import samba.ntacls
from samba.credentials import DONT_USE_KERBEROS
from samba.auth import system_session
import samba.getopt as options
-from samba.provision import provision, FILL_FULL, FILL_NT4SYNC, FILL_DRS, find_setup_dir
+from samba.provision import provision, FILL_FULL, FILL_NT4SYNC, FILL_DRS, find_setup_dir, ProvisioningError
from samba.dsdb import (
DS_DOMAIN_FUNCTION_2003,
DS_DOMAIN_FUNCTION_2008,
DS_DOMAIN_FUNCTION_2008_R2,
)
-from samba.provisionexceptions import ProvisioningError
# how do we make this case insensitive??
@@ -118,7 +117,7 @@ parser.add_option("--slapd-path", type="string", metavar="SLAPD-PATH",
parser.add_option("--setup-ds-path", type="string", metavar="SETUP_DS-PATH",
help="Path to setup-ds.pl script for Fedora DS LDAP backend [e.g.:'/usr/sbin/setup-ds.pl']. Required for Setup with Fedora DS backend.")
parser.add_option("--nosync", help="Configure LDAP backend not to call fsync() (for performance in test environments)", action="store_true")
-parser.add_option("--use-xattrs", type="choice", choices=["yes","no","auto"], help="Define if we should use the native fs capabilities or a tdb file for storing attributes likes ntacl, auto tries to make an inteligent guess based on the user rights and system capabilities")
+parser.add_option("--use-xattrs", type="choice", choices=["yes","no","auto"], help="Define if we should use the native fs capabilities or a tdb file for storing attributes likes ntacl, auto tries to make an inteligent guess based on the user rights and system capabilities", default="auto")
parser.add_option("--ldap-dryrun-mode", help="Configure LDAP backend, but do not run any binaries and exit early. Used only for the test environment. DO NOT USE", action="store_true")
opts = parser.parse_args()[0]
@@ -210,16 +209,14 @@ if opts.blank:
elif opts.partitions_only:
samdb_fill = FILL_DRS
-if not opts.use_xattrs:
- opts.use_xattrs="auto"
-
eadb = True
if opts.use_xattrs == "yes":
eadb = False
elif opts.use_xattrs == "auto":
- file=tempfile.NamedTemporaryFile()
+ file = tempfile.NamedTemporaryFile()
try:
- samba.ntacls.setntacl(lp,file.name,"O:S-1-5-32G:S-1-5-32","S-1-5-32","native")
+ samba.ntacls.setntacl(lp, file.name,
+ "O:S-1-5-32G:S-1-5-32", "S-1-5-32", "native")
eadb = False
except:
if lp.get("posix:eadb") == None: