X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source4%2Fscripting%2Fpython%2Fsamba%2Fprovision.py;h=1e1bf480f53259e9273a4c8cc1d8a51cbfd4c9cd;hb=986627cd67f4ff48152fa5147977813e2b190a93;hp=58c172fc0fdd62a33ae5e7d2df7dbe129310362a;hpb=4291e28a938695593dd90a30d3c2e49defba3e8b;p=abartlet%2Fsamba.git%2F.git diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 58c172fc0fd..1e1bf480f53 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -35,13 +35,14 @@ import socket import param import registry import urllib +import shutil import ldb from samba.auth import system_session, admin_session from samba import glue, version, Ldb, substitute_var, valid_netbios_name from samba import check_all_substituted, read_and_sub_file, setup_file -from samba import DS_DOMAIN_FUNCTION_2003, DS_DC_FUNCTION_2008 +from samba import DS_DOMAIN_FUNCTION_2003, DS_DC_FUNCTION_2008, DS_DC_FUNCTION_2008_R2 from samba.dcerpc import security from samba.dcerpc.misc import SEC_CHAN_BDC, SEC_CHAN_WKSTA from samba.idmap import IDmapDB @@ -294,8 +295,9 @@ def provision_paths_from_lp(lp, dnsdomain): paths.idmapdb = os.path.join(paths.private_dir, lp.get("idmap database") or "idmap.ldb") paths.secrets = os.path.join(paths.private_dir, lp.get("secrets database") or "secrets.ldb") paths.privilege = os.path.join(paths.private_dir, "privilege.ldb") - paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone") + paths.dns = os.path.join(paths.private_dir, "dns", dnsdomain + ".zone") 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") @@ -463,7 +465,11 @@ def make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, if os.path.exists(smbconf): default_lp.load(smbconf) if eadb: - posixeadb_line = "posix:eadb = " + os.path.abspath(os.path.join(os.path.join(targetdir, "private"),"eadb.tdb")) + if targetdir is not None: + privdir = os.path.join(targetdir, "private") + else: + privdir = default_lp.get("private dir") + posixeadb_line = "posix:eadb = " + os.path.abspath(os.path.join(privdir,"eadb.tdb")) else: posixeadb_line = "" @@ -646,7 +652,8 @@ def secretsdb_self_join(secretsdb, domain, secretsdb.add(msg) -def secretsdb_setup_dns(secretsdb, setup_path, realm, dnsdomain, +def secretsdb_setup_dns(secretsdb, setup_path, private_dir, + realm, dnsdomain, dns_keytab_path, dnspass): """Add DNS specific bits to a secrets database. @@ -654,6 +661,11 @@ def secretsdb_setup_dns(secretsdb, setup_path, realm, dnsdomain, :param setup_path: Setup path function :param machinepass: Machine password """ + try: + os.unlink(os.path.join(private_dir, dns_keytab_path)) + except OSError: + pass + setup_ldb(secretsdb, setup_path("secrets_dns.ldif"), { "REALM": realm, "DNSDOMAIN": dnsdomain, @@ -1053,8 +1065,8 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, FILL_FULL = "FULL" FILL_NT4SYNC = "NT4SYNC" FILL_DRS = "DRS" -SYSVOL_ACL = "O:${DOMAINSID}-500G:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;S-1-5-32-549)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)" -POLICIES_ACL = "O:${DOMAINSID}-500G:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;S-1-5-32-549)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001301bf;;;${DOMAINSID}-520)" +SYSVOL_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)" +POLICIES_ACL = "O:LAG:BAD:P(A;OICI;0x001f01ff;;;BA)(A;OICI;0x001200a9;;;SO)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001301bf;;;PA)" def set_gpo_acl(path,acl,lp,domsid): setntacl(lp,path,acl,domsid) @@ -1066,27 +1078,25 @@ def set_gpo_acl(path,acl,lp,domsid): def setsysvolacl(samdb,names,netlogon,sysvol,gid,domainsid,lp): canchown = 1 - acl = SYSVOL_ACL.replace("${DOMAINSID}",str(domainsid)) try: os.chown(sysvol,-1,gid) except: canchown = 0 - setntacl(lp,sysvol,acl,str(domainsid)) + setntacl(lp,sysvol,SYSVOL_ACL,str(domainsid)) for root, dirs, files in os.walk(sysvol, topdown=False): for name in files: if canchown: os.chown(os.path.join(root, name),-1,gid) - setntacl(lp,os.path.join(root, name),acl,str(domainsid)) + setntacl(lp,os.path.join(root, name),SYSVOL_ACL,str(domainsid)) for name in dirs: if canchown: os.chown(os.path.join(root, name),-1,gid) - setntacl(lp,os.path.join(root, name),acl,str(domainsid)) + setntacl(lp,os.path.join(root, name),SYSVOL_ACL,str(domainsid)) # Set ACL for GPO policy_path = os.path.join(sysvol, names.dnsdomain, "Policies") - acl = POLICIES_ACL.replace("${DOMAINSID}",str(domainsid)) - set_gpo_acl(policy_path,dsacl2fsacl(acl,str(domainsid)),lp,str(domainsid)) + set_gpo_acl(policy_path,dsacl2fsacl(POLICIES_ACL,str(domainsid)),lp,str(domainsid)) res = samdb.search(base="CN=Policies,CN=System,%s"%(names.domaindn), attrs=["cn","nTSecurityDescriptor"], expression="", scope=ldb.SCOPE_ONELEVEL) @@ -1163,6 +1173,10 @@ def provision(setup_dir, message, session_info, wheel_gid = findnss_gid(["wheel", "adm"]) else: wheel_gid = findnss_gid([wheel]) + try: + bind_gid = findnss_gid(["bind", "named"]) + except KeyError: + bind_gid = None if targetdir is not None: if (not os.path.exists(os.path.join(targetdir, "etc"))): @@ -1172,9 +1186,18 @@ def provision(setup_dir, message, session_info, smbconf = param.default_path() # only install a new smb.conf if there isn't one there already - if not os.path.exists(smbconf): + if os.path.exists(smbconf): + # if Samba Team members can't figure out the weird errors + # loading an empty smb.conf gives, then we need to be smarter. + # Pretend it just didn't exist --abartlet + data = open(smbconf, 'r').read() + data = data.lstrip() + if data is None or data == "": + make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, + targetdir, sid_generator, useeadb) + else: make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, - targetdir, sid_generator,useeadb) + targetdir, sid_generator, useeadb) lp = param.LoadParm() lp.load(smbconf) @@ -1186,6 +1209,8 @@ def provision(setup_dir, message, session_info, paths = provision_paths_from_lp(lp, names.dnsdomain) + paths.bind_gid = bind_gid + if hostip is None: try: hostip = socket.getaddrinfo(names.hostname, None, socket.AF_INET, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0] @@ -1339,7 +1364,8 @@ def provision(setup_dir, message, session_info, secure_channel_type=SEC_CHAN_BDC) if serverrole == "domain controller": - secretsdb_setup_dns(secrets_ldb, setup_path, + secretsdb_setup_dns(secrets_ldb, setup_path, + paths.private_dir, realm=names.realm, dnsdomain=names.dnsdomain, dns_keytab_path=paths.dns_keytab, dnspass=dnspass) @@ -1349,13 +1375,13 @@ def provision(setup_dir, message, session_info, # Only make a zone file on the first DC, it should be replicated # with DNS replication - create_zone_file(paths.dns, setup_path, dnsdomain=names.dnsdomain, + create_zone_file(lp, message, paths, targetdir, setup_path, dnsdomain=names.dnsdomain, hostip=hostip, hostip6=hostip6, hostname=names.hostname, realm=names.realm, domainguid=domainguid, ntdsguid=names.ntdsguid) - create_named_conf(paths.namedconf, setup_path, realm=names.realm, + create_named_conf(paths, setup_path, realm=names.realm, dnsdomain=names.dnsdomain, private_dir=paths.private_dir) create_named_txt(paths.namedtxt, setup_path, realm=names.realm, @@ -1378,6 +1404,16 @@ def provision(setup_dir, message, session_info, #Now commit the secrets.ldb to disk secrets_ldb.transaction_commit() + # the commit creates the dns.keytab, now chown it + dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab) + if (os.path.isfile(dns_keytab_path) and paths.bind_gid is not None): + try: + os.chmod(dns_keytab_path, 0640) + os.chown(dns_keytab_path, -1, paths.bind_gid) + except OSError: + message("Failed to chown %s to bind gid %u" % (dns_keytab_path, paths.bind_gid)) + + message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig) message("Once the above files are installed, your Samba4 server will be ready to use") @@ -1450,12 +1486,12 @@ def create_phpldapadmin_config(path, setup_path, ldapi_uri): {"S4_LDAPI_URI": ldapi_uri}) -def create_zone_file(path, setup_path, dnsdomain, +def create_zone_file(lp, message, paths, targetdir, setup_path, dnsdomain, hostip, hostip6, hostname, realm, domainguid, ntdsguid): """Write out a DNS zone file, from the info in the current database. - :param path: Path of the new zone file. + :param paths: paths object :param setup_path: Setup path function. :param dnsdomain: DNS Domain name :param domaindn: DN of the Domain @@ -1482,7 +1518,21 @@ def create_zone_file(path, setup_path, dnsdomain, hostip_base_line = "" hostip_host_line = "" - setup_file(setup_path("provision.zone"), path, { + dns_dir = os.path.dirname(paths.dns) + + try: + shutil.rmtree(dns_dir, True) + except OSError: + pass + + os.mkdir(dns_dir, 0775) + + # we need to freeze the zone while we update the contents + if targetdir is None: + rndc = lp.get("rndc command") + os.system(rndc + " freeze " + lp.get("realm")) + + setup_file(setup_path("provision.zone"), paths.dns, { "HOSTNAME": hostname, "DNSDOMAIN": dnsdomain, "REALM": realm, @@ -1496,13 +1546,26 @@ def create_zone_file(path, setup_path, dnsdomain, "HOSTIP6_HOST_LINE": hostip6_host_line, }) + if paths.bind_gid is not None: + try: + os.chown(dns_dir, -1, paths.bind_gid) + os.chown(paths.dns, -1, paths.bind_gid) + # chmod needed to cope with umask + os.chmod(dns_dir, 0775) + os.chmod(paths.dns, 0664) + except OSError: + message("Failed to chown %s to bind gid %u" % (dns_dir, paths.bind_gid)) + + if targetdir is None: + os.system(rndc + " unfreeze " + lp.get("realm")) + -def create_named_conf(path, setup_path, realm, dnsdomain, +def create_named_conf(paths, setup_path, realm, dnsdomain, private_dir): """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 paths: all paths :param setup_path: Setup path function. :param realm: Realm name :param dnsdomain: DNS Domain name @@ -1510,13 +1573,17 @@ def create_named_conf(path, setup_path, realm, dnsdomain, :param keytab_name: File name of DNS keytab file """ - setup_file(setup_path("named.conf"), path, { + setup_file(setup_path("named.conf"), paths.namedconf, { "DNSDOMAIN": dnsdomain, "REALM": realm, + "ZONE_FILE": paths.dns, "REALM_WC": "*." + ".".join(realm.split(".")[1:]), - "PRIVATE_DIR": private_dir + "NAMED_CONF": paths.namedconf, + "NAMED_CONF_UPDATE": paths.namedconf_update }) + setup_file(setup_path("named.conf.update"), paths.namedconf_update) + def create_named_txt(path, setup_path, realm, dnsdomain, private_dir, keytab_name): """Write out a file containing zone statements suitable for inclusion in a