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
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")
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 = ""
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.
: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,
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)
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)
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"))):
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)
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]
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)
# 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,
#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")
{"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
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,
"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
: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