From 31310826e02a398eec6569a9150a798ee216f745 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Sep 2010 20:47:03 -0700 Subject: s4-spnupdate: when we are a RODC we need to use the WriteSPN DRS call we can't do SPN updates via sam writes and replication, as the sam is read-only --- source4/scripting/bin/samba_spnupdate | 67 +++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 10 deletions(-) (limited to 'source4/scripting/bin/samba_spnupdate') diff --git a/source4/scripting/bin/samba_spnupdate b/source4/scripting/bin/samba_spnupdate index b6501fbc47..6a69f48a45 100755 --- a/source4/scripting/bin/samba_spnupdate +++ b/source4/scripting/bin/samba_spnupdate @@ -108,9 +108,6 @@ except ldb.LdbError, (num, msg): print("Unable to open sam database %s : %s" % (lp.get("sam database"), msg)) sys.exit(1) -if samdb.am_rodc(): - # don't try and update SPNs on RODC - exit(0) # get the substitution dictionary sub_vars = get_subst_vars(samdb) @@ -138,6 +135,8 @@ if not res or len(res) != 1: print("Failed to find computer object for %s$" % sub_vars['NETBIOSNAME']) sys.exit(1) +machine_dn = res[0]["dn"] + old_spns = [] for s in res[0]['servicePrincipalName']: old_spns.append(s) @@ -165,10 +164,58 @@ if add_list == []: print("Nothing to add") sys.exit(0) -# build the modify request -msg = ldb.Message() -msg.dn = res[0]['dn'] -msg[""] = ldb.MessageElement(add_list, - ldb.FLAG_MOD_ADD, "servicePrincipalName") -res = samdb.modify(msg) -sys.exit(0) +def local_update(add_list): + '''store locally''' + global res + msg = ldb.Message() + msg.dn = res[0]['dn'] + msg[""] = ldb.MessageElement(add_list, + ldb.FLAG_MOD_ADD, "servicePrincipalName") + res = samdb.modify(msg) + +def call_rodc_update(d): + '''RODCs need to use the writeSPN DRS call''' + global lp, sub_vars + from samba import drs_utils + from samba.dcerpc import drsuapi, nbt + from samba.net import Net + + if opts.verbose: + print("Using RODC SPN update") + + creds = credopts.get_credentials(lp) + creds.set_machine_account(lp) + + net = Net(creds=creds, lp=lp) + try: + cldap_ret = net.finddc(domain, nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE) + except Exception, reason: + print("Unable to find writeable DC for domain '%s' to send DRS writeSPN to : %s" % (domain, reason)) + sys.exit(1) + server = cldap_ret.pdc_dns_name + try: + drs = drsuapi.drsuapi('ncacn_ip_tcp:%s[seal,print]' % server, lp, creds) + drs_handle = drs_utils.drs_DsBind(drs) + except Exception, reason: + print("Unable to connect to DC '%s' for domain '%s' : %s" % (server, domain, reason)) + sys.exit(1) + req1 = drsuapi.DsWriteAccountSpnRequest1() + req1.operation = drsuapi.DRSUAPI_DS_SPN_OPERATION_ADD + req1.object_dn = str(machine_dn) + req1.count = 0 + spn_names = [] + for n in add_list: + if n.find('E3514235-4B06-11D1-AB04-00C04FC2DCD2') != -1: + # this one isn't allowed for RODCs, but we don't know why yet + continue + ns = drsuapi.DsNameString() + ns.str = n + spn_names.append(ns) + req1.count = req1.count + 1 + req1.spn_names = spn_names + (level, res) = drs.DsWriteAccountSpn(drs_handle, 1, req1) + +if samdb.am_rodc(): + call_rodc_update(add_list) +else: + local_update(add_list) -- cgit