summaryrefslogtreecommitdiff
path: root/source4/scripting/python/samba/provision
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2012-12-28 15:37:14 +0100
committerAndrew Bartlett <abartlet@samba.org>2013-03-02 03:57:34 +0100
commit87afc3aee1ea593069322a49355dd8780d99e123 (patch)
tree8e1ea6678d93b53f21b34c4940b7d5a64e0f5020 /source4/scripting/python/samba/provision
parent80fce353e740c793619005ac102ab07fb5e7d280 (diff)
downloadsamba-87afc3aee1ea593069322a49355dd8780d99e123.tar.gz
samba-87afc3aee1ea593069322a49355dd8780d99e123.tar.bz2
samba-87afc3aee1ea593069322a49355dd8780d99e123.zip
Move python modules from source4/scripting/python/ to python/.
Reviewed-by: Andrew Bartlett <abartlet@samba.org> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Sat Mar 2 03:57:34 CET 2013 on sn-devel-104
Diffstat (limited to 'source4/scripting/python/samba/provision')
-rw-r--r--source4/scripting/python/samba/provision/__init__.py2279
-rw-r--r--source4/scripting/python/samba/provision/backend.py840
-rw-r--r--source4/scripting/python/samba/provision/common.py82
-rw-r--r--source4/scripting/python/samba/provision/descriptor.py359
-rw-r--r--source4/scripting/python/samba/provision/sambadns.py1135
5 files changed, 0 insertions, 4695 deletions
diff --git a/source4/scripting/python/samba/provision/__init__.py b/source4/scripting/python/samba/provision/__init__.py
deleted file mode 100644
index aac0ee36b2a..00000000000
--- a/source4/scripting/python/samba/provision/__init__.py
+++ /dev/null
@@ -1,2279 +0,0 @@
-# Unix SMB/CIFS implementation.
-# backend code for provisioning a Samba4 server
-
-# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2012
-# 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/>.
-#
-
-"""Functions for setting up a Samba configuration."""
-
-__docformat__ = "restructuredText"
-
-from base64 import b64encode
-import os
-import re
-import pwd
-import grp
-import logging
-import time
-import uuid
-import socket
-import urllib
-import string
-import tempfile
-
-import ldb
-
-from samba.auth import system_session, admin_session
-import samba
-from samba.samba3 import smbd, passdb
-from samba.samba3 import param as s3param
-from samba.dsdb import DS_DOMAIN_FUNCTION_2000
-from samba import (
- Ldb,
- MAX_NETBIOS_NAME_LEN,
- check_all_substituted,
- is_valid_netbios_char,
- setup_file,
- substitute_var,
- valid_netbios_name,
- version,
- )
-from samba.dcerpc import security, misc
-from samba.dcerpc.misc import (
- SEC_CHAN_BDC,
- SEC_CHAN_WKSTA,
- )
-from samba.dsdb import (
- DS_DOMAIN_FUNCTION_2003,
- DS_DOMAIN_FUNCTION_2008_R2,
- ENC_ALL_TYPES,
- )
-from samba.idmap import IDmapDB
-from samba.ms_display_specifiers import read_ms_ldif
-from samba.ntacls import setntacl, getntacl, dsacl2fsacl
-from samba.ndr import ndr_pack, ndr_unpack
-from samba.provision.backend import (
- ExistingBackend,
- FDSBackend,
- LDBBackend,
- OpenLDAPBackend,
- )
-from samba.provision.descriptor import (
- get_empty_descriptor,
- get_config_descriptor,
- get_config_partitions_descriptor,
- get_config_sites_descriptor,
- get_config_ntds_quotas_descriptor,
- get_config_delete_protected1_descriptor,
- get_config_delete_protected1wd_descriptor,
- get_config_delete_protected2_descriptor,
- get_domain_descriptor,
- get_domain_infrastructure_descriptor,
- get_domain_builtin_descriptor,
- get_domain_computers_descriptor,
- get_domain_users_descriptor,
- get_domain_controllers_descriptor,
- get_domain_delete_protected1_descriptor,
- get_domain_delete_protected2_descriptor,
- get_dns_partition_descriptor,
- get_dns_forest_microsoft_dns_descriptor,
- get_dns_domain_microsoft_dns_descriptor,
- )
-from samba.provision.common import (
- setup_path,
- setup_add_ldif,
- setup_modify_ldif,
- )
-from samba.provision.sambadns import (
- get_dnsadmins_sid,
- setup_ad_dns,
- create_dns_update_list
- )
-
-import samba.param
-import samba.registry
-from samba.schema import Schema
-from samba.samdb import SamDB
-from samba.dbchecker import dbcheck
-
-
-DEFAULT_POLICY_GUID = "31B2F340-016D-11D2-945F-00C04FB984F9"
-DEFAULT_DC_POLICY_GUID = "6AC1786C-016F-11D2-945F-00C04fB984F9"
-DEFAULTSITE = "Default-First-Site-Name"
-LAST_PROVISION_USN_ATTRIBUTE = "lastProvisionUSN"
-
-
-class ProvisionPaths(object):
-
- def __init__(self):
- self.shareconf = None
- self.hklm = None
- self.hkcu = None
- self.hkcr = None
- self.hku = None
- self.hkpd = None
- self.hkpt = None
- self.samdb = None
- self.idmapdb = None
- self.secrets = None
- self.keytab = None
- self.dns_keytab = None
- self.dns = None
- self.winsdb = None
- self.private_dir = None
- self.state_dir = None
-
-
-class ProvisionNames(object):
-
- def __init__(self):
- self.ncs = None
- self.rootdn = None
- self.domaindn = None
- self.configdn = None
- self.schemadn = None
- self.dnsforestdn = None
- self.dnsdomaindn = None
- self.ldapmanagerdn = None
- self.dnsdomain = None
- self.realm = None
- self.netbiosname = None
- self.domain = None
- self.hostname = None
- self.sitename = None
- self.smbconf = None
- self.name_map = {}
-
-
-def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
- lp):
- """Get key provision parameters (realm, domain, ...) from a given provision
-
- :param samdb: An LDB object connected to the sam.ldb file
- :param secretsdb: An LDB object connected to the secrets.ldb file
- :param idmapdb: An LDB object connected to the idmap.ldb file
- :param paths: A list of path to provision object
- :param smbconf: Path to the smb.conf file
- :param lp: A LoadParm object
- :return: A list of key provision parameters
- """
- names = ProvisionNames()
- names.adminpass = None
-
- # NT domain, kerberos realm, root dn, domain dn, domain dns name
- names.domain = string.upper(lp.get("workgroup"))
- names.realm = lp.get("realm")
- names.dnsdomain = names.realm.lower()
- basedn = samba.dn_from_dns_name(names.dnsdomain)
- names.realm = string.upper(names.realm)
- # netbiosname
- # Get the netbiosname first (could be obtained from smb.conf in theory)
- res = secretsdb.search(expression="(flatname=%s)" %
- names.domain,base="CN=Primary Domains",
- scope=ldb.SCOPE_SUBTREE, attrs=["sAMAccountName"])
- names.netbiosname = str(res[0]["sAMAccountName"]).replace("$","")
-
- names.smbconf = smbconf
-
- # That's a bit simplistic but it's ok as long as we have only 3
- # partitions
- current = samdb.search(expression="(objectClass=*)",
- base="", scope=ldb.SCOPE_BASE,
- attrs=["defaultNamingContext", "schemaNamingContext",
- "configurationNamingContext","rootDomainNamingContext",
- "namingContexts"])
-
- names.configdn = current[0]["configurationNamingContext"]
- configdn = str(names.configdn)
- names.schemadn = current[0]["schemaNamingContext"]
- if not (ldb.Dn(samdb, basedn) == (ldb.Dn(samdb,
- current[0]["defaultNamingContext"][0]))):
- raise ProvisioningError(("basedn in %s (%s) and from %s (%s)"
- "is not the same ..." % (paths.samdb,
- str(current[0]["defaultNamingContext"][0]),
- paths.smbconf, basedn)))
-
- names.domaindn=current[0]["defaultNamingContext"]
- names.rootdn=current[0]["rootDomainNamingContext"]
- names.ncs=current[0]["namingContexts"]
- names.dnsforestdn = None
- names.dnsdomaindn = None
-
- for i in range(0, len(names.ncs)):
- nc = names.ncs[i]
-
- dnsforestdn = "DC=ForestDnsZones,%s" % (str(names.rootdn))
- if nc == dnsforestdn:
- names.dnsforestdn = dnsforestdn
- continue
-
- dnsdomaindn = "DC=DomainDnsZones,%s" % (str(names.domaindn))
- if nc == dnsdomaindn:
- names.dnsdomaindn = dnsdomaindn
- continue
-
- # default site name
- res3 = samdb.search(expression="(objectClass=site)",
- base="CN=Sites," + configdn, scope=ldb.SCOPE_ONELEVEL, attrs=["cn"])
- names.sitename = str(res3[0]["cn"])
-
- # dns hostname and server dn
- res4 = samdb.search(expression="(CN=%s)" % names.netbiosname,
- base="OU=Domain Controllers,%s" % basedn,
- scope=ldb.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=ldb.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
- res6 = samdb.search(expression="(objectClass=*)", base=basedn,
- scope=ldb.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") is None or \
- int(res6[0]["msDS-Behavior-Version"][0]) < DS_DOMAIN_FUNCTION_2000:
- names.domainlevel = DS_DOMAIN_FUNCTION_2000
- else:
- names.domainlevel = int(res6[0]["msDS-Behavior-Version"][0])
-
- # policy guid
- res7 = samdb.search(expression="(displayName=Default Domain Policy)",
- base="CN=Policies,CN=System," + basedn,
- scope=ldb.SCOPE_ONELEVEL, attrs=["cn","displayName"])
- names.policyid = str(res7[0]["cn"]).replace("{","").replace("}","")
- # dc policy guid
- res8 = samdb.search(expression="(displayName=Default Domain Controllers"
- " Policy)",
- base="CN=Policies,CN=System," + basedn,
- scope=ldb.SCOPE_ONELEVEL,
- attrs=["cn","displayName"])
- if len(res8) == 1:
- names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
- else:
- names.policyid_dc = None
-
- res9 = idmapdb.search(expression="(cn=%s-%s)" %
- (str(names.domainsid), security.DOMAIN_RID_ADMINISTRATOR),
- attrs=["xidNumber", "type"])
- if len(res9) != 1:
- raise ProvisioningError("Unable to find uid/gid for Domain Admins rid (%s-%s" % (str(names.domainsid), security.DOMAIN_RID_ADMINISTRATOR))
- if res9[0]["type"][0] == "ID_TYPE_BOTH":
- names.root_gid = res9[0]["xidNumber"][0]
- else:
- names.root_gid = pwd.getpwuid(int(res9[0]["xidNumber"][0])).pw_gid
-
- res10 = samdb.search(expression="(samaccountname=dns)",
- scope=ldb.SCOPE_SUBTREE, attrs=["dn"],
- controls=["search_options:1:2"])
- if (len(res10) > 0):
- has_legacy_dns_account = True
- else:
- has_legacy_dns_account = False
-
- res11 = samdb.search(expression="(samaccountname=dns-%s)" % names.netbiosname,
- scope=ldb.SCOPE_SUBTREE, attrs=["dn"],
- controls=["search_options:1:2"])
- if (len(res11) > 0):
- has_dns_account = True
- else:
- has_dns_account = False
-
- if names.dnsdomaindn is not None:
- if has_dns_account:
- names.dns_backend = 'BIND9_DLZ'
- else:
- names.dns_backend = 'SAMBA_INTERNAL'
- elif has_dns_account or has_legacy_dns_account:
- names.dns_backend = 'BIND9_FLATFILE'
- else:
- names.dns_backend = 'NONE'
-
- dns_admins_sid = get_dnsadmins_sid(samdb, names.domaindn)
- names.name_map['DnsAdmins'] = str(dns_admins_sid)
-
- return names
-
-
-def update_provision_usn(samdb, low, high, id, replace=False):
- """Update the field provisionUSN in sam.ldb
-
- This field is used to track range of USN modified by provision and
- upgradeprovision.
- This value is used afterward by next provision to figure out if
- the field have been modified since last provision.
-
- :param samdb: An LDB object connect to sam.ldb
- :param low: The lowest USN modified by this upgrade
- :param high: The highest USN modified by this upgrade
- :param id: The invocation id of the samba's dc
- :param replace: A boolean indicating if the range should replace any
- existing one or appended (default)
- """
-
- tab = []
- if not replace:
- entry = samdb.search(base="@PROVISION",
- scope=ldb.SCOPE_BASE,
- attrs=[LAST_PROVISION_USN_ATTRIBUTE, "dn"])
- for e in entry[0][LAST_PROVISION_USN_ATTRIBUTE]:
- if not re.search(';', e):
- e = "%s;%s" % (e, id)
- tab.append(str(e))
-
- tab.append("%s-%s;%s" % (low, high, id))
- delta = ldb.Message()
- delta.dn = ldb.Dn(samdb, "@PROVISION")
- delta[LAST_PROVISION_USN_ATTRIBUTE] = ldb.MessageElement(tab,
- ldb.FLAG_MOD_REPLACE, LAST_PROVISION_USN_ATTRIBUTE)
- entry = samdb.search(expression='provisionnerID=*',
- base="@PROVISION", scope=ldb.SCOPE_BASE,
- attrs=["provisionnerID"])
- if len(entry) == 0 or len(entry[0]) == 0:
- delta["provisionnerID"] = ldb.MessageElement(id, ldb.FLAG_MOD_ADD, "provisionnerID")
- samdb.modify(delta)
-
-
-def set_provision_usn(samdb, low, high, id):
- """Set the field provisionUSN in sam.ldb
- This field is used to track range of USN modified by provision and
- upgradeprovision.
- This value is used afterward by next provision to figure out if
- the field have been modified since last provision.
-
- :param samdb: An LDB object connect to sam.ldb
- :param low: The lowest USN modified by this upgrade
- :param high: The highest USN modified by this upgrade
- :param id: The invocationId of the provision"""
-
- tab = []
- tab.append("%s-%s;%s" % (low, high, id))
-
- delta = ldb.Message()
- delta.dn = ldb.Dn(samdb, "@PROVISION")
- delta[LAST_PROVISION_USN_ATTRIBUTE] = ldb.MessageElement(tab,
- ldb.FLAG_MOD_ADD, LAST_PROVISION_USN_ATTRIBUTE)
- samdb.add(delta)
-
-
-def get_max_usn(samdb,basedn):
- """ This function return the biggest USN present in the provision
-
- :param samdb: A LDB object pointing to the sam.ldb
- :param basedn: A string containing the base DN of the provision
- (ie. DC=foo, DC=bar)
- :return: The biggest USN in the provision"""
-
- res = samdb.search(expression="objectClass=*",base=basedn,
- scope=ldb.SCOPE_SUBTREE,attrs=["uSNChanged"],
- controls=["search_options:1:2",
- "server_sort:1:1:uSNChanged",
- "paged_results:1:1"])
- return res[0]["uSNChanged"]
-
-
-def get_last_provision_usn(sam):
- """Get USNs ranges modified by a provision or an upgradeprovision
-
- :param sam: An LDB object pointing to the sam.ldb
- :return: a dictionary which keys are invocation id and values are an array
- of integer representing the different ranges
- """
- try:
- entry = sam.search(expression="%s=*" % LAST_PROVISION_USN_ATTRIBUTE,
- base="@PROVISION", scope=ldb.SCOPE_BASE,
- attrs=[LAST_PROVISION_USN_ATTRIBUTE, "provisionnerID"])
- except ldb.LdbError, (ecode, emsg):
- if ecode == ldb.ERR_NO_SUCH_OBJECT:
- return None
- raise
- if len(entry) > 0:
- myids = []
- range = {}
- p = re.compile(r'-')
- if entry[0].get("provisionnerID"):
- for e in entry[0]["provisionnerID"]:
- myids.append(str(e))
- for r in entry[0][LAST_PROVISION_USN_ATTRIBUTE]:
- tab1 = str(r).split(';')
- if len(tab1) == 2:
- id = tab1[1]
- else:
- id = "default"
- if (len(myids) > 0 and id not in myids):
- continue
- tab2 = p.split(tab1[0])
- if range.get(id) is None:
- range[id] = []
- range[id].append(tab2[0])
- range[id].append(tab2[1])
- return range
- else:
- return None
-
-
-class ProvisionResult(object):
- """Result of a provision.
-
- :ivar server_role: The server role
- :ivar paths: ProvisionPaths instance
- :ivar domaindn: The domain dn, as string
- """
-
- def __init__(self):
- self.server_role = None
- self.paths = None
- self.domaindn = None
- self.lp = None
- self.samdb = None
- self.idmap = None
- self.names = None
- self.domainsid = None
- self.adminpass_generated = None
- self.adminpass = None
- self.backend_result = None
-
- def report_logger(self, logger):
- """Report this provision result to a logger."""
- logger.info(
- "Once the above files are installed, your Samba4 server will "
- "be ready to use")
- if self.adminpass_generated:
- logger.info("Admin password: %s", self.adminpass)
- logger.info("Server Role: %s", self.server_role)
- logger.info("Hostname: %s", self.names.hostname)
- logger.info("NetBIOS Domain: %s", self.names.domain)
- logger.info("DNS Domain: %s", self.names.dnsdomain)
- logger.info("DOMAIN SID: %s", self.domainsid)
-
- if self.backend_result:
- self.backend_result.report_logger(logger)
-
-
-def check_install(lp, session_info, credentials):
- """Check whether the current install seems ok.
-
- :param lp: Loadparm context
- :param session_info: Session information
- :param credentials: Credentials
- """
- if lp.get("realm") == "":
- raise Exception("Realm empty")
- samdb = Ldb(lp.samdb_url(), session_info=session_info,
- credentials=credentials, lp=lp)
- if len(samdb.search("(cn=Administrator)")) != 1:
- raise ProvisioningError("No administrator account found")
-
-
-def findnss(nssfn, names):
- """Find a user or group from a list of possibilities.
-
- :param nssfn: NSS Function to try (should raise KeyError if not found)
- :param names: Names to check.
- :return: Value return by first names list.
- """
- for name in names:
- try:
- return nssfn(name)
- except KeyError:
- pass
- raise KeyError("Unable to find user/group in %r" % names)
-
-
-findnss_uid = lambda names: findnss(pwd.getpwnam, names)[2]
-findnss_gid = lambda names: findnss(grp.getgrnam, names)[2]
-
-
-def provision_paths_from_lp(lp, dnsdomain):
- """Set the default paths for provisioning.
-
- :param lp: Loadparm context.
- :param dnsdomain: DNS Domain name
- """
- paths = ProvisionPaths()
- paths.private_dir = lp.get("private dir")
- paths.state_dir = lp.get("state directory")
-
- # This is stored without path prefix for the "privateKeytab" attribute in
- # "secrets_dns.ldif".
- paths.dns_keytab = "dns.keytab"
- paths.keytab = "secrets.keytab"
-
- paths.shareconf = os.path.join(paths.private_dir, "share.ldb")
- paths.samdb = os.path.join(paths.private_dir, "sam.ldb")
- paths.idmapdb = os.path.join(paths.private_dir, "idmap.ldb")
- paths.secrets = os.path.join(paths.private_dir, "secrets.ldb")
- paths.privilege = os.path.join(paths.private_dir, "privilege.ldb")
- paths.dns = os.path.join(paths.private_dir, "dns", dnsdomain + ".zone")
- paths.dns_update_list = os.path.join(paths.private_dir, "dns_update_list")
- paths.spn_update_list = os.path.join(paths.private_dir, "spn_update_list")
- paths.namedconf = os.path.join(paths.private_dir, "named.conf")
- paths.namedconf_update = os.path.join(paths.private_dir, "named.conf.update")
- paths.namedtxt = os.path.join(paths.private_dir, "named.txt")
- paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf")
- paths.winsdb = os.path.join(paths.private_dir, "wins.ldb")
- paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi")
- paths.hklm = "hklm.ldb"
- paths.hkcr = "hkcr.ldb"
- paths.hkcu = "hkcu.ldb"
- paths.hku = "hku.ldb"
- paths.hkpd = "hkpd.ldb"
- paths.hkpt = "hkpt.ldb"
- paths.sysvol = lp.get("path", "sysvol")
- paths.netlogon = lp.get("path", "netlogon")
- paths.smbconf = lp.configfile
- return paths
-
-
-def determine_netbios_name(hostname):
- """Determine a netbios name from a hostname."""
- # remove forbidden chars and force the length to be <16
- netbiosname = "".join([x for x in hostname if is_valid_netbios_char(x)])
- return netbiosname[:MAX_NETBIOS_NAME_LEN].upper()
-
-
-def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None,
- serverrole=None, rootdn=None, domaindn=None, configdn=None,
- schemadn=None, serverdn=None, sitename=None):
- """Guess configuration settings to use."""
-
- if hostname is None:
- hostname = socket.gethostname().split(".")[0]
-
- netbiosname = lp.get("netbios name")
- if netbiosname is None:
- netbiosname = determine_netbios_name(hostname)
- netbiosname = netbiosname.upper()
- if not valid_netbios_name(netbiosname):
- raise InvalidNetbiosName(netbiosname)
-
- if dnsdomain is None:
- dnsdomain = lp.get("realm")
- if dnsdomain is None or dnsdomain == "":
- raise ProvisioningError("guess_names: 'realm' not specified in supplied %s!", lp.configfile)
-
- dnsdomain = dnsdomain.lower()
-
- if serverrole is None:
- serverrole = lp.get("server role")
- if serverrole is None:
- raise ProvisioningError("guess_names: 'server role' not specified in supplied %s!" % lp.configfile)
-
- serverrole = serverrole.lower()
-
- realm = dnsdomain.upper()
-
- if lp.get("realm") == "":
- raise ProvisioningError("guess_names: 'realm =' was not specified in supplied %s. Please remove the smb.conf file and let provision generate it" % lp.configfile)
-
- if lp.get("realm").upper() != realm:
- raise ProvisioningError("guess_names: 'realm=%s' in %s must match chosen realm '%s'! Please remove the smb.conf file and let provision generate it" % (lp.get("realm").upper(), realm, lp.configfile))
-
- if lp.get("server role").lower() != serverrole:
- raise ProvisioningError("guess_names: 'server role=%s' in %s must match chosen server role '%s'! Please remove the smb.conf file and let provision generate it" % (lp.get("server role"), lp.configfile, serverrole))
-
- if serverrole == "active directory domain controller":
- if domain is None:
- # This will, for better or worse, default to 'WORKGROUP'
- domain = lp.get("workgroup")
- domain = domain.upper()
-
- if lp.get("workgroup").upper() != domain:
- raise ProvisioningError("guess_names: Workgroup '%s' in smb.conf must match chosen domain '%s'! Please remove the %s file and let provision generate it" % (lp.get("workgroup").upper(), domain, lp.configfile))
-
- if domaindn is None:
- domaindn = samba.dn_from_dns_name(dnsdomain)
-
- if domain == netbiosname:
- raise ProvisioningError("guess_names: Domain '%s' must not be equal to short host name '%s'!" % (domain, netbiosname))
- else:
- domain = netbiosname
- if domaindn is None:
- domaindn = "DC=" + netbiosname
-
- if not valid_netbios_name(domain):
- raise InvalidNetbiosName(domain)
-
- if hostname.upper() == realm:
- raise ProvisioningError("guess_names: Realm '%s' must not be equal to hostname '%s'!" % (realm, hostname))
- if netbiosname.upper() == realm:
- raise ProvisioningError("guess_names: Realm '%s' must not be equal to netbios hostname '%s'!" % (realm, netbiosname))
- if domain == realm:
- raise ProvisioningError("guess_names: Realm '%s' must not be equal to short domain name '%s'!" % (realm, domain))
-
- if rootdn is None:
- rootdn = domaindn
-
- if configdn is None:
- configdn = "CN=Configuration," + rootdn
- if schemadn is None:
- schemadn = "CN=Schema," + configdn
-
- if sitename is None:
- sitename = DEFAULTSITE
-
- names = ProvisionNames()
- names.rootdn = rootdn
- names.domaindn = domaindn
- names.configdn = configdn
- names.schemadn = schemadn
- names.ldapmanagerdn = "CN=Manager," + rootdn
- names.dnsdomain = dnsdomain
- names.domain = domain
- names.realm = realm
- names.netbiosname = netbiosname
- names.hostname = hostname
- names.sitename = sitename
- names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (
- netbiosname, sitename, configdn)
-
- return names
-
-
-def make_smbconf(smbconf, hostname, domain, realm, targetdir,
- serverrole=None, eadb=False, use_ntvfs=False, lp=None,
- global_param=None):
- """Create a new smb.conf file based on a couple of basic settings.
- """
- assert smbconf is not None
-
- if hostname is None:
- hostname = socket.gethostname().split(".")[0]
-
- netbiosname = determine_netbios_name(hostname)
-
- if serverrole is None:
- serverrole = "standalone server"
-
- assert domain is not None
- domain = domain.upper()
-
- assert realm is not None
- realm = realm.upper()
-
- global_settings = {
- "netbios name": netbiosname,
- "workgroup": domain,
- "realm": realm,
- "server role": serverrole,
- }
-
- if lp is None:
- lp = samba.param.LoadParm()
- #Load non-existent file
- if os.path.exists(smbconf):
- lp.load(smbconf)
-
- if global_param is not None:
- for ent in global_param:
- if global_param[ent] is not None:
- global_settings[ent] = " ".join(global_param[ent])
-
- if targetdir is not None:
- global_settings["private dir"] = os.path.abspath(os.path.join(targetdir, "private"))
- global_settings["lock dir"] = os.path.abspath(targetdir)
- global_settings["state directory"] = os.path.abspath(os.path.join(targetdir, "state"))
- global_settings["cache directory"] = os.path.abspath(os.path.join(targetdir, "cache"))
-
- lp.set("lock dir", os.path.abspath(targetdir))
- lp.set("state directory", global_settings["state directory"])
- lp.set("cache directory", global_settings["cache directory"])
-
- if eadb:
- if use_ntvfs and not lp.get("posix:eadb"):
- if targetdir is not None:
- privdir = os.path.join(targetdir, "private")
- else:
- privdir = lp.get("private dir")
- lp.set("posix:eadb", os.path.abspath(os.path.join(privdir, "eadb.tdb")))
- elif not use_ntvfs and not lp.get("xattr_tdb:file"):
- if targetdir is not None:
- statedir = os.path.join(targetdir, "state")
- else:
- statedir = lp.get("state directory")
- lp.set("xattr_tdb:file", os.path.abspath(os.path.join(statedir, "xattr.tdb")))
-
- shares = {}
- if serverrole == "active directory domain controller":
- shares["sysvol"] = os.path.join(lp.get("state directory"), "sysvol")
- shares["netlogon"] = os.path.join(shares["sysvol"], realm.lower(),
- "scripts")
- else:
- global_settings["passdb backend"] = "samba_dsdb"
-
- f = open(smbconf, 'w')
- try:
- f.write("[globals]\n")
- for key, val in global_settings.iteritems():
- f.write("\t%s = %s\n" % (key, val))
- f.write("\n")
-
- for name, path in shares.iteritems():
- f.write("[%s]\n" % name)
- f.write("\tpath = %s\n" % path)
- f.write("\tread only = no\n")
- f.write("\n")
- finally:
- f.close()
- # reload the smb.conf
- lp.load(smbconf)
-
- # and dump it without any values that are the default
- # this ensures that any smb.conf parameters that were set
- # on the provision/join command line are set in the resulting smb.conf
- f = open(smbconf, mode='w')
- try:
- lp.dump(f, False)
- finally:
- f.close()
-
-
-def setup_name_mappings(idmap, sid, root_uid, nobody_uid,
- users_gid, root_gid):
- """setup reasonable name mappings for sam names to unix names.
-
- :param samdb: SamDB object.
- :param idmap: IDmap db object.
- :param sid: The domain sid.
- :param domaindn: The domain DN.
- :param root_uid: uid of the UNIX root user.
- :param nobody_uid: uid of the UNIX nobody user.
- :param users_gid: gid of the UNIX users group.
- :param root_gid: gid of the UNIX root group.
- """
- idmap.setup_name_mapping("S-1-5-7", idmap.TYPE_UID, nobody_uid)
-
- idmap.setup_name_mapping(sid + "-500", idmap.TYPE_UID, root_uid)
- idmap.setup_name_mapping(sid + "-513", idmap.TYPE_GID, users_gid)
-
-
-def setup_samdb_partitions(samdb_path, logger, lp, session_info,
- provision_backend, names, schema, serverrole,
- erase=False):
- """Setup the partitions for the SAM database.
-
- Alternatively, provision() may call this, and then populate the database.
-
- :note: This will wipe the Sam Database!
-
- :note: This function always removes the local SAM LDB file. The erase
- parameter controls whether to erase the existing data, which
- may not be stored locally but in LDAP.
-
- """
- assert session_info is not None
-
- # We use options=["modules:"] to stop the modules loading - we
- # just want to wipe and re-initialise the database, not start it up
-
- try:
- os.unlink(samdb_path)
- except OSError:
- pass
-
- samdb = Ldb(url=samdb_path, session_info=session_info,
- lp=lp, options=["modules:"])
-
- ldap_backend_line = "# No LDAP backend"
- if provision_backend.type != "ldb":
- ldap_backend_line = "ldapBackend: %s" % provision_backend.ldap_uri
-
- samdb.transaction_start()
- try:
- logger.info("Setting up sam.ldb partitions and settings")
- setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
- "LDAP_BACKEND_LINE": ldap_backend_line
- })
-
-
- setup_add_ldif(samdb, setup_path("provision_init.ldif"), {
- "BACKEND_TYPE": provision_backend.type,
- "SERVER_ROLE": serverrole
- })
-
- logger.info("Setting up sam.ldb rootDSE")
- setup_samdb_rootdse(samdb, names)
- except:
- samdb.transaction_cancel()
- raise
- else:
- samdb.transaction_commit()
-
-
-def secretsdb_self_join(secretsdb, domain,
- netbiosname, machinepass, domainsid=None,
- realm=None, dnsdomain=None,
- keytab_path=None,
- key_version_number=1,
- secure_channel_type=SEC_CHAN_WKSTA):
- """Add domain join-specific bits to a secrets database.
-
- :param secretsdb: Ldb Handle to the secrets database
- :param machinepass: Machine password
- """
- attrs = ["whenChanged",
- "secret",
- "priorSecret",
- "priorChanged",
- "krb5Keytab",
- "privateKeytab"]
-
- if realm is not None:
- if dnsdomain is None:
- dnsdomain = realm.lower()
- dnsname = '%s.%s' % (netbiosname.lower(), dnsdomain.lower())
- else:
- dnsname = None
- shortname = netbiosname.lower()
-
- # We don't need to set msg["flatname"] here, because rdn_name will handle
- # it, and it causes problems for modifies anyway
- msg = ldb.Message(ldb.Dn(secretsdb, "flatname=%s,cn=Primary Domains" % domain))
- msg["secureChannelType"] = [str(secure_channel_type)]
- msg["objectClass"] = ["top", "primaryDomain"]
- if dnsname is not None:
- msg["objectClass"] = ["top", "primaryDomain", "kerberosSecret"]
- msg["realm"] = [realm]
- msg["saltPrincipal"] = ["host/%s@%s" % (dnsname, realm.upper())]
- msg["msDS-KeyVersionNumber"] = [str(key_version_number)]
- msg["privateKeytab"] = ["secrets.keytab"]
-
- msg["secret"] = [machinepass]
- msg["samAccountName"] = ["%s$" % netbiosname]
- msg["secureChannelType"] = [str(secure_channel_type)]
- if domainsid is not None:
- msg["objectSid"] = [ndr_pack(domainsid)]
-
- # This complex expression tries to ensure that we don't have more
- # than one record for this SID, realm or netbios domain at a time,
- # but we don't delete the old record that we are about to modify,
- # because that would delete the keytab and previous password.
- res = secretsdb.search(base="cn=Primary Domains", attrs=attrs,