summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/samba/join.py73
-rw-r--r--python/samba/provision/sambadns.py11
2 files changed, 77 insertions, 7 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)