"""Functions for setting up a Samba configuration."""
+__docformat__ = "restructuredText"
+
DEFAULTSITE = "Default-First-Site-Name"
class InvalidNetbiosName(Exception):
:param credentials: Credentials
"""
if lp.get("realm") == "":
- raise Error("Realm empty")
+ raise Exception("Realm empty")
ldb = Ldb(lp.get("sam database"), session_info=session_info,
credentials=credentials, lp=lp)
if len(ldb.search("(cn=Administrator)")) != 1:
raise KeyError("Unable to find user/group %r" % names)
+findnss_uid = lambda names: findnss(pwd.getpwnam, names)[2]
+findnss_gid = lambda names: findnss(grp.getgrnam, names)[2]
+
+
def open_ldb(session_info, credentials, lp, dbname):
"""Open a LDB, thrashing it if it is corrupt.
paths.secrets = os.path.join(paths.private_dir, lp.get("secrets database") or "secrets.ldb")
paths.templates = os.path.join(paths.private_dir, "templates.ldb")
paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone")
+ paths.namedconf = os.path.join(paths.private_dir, "named.conf")
+ 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.phpldapadminconfig = os.path.join(paths.private_dir,
dnsdomain = dnsdomain.lower()
- if (serverrole == "domain controller"):
+ if serverrole == "domain controller":
if domain is None:
domain = lp.get("workgroup")
if domaindn is None:
domaindn = "DC=" + dnsdomain.replace(".", ",DC=")
if lp.get("workgroup").upper() != domain.upper():
- raise Error("workgroup '%s' in smb.conf must match chosen domain '%s'",
+ raise Exception("workgroup '%s' in smb.conf must match chosen domain '%s'",
lp.get("workgroup"), domain)
else:
domain = netbiosname
return names
-def load_or_make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, targetdir):
- if targetdir is not None:
- if not os.path.exists(targetdir):
- os.mkdir(targetdir)
- if not os.path.exists(os.path.join(targetdir, "etc")):
- os.mkdir(os.path.join(targetdir, "etc"))
+def make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
+ targetdir):
+ if hostname is None:
+ hostname = socket.gethostname().split(".")[0].lower()
- smbconf = os.path.join(targetdir, "etc", "smb.conf")
+ if serverrole is None:
+ serverrole = "standalone"
- # only install a new smb.conf if there isn't one there already
+ assert serverrole in ("domain controller", "member server", "standalone")
+ if serverrole == "domain controller":
+ smbconfsuffix = "dc"
+ elif serverrole == "member server":
+ smbconfsuffix = "member"
+ elif serverrole == "standalone":
+ smbconfsuffix = "standalone"
- if not os.path.exists(smbconf):
- if hostname is None:
- hostname = socket.gethostname().split(".")[0].lower()
+ assert domain is not None
+ assert realm is not None
- if serverrole is None:
- serverrole = "standalone"
+ default_lp = param.LoadParm()
+ #Load non-existant file
+ default_lp.load(smbconf)
+
+ if targetdir is not None:
+ privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private"))
+ lockdir_line = "lock dir = " + os.path.abspath(targetdir)
- assert serverrole in ("domain controller", "member server", "standalone")
- if serverrole == "domain controller":
- smbconfsuffix = "dc"
- elif serverrole == "member server":
- smbconfsuffix = "member"
- elif serverrole == "standalone":
- smbconfsuffix = "standalone"
-
- assert domain is not None
- assert realm is not None
-
- default_lp = param.LoadParm()
- #Load non-existant file
- default_lp.load(smbconf)
-
- if targetdir is not None:
- privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private"))
- lockdir_line = "lock dir = " + os.path.abspath(targetdir)
+ default_lp.set("lock dir", os.path.abspath(targetdir))
+ else:
+ privatedir_line = ""
+ lockdir_line = ""
- default_lp.set("lock dir", os.path.abspath(targetdir))
- else:
- privatedir_line = ""
- lockdir_line = ""
-
- sysvol = os.path.join(default_lp.get("lock dir"), "sysvol")
- netlogon = os.path.join(sysvol, realm.lower(), "scripts")
-
- setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix),
- smbconf, {
- "HOSTNAME": hostname,
- "DOMAIN": domain,
- "REALM": realm,
- "SERVERROLE": serverrole,
- "NETLOGONPATH": netlogon,
- "SYSVOLPATH": sysvol,
- "PRIVATEDIR_LINE": privatedir_line,
- "LOCKDIR_LINE": lockdir_line
- })
+ sysvol = os.path.join(default_lp.get("lock dir"), "sysvol")
+ netlogon = os.path.join(sysvol, realm.lower(), "scripts")
- lp = param.LoadParm()
- lp.load(smbconf)
+ setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix),
+ smbconf, {
+ "HOSTNAME": hostname,
+ "DOMAIN": domain,
+ "REALM": realm,
+ "SERVERROLE": serverrole,
+ "NETLOGONPATH": netlogon,
+ "SYSVOLPATH": sysvol,
+ "PRIVATEDIR_LINE": privatedir_line,
+ "LOCKDIR_LINE": lockdir_line
+ })
- return lp
def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid,
schemadn_ldb = "schema.ldb"
if ldap_backend is not None:
schema_ldb = ldap_backend
- schemadn_ldb = ldap_backend
-
+ schemadn_ldb = ldap_backend
+
if ldap_backend_type == "fedora-ds":
backend_modules = ["nsuniqueid", "paged_searches"]
# We can handle linked attributes here, as we don't have directory-side subtree operations
domainsid, invocationid, setup_path,
policyguid):
"""Join a host to its own domain."""
+ assert isinstance(invocationid, str)
setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), {
"CONFIGDN": names.configdn,
"SCHEMADN": names.schemadn,
if serverrole == "domain controller":
samdb.set_invocation_id(invocationid)
- load_schema(setup_path, samdb, names.schemadn, names.netbiosname, names.configdn, names.sitename)
+ load_schema(setup_path, samdb, names.schemadn, names.netbiosname,
+ names.configdn, names.sitename)
samdb.transaction_start()
domainsid = security.Sid(domainsid)
if policyguid is None:
- policyguid = uuid.random()
+ policyguid = str(uuid.uuid4())
if adminpass is None:
adminpass = misc.random_password(12)
if krbtgtpass is None:
machinepass = misc.random_password(12)
if dnspass is None:
dnspass = misc.random_password(12)
- if root is None:
- root_uid = findnss(pwd.getpwnam, ["root"])[2]
- else:
- root_uid = findnss(pwd.getpwnam, [root])[2]
- if nobody is None:
- nobody_uid = findnss(pwd.getpwnam, ["nobody"])[2]
- else:
- nobody_uid = findnss(pwd.getpwnam, [nobody])[2]
- if users is None:
- users_gid = findnss(grp.getgrnam, ["users"])[2]
- else:
- users_gid = findnss(grp.getgrnam, [users])[2]
+ root_uid = findnss_uid([root or "root"])
+ nobody_uid = findnss_uid([nobody or "nobody"])
+ users_gid = findnss_gid([users or "users"])
if wheel is None:
- wheel_gid = findnss(grp.getgrnam, ["wheel", "adm"])[2]
+ wheel_gid = findnss_gid(["wheel", "adm"])
else:
- wheel_gid = findnss(grp.getgrnam, [wheel])[2]
+ wheel_gid = findnss_gid([wheel])
if aci is None:
aci = "# no aci for local ldb"
- lp = load_or_make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, targetdir)
+ if smbconf is None:
+ os.makedirs(os.path.join(targetdir, "etc"))
+ smbconf = os.path.join(targetdir, "etc", "smb.conf")
+
+ # only install a new smb.conf if there isn't one there already
+ if not os.path.exists(smbconf):
+ make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
+ targetdir)
+
+ lp = param.LoadParm()
+ lp.load(smbconf)
names = guess_names(lp=lp, hostname=hostname, domain=domain,
dnsdomain=realm, serverrole=serverrole, sitename=sitename,
if hostip6 is None:
try:
hostip6 = socket.getaddrinfo(names.hostname, None, socket.AF_INET6, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
- except socket.gaierror: pass
+ except socket.gaierror:
+ pass
if serverrole is None:
serverrole = lp.get("server role")
assert serverrole in ("domain controller", "member server", "standalone")
if invocationid is None and serverrole == "domain controller":
- invocationid = uuid.random()
+ invocationid = str(uuid.uuid4())
if not os.path.exists(paths.private_dir):
os.mkdir(paths.private_dir)
expression="(&(objectClass=computer)(cn=%s))" % names.hostname,
scope=SCOPE_SUBTREE)
assert isinstance(hostguid, str)
-
- create_zone_file(paths.dns, setup_path, samdb,
- hostname=names.hostname, hostip=hostip,
- hostip6=hostip6, dnsdomain=names.dnsdomain,
- domaindn=names.domaindn, dnspass=dnspass, realm=names.realm,
+
+ create_zone_file(paths.dns, setup_path, dnsdomain=names.dnsdomain,
+ domaindn=names.domaindn, hostip=hostip,
+ hostip6=hostip6, hostname=names.hostname,
+ dnspass=dnspass, realm=names.realm,
domainguid=domainguid, hostguid=hostguid)
message("Please install the zone located in %s into your DNS server" % paths.dns)
-
+
+ create_named_conf(paths.namedconf, setup_path, realm=names.realm,
+ dnsdomain=names.dnsdomain, private_dir=paths.private_dir,
+ keytab_name=paths.dns_keytab)
+ message("See %s for example configuration statements for secure GSS-TSIG updates" % paths.namedconf)
+
+ 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)
+
create_phpldapadmin_config(paths.phpldapadminconfig, setup_path,
ldapi_url)
ldap_backend=None, ldap_backend_type=None, sitename=None):
def message(text):
- """print a message if quiet is not set."""
+ """print a message if quiet is not set."""
print text
return provision(setup_dir, message, system_session(), None,
if root is None:
root = findnss(pwd.getpwnam, ["root"])[0]
- lp = load_or_make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, targetdir)
+ if smbconf is None:
+ os.makedirs(os.path.join(targetdir, "etc"))
+ smbconf = os.path.join(targetdir, "etc", "smb.conf")
+
+ # only install a new smb.conf if there isn't one there already
+ if not os.path.exists(smbconf):
+ make_smbconf(smbconf, setup_path, hostname, domain, realm,
+ serverrole, targetdir)
+
+ lp = param.LoadParm()
+ lp.load(smbconf)
names = guess_names(lp=lp, hostname=hostname, domain=domain,
dnsdomain=realm, serverrole=serverrole,
- rootdn=rootdn, domaindn=domaindn, configdn=configdn, schemadn=schemadn)
+ rootdn=rootdn, domaindn=domaindn, configdn=configdn,
+ schemadn=schemadn)
paths = provision_paths_from_lp(lp, names.dnsdomain)
elif ldap_backend_type == "openldap":
attrs = ["linkID", "lDAPDisplayName"]
- res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs);
+ res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs);
- memberof_config = "# Generated from schema in " + schemadb_path + "\n";
- refint_attributes = "";
- for i in range (0, len(res)):
+ memberof_config = "# Generated from schema in " + schemadb_path + "\n";
+ refint_attributes = "";
+ for i in range (0, len(res)):
linkid = res[i]["linkID"][0]
linkid = str(int(linkid) + 1)
expression = "(&(objectclass=attributeSchema)(linkID=" + (linkid) + "))"
""";
- memberof_config = memberof_config + """
+ memberof_config = memberof_config + """
overlay refint
refint_attributes""" + refint_attributes + "\n";
-
- setup_file(setup_path("slapd.conf"), paths.slapdconf,
+
+ setup_file(setup_path("slapd.conf"), paths.slapdconf,
{"DNSDOMAIN": names.dnsdomain,
"LDAPDIR": paths.ldapdir,
"DOMAINDN": names.domaindn,
"LDAPMANAGERDN": names.ldapmanagerdn,
"LDAPMANAGERPASS": adminpass,
"MEMBEROF_CONFIG": memberof_config})
- setup_file(setup_path("modules.conf"), paths.modulesconf,
+ setup_file(setup_path("modules.conf"), paths.modulesconf,
{"REALM": names.realm})
setup_db_config(setup_path, os.path.join(paths.ldapdir, os.path.join("db", "user")))
{"S4_LDAPI_URI": ldapi_uri})
-def create_zone_file(path, setup_path, samdb, dnsdomain, domaindn,
- hostip, hostip6, hostname, dnspass, realm, domainguid, hostguid):
+def create_zone_file(path, setup_path, dnsdomain, domaindn,
+ hostip, hostip6, hostname, dnspass, realm, domainguid, hostguid):
"""Write out a DNS zone file, from the info in the current database.
-
- :param path: Path of the new file.
- :param setup_path": Setup path function.
- :param samdb: SamDB object
+
+ :param path: Path of the new zone file.
+ :param setup_path: Setup path function.
:param dnsdomain: DNS Domain name
:param domaindn: DN of the Domain
:param hostip: Local IPv4 IP
hostip6_host_line = ""
if hostip6 is not None:
- hostip6_base_line = " IN AAAA " + hostip6
- hostip6_host_line = hostname + " IN AAAA " + hostip6
+ hostip6_base_line = " IN AAAA " + hostip6
+ hostip6_host_line = hostname + " IN AAAA " + hostip6
setup_file(setup_path("provision.zone"), path, {
"DNSPASS_B64": b64encode(dnspass),
"HOSTIP6_HOST_LINE": hostip6_host_line,
})
+def create_named_conf(path, setup_path, realm, dnsdomain,
+ private_dir, keytab_name):
+ """Write out a file containing zone statements suitable for inclusion in a
+ named.conf file (including GSS-TSIG configuration).
+
+ :param path: Path of the new named.conf file.
+ :param setup_path: Setup path function.
+ :param realm: Realm name
+ :param dnsdomain: DNS Domain name
+ :param private_dir: Path to private directory
+ :param keytab_name: File name of DNS keytab file
+ """
+
+ setup_file(setup_path("named.conf"), path, {
+ "DNSDOMAIN": dnsdomain,
+ "REALM": realm,
+ "REALM_WC": "*." + ".".join(realm.split(".")[1:]),
+ "DNS_KEYTAB": keytab_name,
+ "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
+ })
+
+def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
+ """Write out a file containing zone statements suitable for inclusion in a
+ named.conf file (including GSS-TSIG configuration).
+
+ :param path: Path of the new named.conf file.
+ :param setup_path: Setup path function.
+ :param dnsdomain: DNS Domain name
+ :param hostname: Local hostname
+ :param realm: Realm name
+ """
+
+ setup_file(setup_path("krb5.conf"), path, {
+ "DNSDOMAIN": dnsdomain,
+ "HOSTNAME": hostname,
+ "REALM": realm,
+ })
+
def load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename):
"""Load schema for the SamDB.