2 # backend code for provisioning a Samba4 server
3 # Released under the GNU GPL v3 or later
4 # Copyright Jelmer Vernooij 2007
6 # Based on the original in EJS:
7 # Copyright Andrew Tridgell 2005
10 from base64 import b64encode
16 from socket import gethostname, gethostbyname
20 from samba import Ldb, substitute_var, valid_netbios_name
21 from samba.samdb import SamDB
23 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, \
24 LDB_ERR_NO_SUCH_OBJECT, timestring, CHANGETYPE_MODIFY, CHANGETYPE_NONE
26 """Functions for setting up a Samba configuration."""
28 DEFAULTSITE = "Default-First-Site-Name"
30 class InvalidNetbiosName(Exception):
31 def __init__(self, name):
32 super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
48 self.dns_keytab = None
51 self.ldap_basedn_ldif = None
52 self.ldap_config_basedn_ldif = None
53 self.ldap_schema_basedn_ldif = None
56 def install_ok(lp, session_info, credentials):
57 """Check whether the current install seems ok.
59 :param lp: Loadparm context
60 :param session_info: Session information
61 :param credentials: Credentials
63 if lp.get("realm") == "":
65 ldb = Ldb(lp.get("sam database"), session_info=session_info,
66 credentials=credentials, lp=lp)
67 if len(ldb.search("(cn=Administrator)")) != 1:
72 def findnss(nssfn, *names):
73 """Find a user or group from a list of possibilities."""
79 raise Exception("Unable to find user/group for %s" % arguments[1])
82 def open_ldb(session_info, credentials, lp, dbname):
83 """Open a LDB, thrashing it if it is corrupt.
85 :param session_info: auth session information
86 :param credentials: credentials
87 :param lp: Loadparm context
88 :param dbname: Path of the database to open.
91 assert session_info is not None
93 return Ldb(dbname, session_info=session_info, credentials=credentials,
98 return Ldb(dbname, session_info=session_info, credentials=credentials,
102 def setup_add_ldif(ldb, ldif_path, subst_vars=None):
103 """Setup a ldb in the private dir.
105 :param ldb: LDB file to import data into
106 :param ldif_path: Path of the LDIF file to load
107 :param subst_vars: Optional variables to subsitute in LDIF.
109 assert isinstance(ldif_path, str)
111 data = open(ldif_path, 'r').read()
112 if subst_vars is not None:
113 data = substitute_var(data, subst_vars)
115 assert "${" not in data
120 def setup_modify_ldif(ldb, ldif_path, substvars=None):
121 """Modify a ldb in the private dir.
123 :param ldb: LDB object.
124 :param ldif_path: LDIF file path.
125 :param substvars: Optional dictionary with substitution variables.
127 data = open(ldif_path, 'r').read()
128 if substvars is not None:
129 data = substitute_var(data, substvars)
131 assert "${" not in data
133 ldb.modify_ldif(data)
136 def setup_ldb(ldb, ldif_path, subst_vars):
137 assert ldb is not None
138 ldb.transaction_start()
140 setup_add_ldif(ldb, ldif_path, subst_vars)
142 ldb.transaction_cancel()
144 ldb.transaction_commit()
147 def setup_file(template, fname, substvars):
148 """Setup a file in the private dir.
150 :param template: Path of the template file.
151 :param fname: Path of the file to create.
152 :param substvars: Substitution variables.
156 if os.path.exists(f):
159 data = open(template, 'r').read()
161 data = substitute_var(data, substvars)
162 assert not "${" in data
164 open(f, 'w').write(data)
167 def provision_paths_from_lp(lp, dnsdomain):
168 """Set the default paths for provisioning.
170 :param lp: Loadparm context.
171 :param dnsdomain: DNS Domain name
173 paths = ProvisionPaths()
174 private_dir = lp.get("private dir")
175 paths.shareconf = os.path.join(private_dir, "share.ldb")
176 paths.samdb = os.path.join(private_dir, lp.get("sam database") or "samdb.ldb")
177 paths.secrets = os.path.join(private_dir, lp.get("secrets database") or "secrets.ldb")
178 paths.templates = os.path.join(private_dir, "templates.ldb")
179 paths.keytab = os.path.join(private_dir, "secrets.keytab")
180 paths.dns_keytab = os.path.join(private_dir, "dns.keytab")
181 paths.dns = os.path.join(private_dir, dnsdomain + ".zone")
182 paths.winsdb = os.path.join(private_dir, "wins.ldb")
183 paths.s4_ldapi_path = os.path.join(private_dir, "ldapi")
184 paths.phpldapadminconfig = os.path.join(private_dir,
185 "phpldapadmin-config.php")
186 paths.hklm = os.path.join(private_dir, "hklm.ldb")
187 paths.sysvol = lp.get("sysvol", "path")
188 if paths.sysvol is None:
189 paths.sysvol = os.path.join(lp.get("lock dir"), "sysvol")
191 paths.netlogon = lp.get("netlogon", "path")
192 if paths.netlogon is None:
193 paths.netlogon = os.path.join(os.path.join(paths.sysvol, "scripts"))
198 def setup_name_mappings(ldb, sid, domaindn, root, nobody, nogroup, users,
200 """setup reasonable name mappings for sam names to unix names.
202 :param ldb: SamDB object.
203 :param sid: The domain sid.
204 :param domaindn: The domain DN.
205 :param root: Name of the UNIX root user.
206 :param nobody: Name of the UNIX nobody user.
207 :param nogroup: Name of the unix nobody group.
208 :param users: Name of the unix users group.
209 :param wheel: Name of the wheel group (users that can become root).
210 :param backup: Name of the backup group."""
211 # add some foreign sids if they are not present already
212 ldb.add_foreign(domaindn, "S-1-5-7", "Anonymous")
213 ldb.add_foreign(domaindn, "S-1-1-0", "World")
214 ldb.add_foreign(domaindn, "S-1-5-2", "Network")
215 ldb.add_foreign(domaindn, "S-1-5-18", "System")
216 ldb.add_foreign(domaindn, "S-1-5-11", "Authenticated Users")
218 # some well known sids
219 ldb.setup_name_mapping(domaindn, "S-1-5-7", nobody)
220 ldb.setup_name_mapping(domaindn, "S-1-1-0", nogroup)
221 ldb.setup_name_mapping(domaindn, "S-1-5-2", nogroup)
222 ldb.setup_name_mapping(domaindn, "S-1-5-18", root)
223 ldb.setup_name_mapping(domaindn, "S-1-5-11", users)
224 ldb.setup_name_mapping(domaindn, "S-1-5-32-544", wheel)
225 ldb.setup_name_mapping(domaindn, "S-1-5-32-545", users)
226 ldb.setup_name_mapping(domaindn, "S-1-5-32-546", nogroup)
227 ldb.setup_name_mapping(domaindn, "S-1-5-32-551", backup)
229 # and some well known domain rids
230 ldb.setup_name_mapping(domaindn, sid + "-500", root)
231 ldb.setup_name_mapping(domaindn, sid + "-518", wheel)
232 ldb.setup_name_mapping(domaindn, sid + "-519", wheel)
233 ldb.setup_name_mapping(domaindn, sid + "-512", wheel)
234 ldb.setup_name_mapping(domaindn, sid + "-513", users)
235 ldb.setup_name_mapping(domaindn, sid + "-520", wheel)
238 def provision_become_dc(setup_dir, message, paths, lp, session_info,
240 assert session_info is not None
243 def setup_path(file):
244 return os.path.join(setup_dir, file)
245 os.path.unlink(paths.samdb)
247 message("Setting up templates db")
248 setup_templatesdb(paths.templates, setup_path, session_info=session_info,
249 credentials=credentials, lp=lp)
251 # Also wipes the database
252 message("Setting up sam.ldb")
253 samdb = SamDB(paths.samdb, session_info=session_info,
254 credentials=credentials, lp=lp)
256 message("Setting up sam.ldb partitions")
257 setup_samdb_partitions(samdb, setup_path, schemadn, configdn, domaindn)
259 samdb = SamDB(paths.samdb, session_info=session_info,
260 credentials=credentials, lp=lp)
262 ldb.transaction_start()
264 message("Setting up sam.ldb attributes")
265 samdb.load_ldif_file_add(setup_path("provision_init.ldif"))
267 message("Setting up sam.ldb rootDSE")
268 setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn,
269 hostname, dnsdomain, realm, rootdn, configdn,
273 message("Erasing data from partitions")
274 samdb.erase_partitions()
276 message("Setting up sam.ldb indexes")
277 samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
279 samdb.transaction_cancel()
282 samdb.transaction_commit()
284 message("Setting up %s" % paths.secrets)
285 secrets_ldb = setup_secretsdb(paths.secrets, setup_path, session_info,
287 setup_ldb(secrets_ldb, setup_path("secrets_dc.ldif"),
288 { "MACHINEPASS_B64": b64encode(machinepass) })
291 def setup_secretsdb(path, setup_path, session_info, credentials, lp):
292 """Setup the secrets database.
294 :param path: Path to the secrets database.
295 :param setup_path: Get the path to a setup file.
296 :param session_info: Session info.
297 :param credentials: Credentials
298 :param lp: Loadparm context
300 if os.path.exists(path):
302 secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials, lp=lp)
304 secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif"))
305 secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif"))
309 def setup_templatesdb(path, setup_path, session_info, credentials, lp):
310 """Setup the templates database.
312 :param path: Path to the database.
313 :param setup_path: Function for obtaining the path to setup files.
314 :param session_info: Session info
315 :param credentials: Credentials
316 :param lp: Loadparm context
318 templates_ldb = SamDB(path, session_info=session_info,
319 credentials=credentials, lp=lp)
320 templates_ldb.erase()
321 templates_ldb.load_ldif_file_add(setup_path("provision_templates.ldif"))
324 def setup_registry(path, setup_path, session_info, credentials, lp):
325 """Setup the registry.
327 :param path: Path to the registry database
328 :param setup_path: Function that returns the path to a setup.
329 :param session_info: Session information
330 :param credentials: Credentials
331 :param lp: Loadparm context
333 reg = registry.Registry()
334 hive = registry.open_ldb(path, session_info=session_info,
335 credentials=credentials, lp_ctx=lp)
336 reg.mount_hive(hive, "HKEY_LOCAL_MACHINE")
337 provision_reg = setup_path("provision.reg")
338 assert os.path.exists(provision_reg)
339 reg.diff_apply(provision_reg)
342 def setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname,
343 dnsdomain, realm, rootdn, configdn, netbiosname):
344 """Setup the SamDB rootdse.
346 :param samdb: Sam Database handle
347 :param setup_path: Obtain setup path
350 setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), {
351 "SCHEMADN": schemadn,
352 "NETBIOSNAME": netbiosname,
353 "DNSDOMAIN": dnsdomain,
354 "DEFAULTSITE": DEFAULTSITE,
356 "DNSNAME": "%s.%s" % (hostname, dnsdomain),
357 "DOMAINDN": domaindn,
359 "CONFIGDN": configdn,
360 "VERSION": samba.version(),
364 def setup_samdb_partitions(samdb, setup_path, schemadn, configdn, domaindn):
365 """Setup SAM database partitions.
367 :param samdb: Sam Database handle
368 :param setup_path: Setup path function
369 :param schemadn: Schema DN.
370 :param configdn: Configuration DN.
371 :param domaindn: Domain DN.
373 #Add modules to the list to activate them by default
374 #beware often order is important
376 # Some Known ordering constraints:
377 # - rootdse must be first, as it makes redirects from "" -> cn=rootdse
378 # - objectclass must be before password_hash, because password_hash checks
379 # that the objectclass is of type person (filled in by objectclass
380 # module when expanding the objectclass list)
381 # - partition must be last
382 # - each partition has its own module list then
383 modules_list = ["rootdse",
399 modules_list2 = ["show_deleted",
402 setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
403 "SCHEMADN": schemadn,
404 "SCHEMADN_LDB": "schema.ldb",
405 "SCHEMADN_MOD2": ",objectguid",
406 "CONFIGDN": configdn,
407 "CONFIGDN_LDB": "configuration.ldb",
408 "DOMAINDN": domaindn,
409 "DOMAINDN_LDB": "users.ldb",
410 "SCHEMADN_MOD": "schema_fsmo",
411 "CONFIGDN_MOD": "naming_fsmo",
412 "CONFIGDN_MOD2": ",objectguid",
413 "DOMAINDN_MOD": "pdc_fsmo,password_hash",
414 "DOMAINDN_MOD2": ",objectguid",
415 "MODULES_LIST": ",".join(modules_list),
416 "TDB_MODULES_LIST": ","+",".join(tdb_modules_list),
417 "MODULES_LIST2": ",".join(modules_list2),
421 def setup_self_join(samdb, configdn, schemadn, domaindn,
422 netbiosname, hostname, dnsdomain, machinepass, dnspass,
423 realm, domainname, domainsid, invocationid, setup_path,
424 policyguid, hostguid=None):
425 if hostguid is not None:
426 hostguid_add = "objectGUID: %s" % hostguid
430 setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), {
431 "CONFIGDN": configdn,
432 "SCHEMADN": schemadn,
433 "DOMAINDN": domaindn,
434 "INVOCATIONID": invocationid,
435 "NETBIOSNAME": netbiosname,
436 "DEFAULTSITE": DEFAULTSITE,
437 "DNSNAME": "%s.%s" % (hostname, dnsdomain),
438 "MACHINEPASS_B64": b64encode(machinepass),
439 "DNSPASS_B64": b64encode(dnspass),
441 "DOMAIN": domainname,
442 "HOSTGUID_ADD": hostguid_add,
443 "DNSDOMAIN": dnsdomain})
444 setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), {
445 "POLICYGUID": policyguid,
446 "DNSDOMAIN": dnsdomain,
447 "DOMAINSID": str(domainsid),
448 "DOMAINDN": domaindn})
451 def setup_samdb(path, setup_path, session_info, credentials, lp,
452 schemadn, configdn, domaindn, dnsdomain, realm,
453 netbiosname, message, hostname, rootdn, erase,
454 domainsid, aci, rdn_dc, domainguid, policyguid,
455 domainname, blank, adminpass, krbtgtpass,
456 machinepass, hostguid, invocationid, dnspass):
457 # Also wipes the database
458 message("Setting up sam.ldb")
459 samdb = SamDB(path, session_info=session_info,
460 credentials=credentials, lp=lp)
462 message("Setting up sam.ldb partitions")
463 setup_samdb_partitions(samdb, setup_path, schemadn, configdn, domaindn)
465 samdb = SamDB(path, session_info=session_info,
466 credentials=credentials, lp=lp)
468 samdb.transaction_start()
470 message("Setting up sam.ldb attributes")
471 samdb.load_ldif_file_add(setup_path("provision_init.ldif"))
473 message("Setting up sam.ldb rootDSE")
474 setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn,
475 hostname, dnsdomain, realm, rootdn, configdn,
479 message("Erasing data from partitions")
480 samdb.erase_partitions()
482 samdb.transaction_cancel()
485 samdb.transaction_commit()
487 message("Pre-loading the Samba 4 and AD schema")
488 samdb = SamDB(path, session_info=session_info,
489 credentials=credentials, lp=lp)
490 samdb.set_domain_sid(domainsid)
491 load_schema(setup_path, samdb, schemadn, netbiosname, configdn)
493 samdb.transaction_start()
496 message("Adding DomainDN: %s (permitted to fail)" % domaindn)
497 setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
498 "DOMAINDN": domaindn,
503 message("Modifying DomainDN: " + domaindn + "")
504 if domainguid is not None:
505 domainguid_mod = "replace: objectGUID\nobjectGUID: %s\n-" % domainguid
509 setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), {
511 "LDAPTIME": timestring(int(time.time())),
512 "DOMAINSID": str(domainsid),
513 "SCHEMADN": schemadn,
514 "NETBIOSNAME": netbiosname,
515 "DEFAULTSITE": DEFAULTSITE,
516 "CONFIGDN": configdn,
517 "POLICYGUID": policyguid,
518 "DOMAINDN": domaindn,
519 "DOMAINGUID_MOD": domainguid_mod,
522 message("Adding configuration container (permitted to fail)")
523 setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
524 "CONFIGDN": configdn,
526 "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb",
528 message("Modifying configuration container")
529 setup_modify_ldif(samdb, setup_path("provision_configuration_basedn_modify.ldif"), {
530 "CONFIGDN": configdn,
531 "SCHEMADN": schemadn,
534 message("Adding schema container (permitted to fail)")
535 setup_add_ldif(samdb, setup_path("provision_schema_basedn.ldif"), {
536 "SCHEMADN": schemadn,
538 "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb"
540 message("Modifying schema container")
541 setup_modify_ldif(samdb, setup_path("provision_schema_basedn_modify.ldif"), {
542 "SCHEMADN": schemadn,
543 "NETBIOSNAME": netbiosname,
544 "DEFAULTSITE": DEFAULTSITE,
545 "CONFIGDN": configdn,
548 message("Setting up sam.ldb Samba4 schema")
549 setup_add_ldif(samdb, setup_path("schema_samba4.ldif"),
550 {"SCHEMADN": schemadn })
551 message("Setting up sam.ldb AD schema")
552 setup_add_ldif(samdb, setup_path("schema.ldif"),
553 {"SCHEMADN": schemadn})
555 message("Setting up sam.ldb configuration data")
556 setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
557 "CONFIGDN": configdn,
558 "NETBIOSNAME": netbiosname,
559 "DEFAULTSITE": DEFAULTSITE,
560 "DNSDOMAIN": dnsdomain,
561 "DOMAIN": domainname,
562 "SCHEMADN": schemadn,
563 "DOMAINDN": domaindn,
566 message("Setting up display specifiers")
567 setup_add_ldif(samdb, setup_path("display_specifiers.ldif"),
568 {"CONFIGDN": configdn})
570 message("Adding users container (permitted to fail)")
571 setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
572 "DOMAINDN": domaindn})
573 message("Modifying users container")
574 setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), {
575 "DOMAINDN": domaindn})
576 message("Adding computers container (permitted to fail)")
577 setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
578 "DOMAINDN": domaindn})
579 message("Modifying computers container")
580 setup_modify_ldif(samdb, setup_path("provision_computers_modify.ldif"), {
581 "DOMAINDN": domaindn})
582 message("Setting up sam.ldb data")
583 setup_add_ldif(samdb, setup_path("provision.ldif"), {
584 "DOMAINDN": domaindn,
585 "NETBIOSNAME": netbiosname,
586 "DEFAULTSITE": DEFAULTSITE,
587 "CONFIGDN": configdn,
591 message("Setting up sam.ldb users and groups")
592 setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
593 "DOMAINDN": domaindn,
594 "DOMAINSID": str(domainsid),
595 "CONFIGDN": configdn,
596 "ADMINPASS_B64": b64encode(adminpass),
597 "KRBTGTPASS_B64": b64encode(krbtgtpass),
600 if lp.get("server role") == "domain controller":
601 message("Setting up self join")
602 setup_self_join(samdb, configdn=configdn, schemadn=schemadn,
603 domaindn=domaindn, invocationid=invocationid,
604 dnspass=dnspass, netbiosname=netbiosname,
605 dnsdomain=dnsdomain, realm=realm,
606 machinepass=machinepass, domainname=domainname,
607 domainsid=domainsid, policyguid=policyguid,
608 hostname=hostname, hostguid=hostguid,
609 setup_path=setup_path)
611 message("Setting up sam.ldb index")
612 samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
614 message("Setting up sam.ldb rootDSE marking as synchronized")
615 setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"))
617 samdb.transaction_cancel()
620 samdb.transaction_commit()
624 def provision(lp, setup_dir, message, blank, paths, session_info,
625 credentials, ldapbackend, realm=None, domain=None, hostname=None,
626 hostip=None, domainsid=None, hostguid=None, adminpass=None,
627 krbtgtpass=None, domainguid=None, policyguid=None,
628 invocationid=None, machinepass=None, dnspass=None, root=None,
629 nobody=None, nogroup=None, users=None, wheel=None, backup=None,
630 aci=None, serverrole=None):
633 :note: caution, this wipes all existing data!
636 def setup_path(file):
637 return os.path.join(setup_dir, file)
641 if domainsid is None:
642 domainsid = security.random_sid()
643 if policyguid is None:
644 policyguid = uuid.random()
645 if invocationid is None:
646 invocationid = uuid.random()
647 if adminpass is None:
648 adminpass = misc.random_password(12)
649 if krbtgtpass is None:
650 krbtgtpass = misc.random_password(12)
651 if machinepass is None:
652 machinepass = misc.random_password(12)
654 dnspass = misc.random_password(12)
656 root = findnss(pwd.getpwnam, "root")[4]
658 nobody = findnss(pwd.getpwnam, "nobody")[4]
660 nogroup = findnss(grp.getgrnam, "nogroup", "nobody")[2]
662 users = findnss(grp.getgrnam, "users", "guest", "other", "unknown",
665 wheel = findnss(grp.getgrnam, "wheel", "root", "staff", "adm")[2]
667 backup = findnss(grp.getgrnam, "backup", "wheel", "root", "staff")[2]
669 aci = "# no aci for local ldb"
670 if serverrole is None:
671 serverrole = lp.get("server role")
674 realm = lp.get("realm")
676 if lp.get("realm").upper() != realm.upper():
677 raise Exception("realm '%s' in smb.conf must match chosen realm '%s'\n" %
678 (lp.get("realm"), realm))
680 assert realm is not None
681 realm = realm.upper()
684 domain = lp.get("workgroup")
686 if lp.get("workgroup").upper() != domain.upper():
687 raise Error("workgroup '%s' in smb.conf must match chosen domain '%s'\n",
688 lp.get("workgroup"), domain)
690 assert domain is not None
691 domain = domain.upper()
692 if not valid_netbios_name(domain):
693 raise InvalidNetbiosName(domain)
696 hostname = gethostname().split(".")[0].lower()
699 hostip = gethostbyname(hostname)
701 netbiosname = hostname.upper()
702 if not valid_netbios_name(netbiosname):
703 raise InvalidNetbiosName(netbiosname)
705 dnsdomain = realm.lower()
706 domaindn = "DC=" + dnsdomain.replace(".", ",DC=")
708 configdn = "CN=Configuration," + rootdn
709 schemadn = "CN=Schema," + configdn
711 rdn_dc = domaindn.split(",")[0][len("DC="):]
713 message("set DOMAIN SID: %s" % str(domainsid))
714 message("Provisioning for %s in realm %s" % (domain, realm))
715 message("Using administrator password: %s" % adminpass)
717 assert paths.smbconf is not None
719 # only install a new smb.conf if there isn't one there already
720 if not os.path.exists(paths.smbconf):
721 message("Setting up smb.conf")
722 if serverrole == "domain controller":
724 elif serverrole == "member":
725 smbconfsuffix = "member"
727 assert "Invalid server role setting: %s" % serverrole
728 setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix), paths.smbconf, {
729 "HOSTNAME": hostname,
730 "DOMAIN_CONF": domain,
732 "SERVERROLE": serverrole,
733 "NETLOGONPATH": paths.netlogon,
734 "SYSVOLPATH": paths.sysvol,
738 # only install a new shares config db if there is none
739 if not os.path.exists(paths.shareconf):
740 message("Setting up share.ldb")
741 share_ldb = Ldb(paths.shareconf, session_info=session_info,
742 credentials=credentials, lp=lp)
743 share_ldb.load_ldif_file_add(setup_path("share.ldif"))
745 message("Setting up secrets.ldb")
746 secrets_ldb = setup_secretsdb(paths.secrets, setup_path,
747 session_info=session_info,
748 credentials=credentials, lp=lp)
750 message("Setting up the registry")
751 setup_registry(paths.hklm, setup_path, session_info,
752 credentials=credentials, lp=lp)
754 message("Setting up templates db")
755 setup_templatesdb(paths.templates, setup_path, session_info=session_info,
756 credentials=credentials, lp=lp)
758 samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info, credentials=credentials,
759 lp=lp, schemadn=schemadn, configdn=configdn, domaindn=domaindn,
760 dnsdomain=dnsdomain, netbiosname=netbiosname, realm=realm, message=message,
761 hostname=hostname, rootdn=rootdn, erase=erase, domainsid=domainsid, aci=aci,
762 rdn_dc=rdn_dc, domainguid=domainguid, policyguid=policyguid,
763 domainname=domain, blank=blank, adminpass=adminpass, krbtgtpass=krbtgtpass,
764 hostguid=hostguid, invocationid=invocationid, machinepass=machinepass,
767 if lp.get("server role") == "domain controller":
768 os.makedirs(os.path.join(paths.sysvol, dnsdomain, "Policies", "{" + policyguid + "}"), 0755)
769 os.makedirs(os.path.join(paths.sysvol, dnsdomain, "Policies", "{" + policyguid + "}", "Machine"), 0755)
770 os.makedirs(os.path.join(paths.sysvol, dnsdomain, "Policies", "{" + policyguid + "}", "User"), 0755)
771 if not os.path.isdir(paths.netlogon):
772 os.makedirs(paths.netlogon, 0755)
773 secrets_ldb = Ldb(paths.secrets, session_info=session_info, credentials=credentials, lp=lp)
774 setup_ldb(secrets_ldb, setup_path("secrets_dc.ldif"), {
775 "MACHINEPASS_B64": b64encode(machinepass),
778 "LDAPTIME": timestring(int(time.time())),
779 "DNSDOMAIN": dnsdomain,
780 "DOMAINSID": str(domainsid),
781 "SECRETS_KEYTAB": paths.keytab,
782 "NETBIOSNAME": netbiosname,
783 "SAM_LDB": paths.samdb,
784 "DNS_KEYTAB": paths.dns_keytab,
785 "DNSPASS_B64": b64encode(dnspass),
789 setup_name_mappings(samdb, str(domainsid),
790 domaindn, root=root, nobody=nobody,
791 nogroup=nogroup, wheel=wheel, users=users,
794 message("Setting up phpLDAPadmin configuration")
795 create_phplpapdadmin_config(paths.phpldapadminconfig, setup_path, paths.s4_ldapi_path)
797 message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
799 if lp.get("server role") == "domain controller":
800 samdb = SamDB(paths.samdb, session_info=session_info,
801 credentials=credentials, lp=lp)
803 domainguid = samdb.searchone(domaindn, "objectGUID")
804 assert isinstance(domainguid, str)
805 hostguid = samdb.searchone(domaindn, "objectGUID",
806 expression="(&(objectClass=computer)(cn=%s))" % hostname,
808 assert isinstance(hostguid, str)
810 message("Setting up DNS zone: %s" % dnsdomain)
811 create_zone_file(paths.dns, setup_path, samdb,
812 hostname=hostname, hostip=hostip, dnsdomain=dnsdomain,
813 domaindn=domaindn, dnspass=dnspass, realm=realm,
814 domainguid=domainguid, hostguid=hostguid)
815 message("Please install the zone located in %s into your DNS server" % paths.dns)
819 def create_phplpapdadmin_config(path, setup_path, s4_ldapi_path):
820 """Create a PHP LDAP admin configuration file.
822 :param path: Path to write the configuration to.
823 :param setup_path: Function to generate setup paths.
824 :param s4_ldapi_path: Path to Samba 4 LDAPI socket.
826 setup_file(setup_path("phpldapadmin-config.php"),
827 path, {"S4_LDAPI_URI": "ldapi://%s" % s4_ldapi_path.replace("/", "%2F")})
830 def create_zone_file(path, setup_path, samdb, dnsdomain, domaindn,
831 hostip, hostname, dnspass, realm, domainguid, hostguid):
832 """Write out a DNS zone file, from the info in the current database.
834 :param path: Path of the new file.
835 :param setup_path": Setup path function.
836 :param samdb: SamDB object
837 :param dnsdomain: DNS Domain name
838 :param domaindn: DN of the Domain
839 :param hostip: Local IP
840 :param hostname: Local hostname
841 :param dnspass: Password for DNS
842 :param realm: Realm name
843 :param domainguid: GUID of the domain.
844 :param hostguid: GUID of the host.
847 setup_file(setup_path("provision.zone"), path, {
848 "DNSPASS_B64": b64encode(dnspass),
849 "HOSTNAME": hostname,
850 "DNSDOMAIN": dnsdomain,
853 "DOMAINGUID": domainguid,
854 "DATESTRING": time.strftime("%Y%m%d%H"),
855 "DEFAULTSITE": DEFAULTSITE,
856 "HOSTGUID": hostguid,
860 def load_schema(setup_path, samdb, schemadn, netbiosname, configdn):
863 :param samdb: Load a schema into a SamDB.
864 :param setup_path: Setup path function.
865 :param schemadn: DN of the schema
866 :param netbiosname: NetBIOS name of the host.
867 :param configdn: DN of the configuration
869 schema_data = open(setup_path("schema.ldif"), 'r').read()
870 schema_data += open(setup_path("schema_samba4.ldif"), 'r').read()
871 schema_data = substitute_var(schema_data, {"SCHEMADN": schemadn})
872 head_data = open(setup_path("provision_schema_basedn_modify.ldif"), 'r').read()
873 head_data = substitute_var(head_data, {
874 "SCHEMADN": schemadn,
875 "NETBIOSNAME": netbiosname,
876 "CONFIGDN": configdn,
877 "DEFAULTSITE": DEFAULTSITE})
878 samdb.attach_schema_from_ldif(head_data, schema_data)