2 # Unix SMB/CIFS implementation.
3 # backend code for provisioning a Samba4 server
5 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
6 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8 # Based on the original in EJS:
9 # Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 """Functions for setting up a Samba configuration."""
27 from base64 import b64encode
37 from auth import system_session
38 from samba import Ldb, substitute_var, valid_netbios_name, check_all_substituted
39 from samba.samdb import SamDB
40 from samba.idmap import IDmapDB
43 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, \
44 LDB_ERR_NO_SUCH_OBJECT, timestring, CHANGETYPE_MODIFY, CHANGETYPE_NONE
46 __docformat__ = "restructuredText"
48 DEFAULTSITE = "Default-First-Site-Name"
50 class InvalidNetbiosName(Exception):
51 """A specified name was not a valid NetBIOS name."""
52 def __init__(self, name):
53 super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
56 class ProvisionPaths(object):
69 self.dns_keytab = None
72 self.private_dir = None
75 self.modulesconf = None
76 self.memberofconf = None
77 self.fedoradsinf = None
78 self.fedoradspartitions = None
81 class ProvisionNames(object):
87 self.ldapmanagerdn = None
90 self.netbiosname = None
97 class ProvisionResult(object):
104 def check_install(lp, session_info, credentials):
105 """Check whether the current install seems ok.
107 :param lp: Loadparm context
108 :param session_info: Session information
109 :param credentials: Credentials
111 if lp.get("realm") == "":
112 raise Exception("Realm empty")
113 ldb = Ldb(lp.get("sam database"), session_info=session_info,
114 credentials=credentials, lp=lp)
115 if len(ldb.search("(cn=Administrator)")) != 1:
116 raise "No administrator account found"
119 def findnss(nssfn, names):
120 """Find a user or group from a list of possibilities.
122 :param nssfn: NSS Function to try (should raise KeyError if not found)
123 :param names: Names to check.
124 :return: Value return by first names list.
131 raise KeyError("Unable to find user/group %r" % names)
134 findnss_uid = lambda names: findnss(pwd.getpwnam, names)[2]
135 findnss_gid = lambda names: findnss(grp.getgrnam, names)[2]
138 def read_and_sub_file(file, subst_vars):
139 """Read a file and sub in variables found in it
141 :param file: File to be read (typically from setup directory)
142 param subst_vars: Optional variables to subsitute in the file.
144 data = open(file, 'r').read()
145 if subst_vars is not None:
146 data = substitute_var(data, subst_vars)
147 check_all_substituted(data)
151 def setup_add_ldif(ldb, ldif_path, subst_vars=None):
152 """Setup a ldb in the private dir.
154 :param ldb: LDB file to import data into
155 :param ldif_path: Path of the LDIF file to load
156 :param subst_vars: Optional variables to subsitute in LDIF.
158 assert isinstance(ldif_path, str)
160 data = read_and_sub_file(ldif_path, subst_vars)
164 def setup_modify_ldif(ldb, ldif_path, subst_vars=None):
165 """Modify a ldb in the private dir.
167 :param ldb: LDB object.
168 :param ldif_path: LDIF file path.
169 :param subst_vars: Optional dictionary with substitution variables.
171 data = read_and_sub_file(ldif_path, subst_vars)
173 ldb.modify_ldif(data)
176 def setup_ldb(ldb, ldif_path, subst_vars):
177 """Import a LDIF a file into a LDB handle, optionally substituting variables.
179 :note: Either all LDIF data will be added or none (using transactions).
181 :param ldb: LDB file to import into.
182 :param ldif_path: Path to the LDIF file.
183 :param subst_vars: Dictionary with substitution variables.
185 assert ldb is not None
186 ldb.transaction_start()
188 setup_add_ldif(ldb, ldif_path, subst_vars)
190 ldb.transaction_cancel()
192 ldb.transaction_commit()
195 def setup_file(template, fname, subst_vars):
196 """Setup a file in the private dir.
198 :param template: Path of the template file.
199 :param fname: Path of the file to create.
200 :param subst_vars: Substitution variables.
204 if os.path.exists(f):
207 data = read_and_sub_file(template, subst_vars)
208 open(f, 'w').write(data)
211 def provision_paths_from_lp(lp, dnsdomain):
212 """Set the default paths for provisioning.
214 :param lp: Loadparm context.
215 :param dnsdomain: DNS Domain name
217 paths = ProvisionPaths()
218 paths.private_dir = lp.get("private dir")
219 paths.keytab = "secrets.keytab"
220 paths.dns_keytab = "dns.keytab"
222 paths.shareconf = os.path.join(paths.private_dir, "share.ldb")
223 paths.samdb = os.path.join(paths.private_dir, lp.get("sam database") or "samdb.ldb")
224 paths.idmapdb = os.path.join(paths.private_dir, lp.get("idmap database") or "idmap.ldb")
225 paths.secrets = os.path.join(paths.private_dir, lp.get("secrets database") or "secrets.ldb")
226 paths.templates = os.path.join(paths.private_dir, "templates.ldb")
227 paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone")
228 paths.namedconf = os.path.join(paths.private_dir, "named.conf")
229 paths.namedtxt = os.path.join(paths.private_dir, "named.txt")
230 paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf")
231 paths.winsdb = os.path.join(paths.private_dir, "wins.ldb")
232 paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi")
233 paths.phpldapadminconfig = os.path.join(paths.private_dir,
234 "phpldapadmin-config.php")
235 paths.ldapdir = os.path.join(paths.private_dir,
237 paths.slapdconf = os.path.join(paths.ldapdir,
239 paths.modulesconf = os.path.join(paths.ldapdir,
241 paths.memberofconf = os.path.join(paths.ldapdir,
243 paths.fedoradsinf = os.path.join(paths.ldapdir,
245 paths.fedoradspartitions = os.path.join(paths.ldapdir,
246 "fedorads-partitions.ldif")
247 paths.hklm = "hklm.ldb"
248 paths.hkcr = "hkcr.ldb"
249 paths.hkcu = "hkcu.ldb"
250 paths.hku = "hku.ldb"
251 paths.hkpd = "hkpd.ldb"
252 paths.hkpt = "hkpt.ldb"
254 paths.sysvol = lp.get("path", "sysvol")
256 paths.netlogon = lp.get("path", "netlogon")
258 paths.smbconf = lp.configfile()
263 def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None, serverrole=None,
264 rootdn=None, domaindn=None, configdn=None, schemadn=None, serverdn=None,
266 """Guess configuration settings to use."""
269 hostname = socket.gethostname().split(".")[0].lower()
271 netbiosname = hostname.upper()
272 if not valid_netbios_name(netbiosname):
273 raise InvalidNetbiosName(netbiosname)
275 hostname = hostname.lower()
277 if dnsdomain is None:
278 dnsdomain = lp.get("realm")
280 if serverrole is None:
281 serverrole = lp.get("server role")
283 assert dnsdomain is not None
284 realm = dnsdomain.upper()
286 if lp.get("realm").upper() != realm:
287 raise Exception("realm '%s' in %s must match chosen realm '%s'" %
288 (lp.get("realm"), lp.configfile(), realm))
290 dnsdomain = dnsdomain.lower()
292 if serverrole == "domain controller":
294 domain = lp.get("workgroup")
296 domaindn = "DC=" + dnsdomain.replace(".", ",DC=")
297 if lp.get("workgroup").upper() != domain.upper():
298 raise Exception("workgroup '%s' in smb.conf must match chosen domain '%s'",
299 lp.get("workgroup"), domain)
303 domaindn = "CN=" + netbiosname
305 assert domain is not None
306 domain = domain.upper()
307 if not valid_netbios_name(domain):
308 raise InvalidNetbiosName(domain)
314 configdn = "CN=Configuration," + rootdn
316 schemadn = "CN=Schema," + configdn
321 names = ProvisionNames()
322 names.rootdn = rootdn
323 names.domaindn = domaindn
324 names.configdn = configdn
325 names.schemadn = schemadn
326 names.ldapmanagerdn = "CN=Manager," + rootdn
327 names.dnsdomain = dnsdomain
328 names.domain = domain
330 names.netbiosname = netbiosname
331 names.hostname = hostname
332 names.sitename = sitename
333 names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (netbiosname, sitename, configdn)
338 def make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
341 hostname = socket.gethostname().split(".")[0].lower()
343 if serverrole is None:
344 serverrole = "standalone"
346 assert serverrole in ("domain controller", "member server", "standalone")
347 if serverrole == "domain controller":
349 elif serverrole == "member server":
350 smbconfsuffix = "member"
351 elif serverrole == "standalone":
352 smbconfsuffix = "standalone"
354 assert domain is not None
355 assert realm is not None
357 default_lp = param.LoadParm()
358 #Load non-existant file
359 default_lp.load(smbconf)
361 if targetdir is not None:
362 privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private"))
363 lockdir_line = "lock dir = " + os.path.abspath(targetdir)
365 default_lp.set("lock dir", os.path.abspath(targetdir))
370 sysvol = os.path.join(default_lp.get("lock dir"), "sysvol")
371 netlogon = os.path.join(sysvol, realm.lower(), "scripts")
373 setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix),
375 "HOSTNAME": hostname,
378 "SERVERROLE": serverrole,
379 "NETLOGONPATH": netlogon,
380 "SYSVOLPATH": sysvol,
381 "PRIVATEDIR_LINE": privatedir_line,
382 "LOCKDIR_LINE": lockdir_line
387 def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid,
388 users_gid, wheel_gid):
389 """setup reasonable name mappings for sam names to unix names.
391 :param samdb: SamDB object.
392 :param idmap: IDmap db object.
393 :param sid: The domain sid.
394 :param domaindn: The domain DN.
395 :param root_uid: uid of the UNIX root user.
396 :param nobody_uid: uid of the UNIX nobody user.
397 :param users_gid: gid of the UNIX users group.
398 :param wheel_gid: gid of the UNIX wheel group."""
399 # add some foreign sids if they are not present already
400 samdb.add_foreign(domaindn, "S-1-5-7", "Anonymous")
401 samdb.add_foreign(domaindn, "S-1-1-0", "World")
402 samdb.add_foreign(domaindn, "S-1-5-2", "Network")
403 samdb.add_foreign(domaindn, "S-1-5-18", "System")
404 samdb.add_foreign(domaindn, "S-1-5-11", "Authenticated Users")
406 idmap.setup_name_mapping("S-1-5-7", idmap.TYPE_UID, nobody_uid)
407 idmap.setup_name_mapping("S-1-5-32-544", idmap.TYPE_GID, wheel_gid)
409 idmap.setup_name_mapping(sid + "-500", idmap.TYPE_UID, root_uid)
410 idmap.setup_name_mapping(sid + "-513", idmap.TYPE_GID, users_gid)
413 def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
415 serverrole, ldap_backend=None,
416 ldap_backend_type=None, erase=False):
417 """Setup the partitions for the SAM database.
419 Alternatively, provision() may call this, and then populate the database.
421 :note: This will wipe the Sam Database!
423 :note: This function always removes the local SAM LDB file. The erase
424 parameter controls whether to erase the existing data, which
425 may not be stored locally but in LDAP.
427 assert session_info is not None
429 samdb = SamDB(samdb_path, session_info=session_info,
430 credentials=credentials, lp=lp)
436 os.unlink(samdb_path)
438 samdb = SamDB(samdb_path, session_info=session_info,
439 credentials=credentials, lp=lp)
441 #Add modules to the list to activate them by default
442 #beware often order is important
444 # Some Known ordering constraints:
445 # - rootdse must be first, as it makes redirects from "" -> cn=rootdse
446 # - objectclass must be before password_hash, because password_hash checks
447 # that the objectclass is of type person (filled in by objectclass
448 # module when expanding the objectclass list)
449 # - partition must be last
450 # - each partition has its own module list then
451 modules_list = ["rootdse",
467 modules_list2 = ["show_deleted",
470 domaindn_ldb = "users.ldb"
471 if ldap_backend is not None:
472 domaindn_ldb = ldap_backend
473 configdn_ldb = "configuration.ldb"
474 if ldap_backend is not None:
475 configdn_ldb = ldap_backend
476 schemadn_ldb = "schema.ldb"
477 if ldap_backend is not None:
478 schema_ldb = ldap_backend
479 schemadn_ldb = ldap_backend
481 if ldap_backend_type == "fedora-ds":
482 backend_modules = ["nsuniqueid", "paged_searches"]
483 # We can handle linked attributes here, as we don't have directory-side subtree operations
484 tdb_modules_list = ["linked_attributes"]
485 elif ldap_backend_type == "openldap":
486 backend_modules = ["normalise", "entryuuid", "paged_searches"]
487 # OpenLDAP handles subtree renames, so we don't want to do any of these things
488 tdb_modules_list = None
489 elif ldap_backend is not None:
490 raise "LDAP Backend specified, but LDAP Backend Type not specified"
491 elif serverrole == "domain controller":
492 backend_modules = ["repl_meta_data"]
494 backend_modules = ["objectguid"]
496 if tdb_modules_list is None:
497 tdb_modules_list_as_string = ""
499 tdb_modules_list_as_string = ","+",".join(tdb_modules_list)
501 samdb.transaction_start()
503 setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
504 "SCHEMADN": names.schemadn,
505 "SCHEMADN_LDB": schemadn_ldb,
506 "SCHEMADN_MOD2": ",objectguid",
507 "CONFIGDN": names.configdn,
508 "CONFIGDN_LDB": configdn_ldb,
509 "DOMAINDN": names.domaindn,
510 "DOMAINDN_LDB": domaindn_ldb,
511 "SCHEMADN_MOD": "schema_fsmo,instancetype",
512 "CONFIGDN_MOD": "naming_fsmo,instancetype",
513 "DOMAINDN_MOD": "pdc_fsmo,password_hash,instancetype",
514 "MODULES_LIST": ",".join(modules_list),
515 "TDB_MODULES_LIST": tdb_modules_list_as_string,
516 "MODULES_LIST2": ",".join(modules_list2),
517 "BACKEND_MOD": ",".join(backend_modules),
521 samdb.transaction_cancel()
524 samdb.transaction_commit()
526 samdb = SamDB(samdb_path, session_info=session_info,
527 credentials=credentials, lp=lp)
529 samdb.transaction_start()
531 message("Setting up sam.ldb attributes")
532 samdb.load_ldif_file_add(setup_path("provision_init.ldif"))
534 message("Setting up sam.ldb rootDSE")
535 setup_samdb_rootdse(samdb, setup_path, names)
538 message("Erasing data from partitions")
539 samdb.erase_partitions()
542 samdb.transaction_cancel()
545 samdb.transaction_commit()
550 def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain,
551 netbiosname, domainsid, keytab_path, samdb_url,
552 dns_keytab_path, dnspass, machinepass):
553 """Add DC-specific bits to a secrets database.
555 :param secretsdb: Ldb Handle to the secrets database
556 :param setup_path: Setup path function
557 :param machinepass: Machine password
559 setup_ldb(secretsdb, setup_path("secrets_dc.ldif"), {
560 "MACHINEPASS_B64": b64encode(machinepass),
563 "DNSDOMAIN": dnsdomain,
564 "DOMAINSID": str(domainsid),
565 "SECRETS_KEYTAB": keytab_path,
566 "NETBIOSNAME": netbiosname,
567 "SAM_LDB": samdb_url,
568 "DNS_KEYTAB": dns_keytab_path,
569 "DNSPASS_B64": b64encode(dnspass),
573 def setup_secretsdb(path, setup_path, session_info, credentials, lp):
574 """Setup the secrets database.
576 :param path: Path to the secrets database.
577 :param setup_path: Get the path to a setup file.
578 :param session_info: Session info.
579 :param credentials: Credentials
580 :param lp: Loadparm context
581 :return: LDB handle for the created secrets database
583 if os.path.exists(path):
585 secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
588 secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif"))
589 secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
591 secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif"))
593 if credentials is not None and credentials.authentication_requested():
594 if credentials.get_bind_dn() is not None:
595 setup_add_ldif(secrets_ldb, setup_path("secrets_simple_ldap.ldif"), {
596 "LDAPMANAGERDN": credentials.get_bind_dn(),
597 "LDAPMANAGERPASS_B64": b64encode(credentials.get_password())
600 setup_add_ldif(secrets_ldb, setup_path("secrets_sasl_ldap.ldif"), {
601 "LDAPADMINUSER": credentials.get_username(),
602 "LDAPADMINREALM": credentials.get_realm(),
603 "LDAPADMINPASS_B64": b64encode(credentials.get_password())
609 def setup_templatesdb(path, setup_path, session_info, credentials, lp):
610 """Setup the templates database.
612 :param path: Path to the database.
613 :param setup_path: Function for obtaining the path to setup files.
614 :param session_info: Session info
615 :param credentials: Credentials
616 :param lp: Loadparm context
618 templates_ldb = SamDB(path, session_info=session_info,
619 credentials=credentials, lp=lp)
622 templates_ldb.erase()
626 templates_ldb.load_ldif_file_add(setup_path("provision_templates_init.ldif"))
628 templates_ldb = SamDB(path, session_info=session_info,
629 credentials=credentials, lp=lp)
631 templates_ldb.load_ldif_file_add(setup_path("provision_templates.ldif"))
634 def setup_registry(path, setup_path, session_info, credentials, lp):
635 """Setup the registry.
637 :param path: Path to the registry database
638 :param setup_path: Function that returns the path to a setup.
639 :param session_info: Session information
640 :param credentials: Credentials
641 :param lp: Loadparm context
643 reg = registry.Registry()
644 hive = registry.open_ldb(path, session_info=session_info,
645 credentials=credentials, lp_ctx=lp)
646 reg.mount_hive(hive, "HKEY_LOCAL_MACHINE")
647 provision_reg = setup_path("provision.reg")
648 assert os.path.exists(provision_reg)
649 reg.diff_apply(provision_reg)
652 def setup_idmapdb(path, setup_path, session_info, credentials, lp):
653 """Setup the idmap database.
655 :param path: path to the idmap database
656 :param setup_path: Function that returns a path to a setup file
657 :param session_info: Session information
658 :param credentials: Credentials
659 :param lp: Loadparm context
661 if os.path.exists(path):
664 idmap_ldb = IDmapDB(path, session_info=session_info,
665 credentials=credentials, lp=lp)
668 idmap_ldb.load_ldif_file_add(setup_path("idmap_init.ldif"))
672 def setup_samdb_rootdse(samdb, setup_path, names):
673 """Setup the SamDB rootdse.
675 :param samdb: Sam Database handle
676 :param setup_path: Obtain setup path
678 setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), {
679 "SCHEMADN": names.schemadn,
680 "NETBIOSNAME": names.netbiosname,
681 "DNSDOMAIN": names.dnsdomain,
682 "REALM": names.realm,
683 "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
684 "DOMAINDN": names.domaindn,
685 "ROOTDN": names.rootdn,
686 "CONFIGDN": names.configdn,
687 "SERVERDN": names.serverdn,
691 def setup_self_join(samdb, names,
692 machinepass, dnspass,
693 domainsid, invocationid, setup_path,
695 """Join a host to its own domain."""
696 assert isinstance(invocationid, str)
697 setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), {
698 "CONFIGDN": names.configdn,
699 "SCHEMADN": names.schemadn,
700 "DOMAINDN": names.domaindn,
701 "SERVERDN": names.serverdn,
702 "INVOCATIONID": invocationid,
703 "NETBIOSNAME": names.netbiosname,
704 "DEFAULTSITE": names.sitename,
705 "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
706 "MACHINEPASS_B64": b64encode(machinepass),
707 "DNSPASS_B64": b64encode(dnspass),
708 "REALM": names.realm,
709 "DOMAIN": names.domain,
710 "DNSDOMAIN": names.dnsdomain})
711 setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), {
712 "POLICYGUID": policyguid,
713 "DNSDOMAIN": names.dnsdomain,
714 "DOMAINSID": str(domainsid),
715 "DOMAINDN": names.domaindn})
718 def setup_samdb(path, setup_path, session_info, credentials, lp,
720 domainsid, aci, domainguid, policyguid,
721 fill, adminpass, krbtgtpass,
722 machinepass, invocationid, dnspass,
723 serverrole, ldap_backend=None,
724 ldap_backend_type=None):
725 """Setup a complete SAM Database.
727 :note: This will wipe the main SAM database file!
730 erase = (fill != FILL_DRS)
732 # Also wipes the database
733 setup_samdb_partitions(path, setup_path, message=message, lp=lp,
734 credentials=credentials, session_info=session_info,
736 ldap_backend=ldap_backend, serverrole=serverrole,
737 ldap_backend_type=ldap_backend_type, erase=erase)
739 samdb = SamDB(path, session_info=session_info,
740 credentials=credentials, lp=lp)
743 # We want to finish here, but setup the index before we do so
744 message("Setting up sam.ldb index")
745 samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
748 message("Pre-loading the Samba 4 and AD schema")
749 samdb.set_domain_sid(domainsid)
750 if serverrole == "domain controller":
751 samdb.set_invocation_id(invocationid)
753 load_schema(setup_path, samdb, names.schemadn, names.netbiosname,
754 names.configdn, names.sitename, names.serverdn,
757 samdb.transaction_start()
760 message("Adding DomainDN: %s (permitted to fail)" % names.domaindn)
761 if serverrole == "domain controller":
762 domain_oc = "domainDNS"
764 domain_oc = "samba4LocalDomain"
766 setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
767 "DOMAINDN": names.domaindn,
769 "DOMAIN_OC": domain_oc
772 message("Modifying DomainDN: " + names.domaindn + "")
773 if domainguid is not None:
774 domainguid_mod = "replace: objectGUID\nobjectGUID: %s\n-" % domainguid
778 setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), {
779 "LDAPTIME": timestring(int(time.time())),
780 "DOMAINSID": str(domainsid),
781 "SCHEMADN": names.schemadn,
782 "NETBIOSNAME": names.netbiosname,
783 "DEFAULTSITE": names.sitename,
784 "CONFIGDN": names.configdn,
785 "SERVERDN": names.serverdn,
786 "POLICYGUID": policyguid,
787 "DOMAINDN": names.domaindn,
788 "DOMAINGUID_MOD": domainguid_mod,
791 message("Adding configuration container (permitted to fail)")
792 setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
793 "CONFIGDN": names.configdn,
796 message("Modifying configuration container")
797 setup_modify_ldif(samdb, setup_path("provision_configuration_basedn_modify.ldif"), {
798 "CONFIGDN": names.configdn,
799 "SCHEMADN": names.schemadn,
802 message("Adding schema container (permitted to fail)")
803 setup_add_ldif(samdb, setup_path("provision_schema_basedn.ldif"), {
804 "SCHEMADN": names.schemadn,
807 message("Modifying schema container")
809 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
811 setup_modify_ldif(samdb,
812 setup_path("provision_schema_basedn_modify.ldif"), {
813 "SCHEMADN": names.schemadn,
814 "NETBIOSNAME": names.netbiosname,
815 "DEFAULTSITE": names.sitename,
816 "CONFIGDN": names.configdn,
817 "SERVERDN": names.serverdn,
818 "PREFIXMAP_B64": b64encode(prefixmap)
821 message("Setting up sam.ldb Samba4 schema")
822 setup_add_ldif(samdb, setup_path("schema_samba4.ldif"),
823 {"SCHEMADN": names.schemadn })
824 message("Setting up sam.ldb AD schema")
825 setup_add_ldif(samdb, setup_path("schema.ldif"),
826 {"SCHEMADN": names.schemadn})
828 message("Setting up sam.ldb configuration data")
829 setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
830 "CONFIGDN": names.configdn,
831 "NETBIOSNAME": names.netbiosname,
832 "DEFAULTSITE": names.sitename,
833 "DNSDOMAIN": names.dnsdomain,
834 "DOMAIN": names.domain,
835 "SCHEMADN": names.schemadn,
836 "DOMAINDN": names.domaindn,
837 "SERVERDN": names.serverdn
840 message("Setting up display specifiers")
841 setup_add_ldif(samdb, setup_path("display_specifiers.ldif"),
842 {"CONFIGDN": names.configdn})
844 message("Adding users container (permitted to fail)")
845 setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
846 "DOMAINDN": names.domaindn})
847 message("Modifying users container")
848 setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), {
849 "DOMAINDN": names.domaindn})
850 message("Adding computers container (permitted to fail)")
851 setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
852 "DOMAINDN": names.domaindn})
853 message("Modifying computers container")
854 setup_modify_ldif(samdb, setup_path("provision_computers_modify.ldif"), {
855 "DOMAINDN": names.domaindn})
856 message("Setting up sam.ldb data")
857 setup_add_ldif(samdb, setup_path("provision.ldif"), {
858 "DOMAINDN": names.domaindn,
859 "NETBIOSNAME": names.netbiosname,
860 "DEFAULTSITE": names.sitename,
861 "CONFIGDN": names.configdn,
862 "SERVERDN": names.serverdn
865 if fill == FILL_FULL:
866 message("Setting up sam.ldb users and groups")
867 setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
868 "DOMAINDN": names.domaindn,
869 "DOMAINSID": str(domainsid),
870 "CONFIGDN": names.configdn,
871 "ADMINPASS_B64": b64encode(adminpass),
872 "KRBTGTPASS_B64": b64encode(krbtgtpass),
875 if serverrole == "domain controller":
876 message("Setting up self join")
877 setup_self_join(samdb, names=names, invocationid=invocationid,
879 machinepass=machinepass,
880 domainsid=domainsid, policyguid=policyguid,
881 setup_path=setup_path)
883 #We want to setup the index last, as adds are faster unindexed
884 message("Setting up sam.ldb index")
885 samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
887 samdb.transaction_cancel()
890 samdb.transaction_commit()
895 FILL_NT4SYNC = "NT4SYNC"
898 def provision(setup_dir, message, session_info,
899 credentials, smbconf=None, targetdir=None, samdb_fill=FILL_FULL, realm=None,
900 rootdn=None, domaindn=None, schemadn=None, configdn=None,
902 domain=None, hostname=None, hostip=None, hostip6=None,
903 domainsid=None, adminpass=None, krbtgtpass=None, domainguid=None,
904 policyguid=None, invocationid=None, machinepass=None,
905 dnspass=None, root=None, nobody=None, nogroup=None, users=None,
906 wheel=None, backup=None, aci=None, serverrole=None,
907 ldap_backend=None, ldap_backend_type=None, sitename=None):
910 :note: caution, this wipes all existing data!
913 def setup_path(file):
914 return os.path.join(setup_dir, file)
916 if domainsid is None:
917 domainsid = security.random_sid()
919 domainsid = security.Sid(domainsid)
921 if policyguid is None:
922 policyguid = str(uuid.uuid4())
923 if adminpass is None:
924 adminpass = misc.random_password(12)
925 if krbtgtpass is None:
926 krbtgtpass = misc.random_password(12)
927 if machinepass is None:
928 machinepass = misc.random_password(12)
930 dnspass = misc.random_password(12)
931 root_uid = findnss_uid([root or "root"])
932 nobody_uid = findnss_uid([nobody or "nobody"])
933 users_gid = findnss_gid([users or "users"])
935 wheel_gid = findnss_gid(["wheel", "adm"])
937 wheel_gid = findnss_gid([wheel])
939 aci = "# no aci for local ldb"
941 if targetdir is not None:
942 if (not os.path.exists(os.path.join(targetdir, "etc"))):
943 os.makedirs(os.path.join(targetdir, "etc"))
944 smbconf = os.path.join(targetdir, "etc", "smb.conf")
946 # only install a new smb.conf if there isn't one there already
947 if not os.path.exists(smbconf):
948 make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
951 lp = param.LoadParm()
954 names = guess_names(lp=lp, hostname=hostname, domain=domain,
955 dnsdomain=realm, serverrole=serverrole, sitename=sitename,
956 rootdn=rootdn, domaindn=domaindn, configdn=configdn, schemadn=schemadn,
959 paths = provision_paths_from_lp(lp, names.dnsdomain)
962 hostip = socket.getaddrinfo(names.hostname, None, socket.AF_INET, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
966 hostip6 = socket.getaddrinfo(names.hostname, None, socket.AF_INET6, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
967 except socket.gaierror:
970 if serverrole is None:
971 serverrole = lp.get("server role")
973 assert serverrole in ("domain controller", "member server", "standalone")
974 if invocationid is None and serverrole == "domain controller":
975 invocationid = str(uuid.uuid4())
977 if not os.path.exists(paths.private_dir):
978 os.mkdir(paths.private_dir)
980 ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
982 if ldap_backend is not None:
983 if ldap_backend == "ldapi":
984 # provision-backend will set this path suggested slapd command line / fedorads.inf
985 ldap_backend = "ldapi://%s" % urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="")
987 # only install a new shares config db if there is none
988 if not os.path.exists(paths.shareconf):
989 message("Setting up share.ldb")
990 share_ldb = Ldb(paths.shareconf, session_info=session_info,
991 credentials=credentials, lp=lp)
992 share_ldb.load_ldif_file_add(setup_path("share.ldif"))
995 message("Setting up secrets.ldb")
996 secrets_ldb = setup_secretsdb(paths.secrets, setup_path,
997 session_info=session_info,
998 credentials=credentials, lp=lp)
1000 message("Setting up the registry")
1001 setup_registry(paths.hklm, setup_path, session_info,
1002 credentials=credentials, lp=lp)
1004 message("Setting up templates db")
1005 setup_templatesdb(paths.templates, setup_path, session_info=session_info,
1006 credentials=credentials, lp=lp)
1008 message("Setting up idmap db")
1009 idmap = setup_idmapdb(paths.idmapdb, setup_path, session_info=session_info,
1010 credentials=credentials, lp=lp)
1012 samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info,
1013 credentials=credentials, lp=lp, names=names,
1015 domainsid=domainsid,
1016 aci=aci, domainguid=domainguid, policyguid=policyguid,
1018 adminpass=adminpass, krbtgtpass=krbtgtpass,
1019 invocationid=invocationid,
1020 machinepass=machinepass, dnspass=dnspass,
1021 serverrole=serverrole, ldap_backend=ldap_backend,
1022 ldap_backend_type=ldap_backend_type)
1024 if lp.get("server role") == "domain controller":
1025 if paths.netlogon is None:
1026 message("Existing smb.conf does not have a [netlogon] share, but you are configuring a DC.")
1027 message("Please either remove %s or see the template at %s" %
1028 ( paths.smbconf, setup_path("provision.smb.conf.dc")))
1029 assert(paths.netlogon is not None)
1031 if paths.sysvol is None:
1032 message("Existing smb.conf does not have a [sysvol] share, but you are configuring a DC.")
1033 message("Please either remove %s or see the template at %s" %
1034 (paths.smbconf, setup_path("provision.smb.conf.dc")))
1035 assert(paths.sysvol is not None)
1037 policy_path = os.path.join(paths.sysvol, names.dnsdomain, "Policies",
1038 "{" + policyguid + "}")
1039 os.makedirs(policy_path, 0755)
1040 open(os.path.join(policy_path, "GPT.INI"), 'w').write("")
1041 os.makedirs(os.path.join(policy_path, "Machine"), 0755)
1042 os.makedirs(os.path.join(policy_path, "User"), 0755)
1043 if not os.path.isdir(paths.netlogon):
1044 os.makedirs(paths.netlogon, 0755)
1046 if samdb_fill == FILL_FULL:
1047 setup_name_mappings(samdb, idmap, str(domainsid), names.domaindn,
1048 root_uid=root_uid, nobody_uid=nobody_uid,
1049 users_gid=users_gid, wheel_gid=wheel_gid)
1051 message("Setting up sam.ldb rootDSE marking as synchronized")
1052 setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"))
1054 # Only make a zone file on the first DC, it should be replicated with DNS replication
1055 if serverrole == "domain controller":
1056 secrets_ldb = Ldb(paths.secrets, session_info=session_info,
1057 credentials=credentials, lp=lp)
1058 secretsdb_become_dc(secrets_ldb, setup_path, domain=domain, realm=names.realm,
1059 netbiosname=names.netbiosname, domainsid=domainsid,
1060 keytab_path=paths.keytab, samdb_url=paths.samdb,
1061 dns_keytab_path=paths.dns_keytab, dnspass=dnspass,
1062 machinepass=machinepass, dnsdomain=names.dnsdomain)
1064 samdb = SamDB(paths.samdb, session_info=session_info,
1065 credentials=credentials, lp=lp)
1067 domainguid = samdb.searchone(basedn=domaindn, attribute="objectGUID")
1068 assert isinstance(domainguid, str)
1069 hostguid = samdb.searchone(basedn=domaindn, attribute="objectGUID",
1070 expression="(&(objectClass=computer)(cn=%s))" % names.hostname,
1071 scope=SCOPE_SUBTREE)
1072 assert isinstance(hostguid, str)
1074 create_zone_file(paths.dns, setup_path, dnsdomain=names.dnsdomain,
1075 domaindn=names.domaindn, hostip=hostip,
1076 hostip6=hostip6, hostname=names.hostname,
1077 dnspass=dnspass, realm=names.realm,
1078 domainguid=domainguid, hostguid=hostguid)
1080 create_named_conf(paths.namedconf, setup_path, realm=names.realm,
1081 dnsdomain=names.dnsdomain, private_dir=paths.private_dir)
1083 create_named_txt(paths.namedtxt, setup_path, realm=names.realm,
1084 dnsdomain=names.dnsdomain, private_dir=paths.private_dir,
1085 keytab_name=paths.dns_keytab)
1086 message("See %s for an example configuration include file for BIND" % paths.namedconf)
1087 message("and %s for further documentation required for secure DNS updates" % paths.namedtxt)
1089 create_krb5_conf(paths.krb5conf, setup_path, dnsdomain=names.dnsdomain,
1090 hostname=names.hostname, realm=names.realm)
1091 message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf)
1093 create_phpldapadmin_config(paths.phpldapadminconfig, setup_path,
1096 message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
1098 message("Once the above files are installed, your Samba4 server will be ready to use")
1099 message("Server Role: %s" % serverrole)
1100 message("Hostname: %s" % names.hostname)
1101 message("NetBIOS Domain: %s" % names.domain)
1102 message("DNS Domain: %s" % names.dnsdomain)
1103 message("DOMAIN SID: %s" % str(domainsid))
1104 message("Admin password: %s" % adminpass)
1106 result = ProvisionResult()
1107 result.domaindn = domaindn
1108 result.paths = paths
1110 result.samdb = samdb
1114 def provision_become_dc(setup_dir=None,
1115 smbconf=None, targetdir=None, realm=None,
1116 rootdn=None, domaindn=None, schemadn=None, configdn=None,
1118 domain=None, hostname=None, domainsid=None,
1119 adminpass=None, krbtgtpass=None, domainguid=None,
1120 policyguid=None, invocationid=None, machinepass=None,
1121 dnspass=None, root=None, nobody=None, nogroup=None, users=None,
1122 wheel=None, backup=None, aci=None, serverrole=None,
1123 ldap_backend=None, ldap_backend_type=None, sitename=None):
1126 """print a message if quiet is not set."""
1129 return provision(setup_dir, message, system_session(), None,
1130 smbconf=smbconf, targetdir=targetdir, samdb_fill=FILL_DRS, realm=realm,
1131 rootdn=rootdn, domaindn=domaindn, schemadn=schemadn, configdn=configdn, serverdn=serverdn,
1132 domain=domain, hostname=hostname, hostip="127.0.0.1", domainsid=domainsid, machinepass=machinepass, serverrole="domain controller", sitename=sitename)
1135 def setup_db_config(setup_path, dbdir):
1136 """Setup a Berkeley database.
1138 :param setup_path: Setup path function.
1139 :param dbdir: Database directory."""
1140 if not os.path.isdir(os.path.join(dbdir, "bdb-logs")):
1141 os.makedirs(os.path.join(dbdir, "bdb-logs"), 0700)
1142 if not os.path.isdir(os.path.join(dbdir, "tmp")):
1143 os.makedirs(os.path.join(dbdir, "tmp"), 0700)
1145 setup_file(setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"),
1146 {"LDAPDBDIR": dbdir})
1150 def provision_backend(setup_dir=None, message=None,
1151 smbconf=None, targetdir=None, realm=None,
1152 rootdn=None, domaindn=None, schemadn=None, configdn=None,
1153 domain=None, hostname=None, adminpass=None, root=None, serverrole=None,
1154 ldap_backend_type=None, ldap_backend_port=None):
1156 def setup_path(file):
1157 return os.path.join(setup_dir, file)
1159 if hostname is None:
1160 hostname = socket.gethostname().split(".")[0].lower()
1163 root = findnss(pwd.getpwnam, ["root"])[0]
1165 if adminpass is None:
1166 adminpass = misc.random_password(12)
1168 if targetdir is not None:
1169 if (not os.path.exists(os.path.join(targetdir, "etc"))):
1170 os.makedirs(os.path.join(targetdir, "etc"))
1171 smbconf = os.path.join(targetdir, "etc", "smb.conf")
1173 # only install a new smb.conf if there isn't one there already
1174 if not os.path.exists(smbconf):
1175 make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
1178 lp = param.LoadParm()
1181 names = guess_names(lp=lp, hostname=hostname, domain=domain,
1182 dnsdomain=realm, serverrole=serverrole,
1183 rootdn=rootdn, domaindn=domaindn, configdn=configdn,
1186 paths = provision_paths_from_lp(lp, names.dnsdomain)
1188 if not os.path.isdir(paths.ldapdir):
1189 os.makedirs(paths.ldapdir, 0700)
1190 schemadb_path = os.path.join(paths.ldapdir, "schema-tmp.ldb")
1192 os.unlink(schemadb_path)
1196 schemadb = Ldb(schemadb_path, lp=lp)
1198 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
1200 setup_add_ldif(schemadb, setup_path("provision_schema_basedn.ldif"),
1201 {"SCHEMADN": names.schemadn,
1204 setup_modify_ldif(schemadb,
1205 setup_path("provision_schema_basedn_modify.ldif"), \
1206 {"SCHEMADN": names.schemadn,
1207 "NETBIOSNAME": names.netbiosname,
1208 "DEFAULTSITE": DEFAULTSITE,
1209 "CONFIGDN": names.configdn,
1210 "SERVERDN": names.serverdn,
1211 "PREFIXMAP_B64": b64encode(prefixmap)
1214 setup_add_ldif(schemadb, setup_path("schema_samba4.ldif"),
1215 {"SCHEMADN": names.schemadn })
1216 setup_add_ldif(schemadb, setup_path("schema.ldif"),
1217 {"SCHEMADN": names.schemadn})
1219 if ldap_backend_type == "fedora-ds":
1220 if ldap_backend_port is not None:
1221 serverport = "ServerPort=%d" % ldap_backend_port
1225 setup_file(setup_path("fedorads.inf"), paths.fedoradsinf,
1227 "HOSTNAME": hostname,
1228 "DNSDOMAIN": names.dnsdomain,
1229 "LDAPDIR": paths.ldapdir,
1230 "DOMAINDN": names.domaindn,
1231 "LDAPMANAGERDN": names.ldapmanagerdn,
1232 "LDAPMANAGERPASS": adminpass,
1233 "SERVERPORT": serverport})
1235 setup_file(setup_path("fedorads-partitions.ldif"), paths.fedoradspartitions,
1236 {"CONFIGDN": names.configdn,
1237 "SCHEMADN": names.schemadn,
1240 mapping = "schema-map-fedora-ds-1.0"
1241 backend_schema = "99_ad.ldif"
1243 slapdcommand="Initailise Fedora DS with: setup-ds.pl --file=%s" % paths.fedoradsinf
1245 ldapuser = "--simple-bind-dn=" + names.ldapmanagerdn
1247 elif ldap_backend_type == "openldap":
1248 attrs = ["linkID", "lDAPDisplayName"]
1249 res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs)
1251 memberof_config = "# Generated from schema in %s\n" % schemadb_path
1252 refint_attributes = ""
1253 for i in range (0, len(res)):
1254 expression = "(&(objectclass=attributeSchema)(linkID=%d))" % (int(res[i]["linkID"][0])+1)
1255 target = schemadb.searchone(basedn=names.schemadn,
1256 expression=expression,
1257 attribute="lDAPDisplayName",
1258 scope=SCOPE_SUBTREE)
1259 if target is not None:
1260 refint_attributes = refint_attributes + " " + target + " " + res[i]["lDAPDisplayName"][0]
1262 memberof_config += read_and_sub_file(setup_path("memberof.conf"),
1263 { "MEMBER_ATTR" : str(res[i]["lDAPDisplayName"][0]),
1264 "MEMBEROF_ATTR" : str(target) })
1266 refint_config = read_and_sub_file(setup_path("refint.conf"),
1267 { "LINK_ATTRS" : refint_attributes})
1269 setup_file(setup_path("slapd.conf"), paths.slapdconf,
1270 {"DNSDOMAIN": names.dnsdomain,
1271 "LDAPDIR": paths.ldapdir,
1272 "DOMAINDN": names.domaindn,
1273 "CONFIGDN": names.configdn,
1274 "SCHEMADN": names.schemadn,
1275 "MEMBEROF_CONFIG": memberof_config,
1276 "REFINT_CONFIG": refint_config})
1277 setup_file(setup_path("modules.conf"), paths.modulesconf,
1278 {"REALM": names.realm})
1280 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "user"))
1281 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "config"))
1282 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "schema"))
1284 if not os.path.exists(os.path.join(paths.ldapdir, "db", "samba", "cn=samba")):
1285 os.makedirs(os.path.join(paths.ldapdir, "db", "samba", "cn=samba"), 0700)
1287 setup_file(setup_path("cn=samba.ldif"),
1288 os.path.join(paths.ldapdir, "db", "samba", "cn=samba.ldif"),
1289 { "UUID": str(uuid.uuid4()),
1290 "LDAPTIME": timestring(int(time.time()))} )
1291 setup_file(setup_path("cn=samba-admin.ldif"),
1292 os.path.join(paths.ldapdir, "db", "samba", "cn=samba", "cn=samba-admin.ldif"),
1293 {"LDAPADMINPASS_B64": b64encode(adminpass),
1294 "UUID": str(uuid.uuid4()),
1295 "LDAPTIME": timestring(int(time.time()))} )
1297 mapping = "schema-map-openldap-2.3"
1298 backend_schema = "backend-schema.schema"
1300 ldapi_uri = "ldapi://" + urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="")
1301 if ldap_backend_port is not None:
1302 server_port_string = " -h ldap://0.0.0.0:%d" % ldap_backend_port
1304 server_port_string = ""
1306 slapdcommand="Start slapd with: slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri + server_port_string
1308 ldapuser = "--username=samba-admin"
1311 schema_command = "bin/ad2oLschema --option=convert:target=" + ldap_backend_type + " -I " + setup_path(mapping) + " -H tdb://" + schemadb_path + " -O " + os.path.join(paths.ldapdir, backend_schema)
1313 os.system(schema_command)
1315 message("Your %s Backend for Samba4 is now configured, and is ready to be started" % ldap_backend_type)
1316 message("Server Role: %s" % serverrole)
1317 message("Hostname: %s" % names.hostname)
1318 message("DNS Domain: %s" % names.dnsdomain)
1319 message("Base DN: %s" % names.domaindn)
1321 if ldap_backend_type == "openldap":
1322 message("LDAP admin user: samba-admin")
1324 message("LDAP admin DN: %s" % names.ldapmanagerdn)
1326 message("LDAP admin password: %s" % adminpass)
1327 message(slapdcommand)
1328 message("Run provision with: --ldap-backend=ldapi --ldap-backend-type=" + ldap_backend_type + " --password=" + adminpass + " " + ldapuser)
1330 def create_phpldapadmin_config(path, setup_path, ldapi_uri):
1331 """Create a PHP LDAP admin configuration file.
1333 :param path: Path to write the configuration to.
1334 :param setup_path: Function to generate setup paths.
1336 setup_file(setup_path("phpldapadmin-config.php"), path,
1337 {"S4_LDAPI_URI": ldapi_uri})
1340 def create_zone_file(path, setup_path, dnsdomain, domaindn,
1341 hostip, hostip6, hostname, dnspass, realm, domainguid, hostguid):
1342 """Write out a DNS zone file, from the info in the current database.
1344 :param path: Path of the new zone file.
1345 :param setup_path: Setup path function.
1346 :param dnsdomain: DNS Domain name
1347 :param domaindn: DN of the Domain
1348 :param hostip: Local IPv4 IP
1349 :param hostip6: Local IPv6 IP
1350 :param hostname: Local hostname
1351 :param dnspass: Password for DNS
1352 :param realm: Realm name
1353 :param domainguid: GUID of the domain.
1354 :param hostguid: GUID of the host.
1356 assert isinstance(domainguid, str)
1358 if hostip6 is not None:
1359 hostip6_base_line = " IN AAAA " + hostip6
1360 hostip6_host_line = hostname + " IN AAAA " + hostip6
1362 hostip6_base_line = ""
1363 hostip6_host_line = ""
1365 setup_file(setup_path("provision.zone"), path, {
1366 "DNSPASS_B64": b64encode(dnspass),
1367 "HOSTNAME": hostname,
1368 "DNSDOMAIN": dnsdomain,
1371 "DOMAINGUID": domainguid,
1372 "DATESTRING": time.strftime("%Y%m%d%H"),
1373 "DEFAULTSITE": DEFAULTSITE,
1374 "HOSTGUID": hostguid,
1375 "HOSTIP6_BASE_LINE": hostip6_base_line,
1376 "HOSTIP6_HOST_LINE": hostip6_host_line,
1380 def create_named_conf(path, setup_path, realm, dnsdomain,
1382 """Write out a file containing zone statements suitable for inclusion in a
1383 named.conf file (including GSS-TSIG configuration).
1385 :param path: Path of the new named.conf file.
1386 :param setup_path: Setup path function.
1387 :param realm: Realm name
1388 :param dnsdomain: DNS Domain name
1389 :param private_dir: Path to private directory
1390 :param keytab_name: File name of DNS keytab file
1393 setup_file(setup_path("named.conf"), path, {
1394 "DNSDOMAIN": dnsdomain,
1396 "REALM_WC": "*." + ".".join(realm.split(".")[1:]),
1397 "PRIVATE_DIR": private_dir
1400 def create_named_txt(path, setup_path, realm, dnsdomain,
1401 private_dir, keytab_name):
1402 """Write out a file containing zone statements suitable for inclusion in a
1403 named.conf file (including GSS-TSIG configuration).
1405 :param path: Path of the new named.conf file.
1406 :param setup_path: Setup path function.
1407 :param realm: Realm name
1408 :param dnsdomain: DNS Domain name
1409 :param private_dir: Path to private directory
1410 :param keytab_name: File name of DNS keytab file
1413 setup_file(setup_path("named.txt"), path, {
1414 "DNSDOMAIN": dnsdomain,
1416 "DNS_KEYTAB": keytab_name,
1417 "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
1418 "PRIVATE_DIR": private_dir
1421 def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
1422 """Write out a file containing zone statements suitable for inclusion in a
1423 named.conf file (including GSS-TSIG configuration).
1425 :param path: Path of the new named.conf file.
1426 :param setup_path: Setup path function.
1427 :param dnsdomain: DNS Domain name
1428 :param hostname: Local hostname
1429 :param realm: Realm name
1432 setup_file(setup_path("krb5.conf"), path, {
1433 "DNSDOMAIN": dnsdomain,
1434 "HOSTNAME": hostname,
1439 def load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename,
1440 serverdn, servername):
1441 """Load schema for the SamDB.
1443 :param samdb: Load a schema into a SamDB.
1444 :param setup_path: Setup path function.
1445 :param schemadn: DN of the schema
1446 :param netbiosname: NetBIOS name of the host.
1447 :param configdn: DN of the configuration
1448 :param serverdn: DN of the server
1449 :param servername: Host name of the server
1451 schema_data = open(setup_path("schema.ldif"), 'r').read()
1452 schema_data += open(setup_path("schema_samba4.ldif"), 'r').read()
1453 schema_data = substitute_var(schema_data, {"SCHEMADN": schemadn})
1454 check_all_substituted(schema_data)
1455 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
1456 prefixmap = b64encode(prefixmap)
1458 head_data = open(setup_path("provision_schema_basedn_modify.ldif"), 'r').read()
1459 head_data = substitute_var(head_data, {
1460 "SCHEMADN": schemadn,
1461 "NETBIOSNAME": netbiosname,
1462 "CONFIGDN": configdn,
1463 "DEFAULTSITE": sitename,
1464 "PREFIXMAP_B64": prefixmap,
1465 "SERVERDN": serverdn,
1466 "SERVERNAME": servername,
1468 check_all_substituted(head_data)
1469 samdb.attach_schema_from_ldif(head_data, schema_data)