summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/samba/join.py73
-rw-r--r--python/samba/provision/sambadns.py11
-rwxr-xr-xsource4/scripting/bin/samba_upgradedns11
-rw-r--r--source4/setup/secrets_dns.ldif2
4 files changed, 88 insertions, 9 deletions
diff --git a/python/samba/join.py b/python/samba/join.py
index c55c22cad5..b2f4da4790 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -26,9 +26,12 @@ from samba.ndr import ndr_pack
from samba.dcerpc import security, drsuapi, misc, nbt, lsa, drsblobs
from samba.credentials import Credentials, DONT_USE_KERBEROS
from samba.provision import secretsdb_self_join, provision, provision_fill, FILL_DRS, FILL_SUBDOMAIN
+from samba.provision.common import setup_path
from samba.schema import Schema
from samba.net import Net
from samba.provision.sambadns import setup_bind9_dns
+from samba import read_and_sub_file
+from base64 import b64encode
import logging
import talloc
import random
@@ -179,6 +182,19 @@ class dc_join(object):
attrs=["msDS-krbTgtLink"])
if res:
ctx.del_noerror(res[0].dn, recursive=True)
+
+ res = ctx.samdb.search(base=ctx.samdb.get_default_basedn(),
+ expression='(&(sAMAccountName=%s)(servicePrincipalName=%s))' % (ldb.binary_encode("dns-%s" % ctx.myname), ldb.binary_encode("dns/%s" % ctx.dnshostname)),
+ attrs=[])
+ if res:
+ ctx.del_noerror(res[0].dn, recursive=True)
+
+ res = ctx.samdb.search(base=ctx.samdb.get_default_basedn(),
+ expression='(sAMAccountName=%s)' % ldb.binary_encode("dns-%s" % ctx.myname),
+ attrs=[])
+ if res:
+ raise RuntimeError("Not removing account %s which looks like a Samba DNS service account but does not have servicePrincipalName=%s" % (ldb.binary_encode("dns-%s" % ctx.myname), ldb.binary_encode("dns/%s" % ctx.dnshostname)))
+
if ctx.connection_dn is not None:
ctx.del_noerror(ctx.connection_dn)
if ctx.krbtgt_dn is not None:
@@ -579,6 +595,56 @@ class dc_join(object):
"userAccountControl")
ctx.samdb.modify(m)
+ if ctx.dns_backend.startswith("BIND9_"):
+ ctx.dnspass = samba.generate_random_password(128, 255)
+
+ recs = ctx.samdb.parse_ldif(read_and_sub_file(setup_path("provision_dns_add_samba.ldif"),
+ {"DNSDOMAIN": ctx.dnsdomain,
+ "DOMAINDN": ctx.base_dn,
+ "HOSTNAME" : ctx.myname,
+ "DNSPASS_B64": b64encode(ctx.dnspass),
+ "DNSNAME" : ctx.dnshostname}))
+ for changetype, msg in recs:
+ assert changetype == ldb.CHANGETYPE_NONE
+ print "Adding DNS account %s with dns/ SPN" % msg["dn"]
+
+ # Remove dns password (we will set it as a modify, as we can't do clearTextPassword over LDAP)
+ del msg["clearTextPassword"]
+ # Remove isCriticalSystemObject for similar reasons, it cannot be set over LDAP
+ del msg["isCriticalSystemObject"]
+ try:
+ ctx.samdb.add(msg)
+ dns_acct_dn = msg["dn"]
+ except ldb.LdbError, (num, _):
+ if num != ldb.ERR_ENTRY_ALREADY_EXISTS:
+ raise
+
+ # The account password set operation should normally be done over
+ # LDAP. Windows 2000 DCs however allow this only with SSL
+ # connections which are hard to set up and otherwise refuse with
+ # ERR_UNWILLING_TO_PERFORM. In this case we fall back to libnet
+ # over SAMR.
+ print "Setting account password for %s" % ctx.samname
+ try:
+ ctx.samdb.setpassword("(&(objectClass=user)(samAccountName=dns-%s))"
+ % ldb.binary_encode(ctx.myname),
+ ctx.dnspass,
+ force_change_at_next_login=False,
+ username=ctx.samname)
+ except ldb.LdbError, (num, _):
+ if num != ldb.ERR_UNWILLING_TO_PERFORM:
+ pass
+ ctx.net.set_password(account_name="dns-" % ctx.myname,
+ domain_name=ctx.domain_name,
+ newpassword=ctx.dnspass)
+
+ res = ctx.samdb.search(base=dns_acct_dn, scope=ldb.SCOPE_BASE,
+ attrs=["msDS-KeyVersionNumber"])
+ if "msDS-KeyVersionNumber" in res[0]:
+ ctx.dns_key_version_number = int(res[0]["msDS-KeyVersionNumber"][0])
+ else:
+ ctx.dns_key_version_number = None
+
def join_add_objects2(ctx):
"""add the various objects needed for the join, for subdomains post replication"""
@@ -861,13 +927,12 @@ class dc_join(object):
key_version_number=ctx.key_version_number)
if ctx.dns_backend.startswith("BIND9_"):
- dnspass = samba.generate_random_password(128, 255)
-
setup_bind9_dns(ctx.local_samdb, secrets_ldb, security.dom_sid(ctx.domsid),
ctx.names, ctx.paths, ctx.lp, logger,
dns_backend=ctx.dns_backend,
- dnspass=dnspass, os_level=ctx.behavior_version,
- targetdir=ctx.targetdir)
+ dnspass=ctx.dnspass, os_level=ctx.behavior_version,
+ targetdir=ctx.targetdir,
+ key_version_number=ctx.dns_key_version_number)
def join_setup_trusts(ctx):
"""provision the local SAM."""
diff --git a/python/samba/provision/sambadns.py b/python/samba/provision/sambadns.py
index a5a45cf494..4acc24b699 100644
--- a/python/samba/provision/sambadns.py
+++ b/python/samba/provision/sambadns.py
@@ -620,7 +620,7 @@ def add_dc_msdcs_records(samdb, forestdn, prefix, site, dnsforest, hostname,
def secretsdb_setup_dns(secretsdb, names, private_dir, realm,
- dnsdomain, dns_keytab_path, dnspass):
+ dnsdomain, dns_keytab_path, dnspass, key_version_number):
"""Add DNS specific bits to a secrets database.
:param secretsdb: Ldb Handle to the secrets database
@@ -632,11 +632,15 @@ def secretsdb_setup_dns(secretsdb, names, private_dir, realm,
except OSError:
pass
+ if key_version_number is None:
+ key_version_number = 1
+
setup_ldb(secretsdb, setup_path("secrets_dns.ldif"), {
"REALM": realm,
"DNSDOMAIN": dnsdomain,
"DNS_KEYTAB": dns_keytab_path,
"DNSPASS_B64": b64encode(dnspass),
+ "KEY_VERSION_NUMBER": str(key_version_number),
"HOSTNAME": names.hostname,
"DNSNAME" : '%s.%s' % (
names.netbiosname.lower(), names.dnsdomain.lower())
@@ -1074,7 +1078,7 @@ def setup_ad_dns(samdb, secretsdb, domainsid, names, paths, lp, logger,
def setup_bind9_dns(samdb, secretsdb, domainsid, names, paths, lp, logger,
dns_backend, os_level, site=None, dnspass=None, hostip=None,
- hostip6=None, targetdir=None):
+ hostip6=None, targetdir=None, key_version_number=None):
"""Provision DNS information (assuming BIND9 backend in DC role)
:param samdb: LDB object connected to sam.ldb file
@@ -1107,7 +1111,8 @@ def setup_bind9_dns(samdb, secretsdb, domainsid, names, paths, lp, logger,
secretsdb_setup_dns(secretsdb, names,
paths.private_dir, realm=names.realm,
dnsdomain=names.dnsdomain,
- dns_keytab_path=paths.dns_keytab, dnspass=dnspass)
+ dns_keytab_path=paths.dns_keytab, dnspass=dnspass,
+ key_version_number=key_version_number)
create_dns_dir(logger, paths)
diff --git a/source4/scripting/bin/samba_upgradedns b/source4/scripting/bin/samba_upgradedns
index b7af98c30d..9c1a6b4d5a 100755
--- a/source4/scripting/bin/samba_upgradedns
+++ b/source4/scripting/bin/samba_upgradedns
@@ -436,10 +436,19 @@ if __name__ == '__main__':
"DNSNAME" : dnsname }
)
+ res = ldbs.sam.search(base=domaindn, scope=ldb.SCOPE_DEFAULT,
+ expression='(sAMAccountName=dns-%s)' % (hostname),
+ attrs=["msDS-KeyVersionNumber"])
+ if "msDS-KeyVersionNumber" in res[0]:
+ dns_key_version_number = int(res[0]["msDS-KeyVersionNumber"][0])
+ else:
+ dns_key_version_number = None
+
secretsdb_setup_dns(ldbs.secrets, names,
paths.private_dir, realm=names.realm,
dnsdomain=names.dnsdomain,
- dns_keytab_path=paths.dns_keytab, dnspass=dnspass)
+ dns_keytab_path=paths.dns_keytab, dnspass=dnspass,
+ key_version_number=dns_key_version_number)
else:
logger.info("dns-%s account already exists" % hostname)
diff --git a/source4/setup/secrets_dns.ldif b/source4/setup/secrets_dns.ldif
index 67fd66b057..192c06d286 100644
--- a/source4/setup/secrets_dns.ldif
+++ b/source4/setup/secrets_dns.ldif
@@ -5,7 +5,7 @@ objectClass: secret
objectClass: kerberosSecret
realm: ${REALM}
servicePrincipalName: DNS/${DNSNAME}
-msDS-KeyVersionNumber: 1
+msDS-KeyVersionNumber: ${KEY_VERSION_NUMBER}
privateKeytab: ${DNS_KEYTAB}
secret:: ${DNSPASS_B64}
samAccountName: dns-${HOSTNAME}