The branch, master has been updated via ef13264... s4-provision: setup spn_update_list in provision via b5b8e6b... s4-dns: install samba_spnupdate via ff2edd5... s4-dns: call spn update command alongside dns update via 37dfaff... s4-param: added a "spn update command" option via fa26383... s4-dsdb: added samba_spnupdate via 570c892... s4-dns: explain what the file is for via 7872efc... s4-dns: cope better with comments in dns_update_list from 1ae9044... s4:gensec Use a different form of 'name' in GSSAPI import_name()
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit ef1326412573777b0a5457c06d130c6455932af7 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Apr 27 18:38:47 2010 +1000 s4-provision: setup spn_update_list in provision commit b5b8e6b6adc0abcb833c034f8dc33f338dd6b815 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Apr 27 18:38:25 2010 +1000 s4-dns: install samba_spnupdate commit ff2edd52cba6e99763be5193847900119670ad7e Author: Andrew Tridgell <tri...@samba.org> Date: Tue Apr 27 18:38:04 2010 +1000 s4-dns: call spn update command alongside dns update call samba_spnupdate at the same time as samba_spnupdate commit 37dfaff82cb554492fb0a3ddc95d3144d0508bc6 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Apr 27 18:37:12 2010 +1000 s4-param: added a "spn update command" option used by SPN update code commit fa26383884751c5775ccb65e3fbbf9ec7eeda28c Author: Andrew Tridgell <tri...@samba.org> Date: Tue Apr 27 18:25:55 2010 +1000 s4-dsdb: added samba_spnupdate this script adds all our required servicePrincipalName entries at runtime. The admin can add more entries to spn_update_list as needed commit 570c89287e3f5e424db65098d5e60c9e37a5b6f3 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Apr 27 18:25:06 2010 +1000 s4-dns: explain what the file is for commit 7872efcbc0d02ef5ca79abf08f3274463ff3ec26 Author: Andrew Tridgell <tri...@samba.org> Date: Tue Apr 27 18:24:52 2010 +1000 s4-dns: cope better with comments in dns_update_list ----------------------------------------------------------------------- Summary of changes: source4/dsdb/dns/dns_update.c | 46 +++++++++ source4/param/loadparm.c | 4 + source4/param/param.h | 1 + source4/script/installmisc.sh | 2 +- source4/scripting/bin/samba_dnsupdate | 11 +-- source4/scripting/bin/samba_spnupdate | 137 +++++++++++++++++++++++++++ source4/scripting/python/samba/provision.py | 6 +- source4/scripting/wscript_build | 2 +- source4/setup/dns_update_list | 2 + source4/setup/spn_update_list | 27 +++++ 10 files changed, 228 insertions(+), 10 deletions(-) create mode 100755 source4/scripting/bin/samba_spnupdate create mode 100644 source4/setup/spn_update_list Changeset truncated at 500 lines: diff --git a/source4/dsdb/dns/dns_update.c b/source4/dsdb/dns/dns_update.c index 1420bb7..7242acf 100644 --- a/source4/dsdb/dns/dns_update.c +++ b/source4/dsdb/dns/dns_update.c @@ -55,6 +55,7 @@ struct dnsupdate_service { uint32_t interval; struct tevent_timer *te; struct tevent_req *subreq; + struct tevent_req *spnreq; NTSTATUS status; } nameupdate; }; @@ -251,12 +252,42 @@ static void dnsupdate_nameupdate_done(struct tevent_req *subreq) } } + +/* + called when spn update script has finished + */ +static void dnsupdate_spnupdate_done(struct tevent_req *subreq) +{ + struct dnsupdate_service *service = tevent_req_callback_data(subreq, + struct dnsupdate_service); + int ret; + int sys_errno; + + service->nameupdate.spnreq = NULL; + + ret = samba_runcmd_recv(subreq, &sys_errno); + TALLOC_FREE(subreq); + if (ret != 0) { + service->nameupdate.status = map_nt_error_from_unix(sys_errno); + } else { + service->nameupdate.status = NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(service->nameupdate.status)) { + DEBUG(0,(__location__ ": Failed SPN update - %s\n", + nt_errstr(service->nameupdate.status))); + } else { + DEBUG(3,("Completed SPN update check OK\n")); + } +} + /* called every 'dnsupdate:name interval' seconds */ static void dnsupdate_check_names(struct dnsupdate_service *service) { const char * const *dns_update_command = lp_dns_update_command(service->task->lp_ctx); + const char * const *spn_update_command = lp_spn_update_command(service->task->lp_ctx); /* kill any existing child */ TALLOC_FREE(service->nameupdate.subreq); @@ -275,6 +306,21 @@ static void dnsupdate_check_names(struct dnsupdate_service *service) tevent_req_set_callback(service->nameupdate.subreq, dnsupdate_nameupdate_done, service); + + DEBUG(3,("Calling SPN name update script\n")); + service->nameupdate.spnreq = samba_runcmd_send(service, + service->task->event_ctx, + timeval_current_ofs(10, 0), + 2, 0, + spn_update_command, + NULL); + if (service->nameupdate.spnreq == NULL) { + DEBUG(0,(__location__ ": samba_runcmd_send() failed with no memory\n")); + return; + } + tevent_req_set_callback(service->nameupdate.spnreq, + dnsupdate_spnupdate_done, + service); } static NTSTATUS dnsupdate_nameupdate_schedule(struct dnsupdate_service *service); diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index b7dcd9b..45b2064 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -188,6 +188,7 @@ struct loadparm_global char *szNTPSignDSocketDirectory; const char **szRNDCCommand; const char **szDNSUpdateCommand; + const char **szSPNUpdateCommand; char *szNSUpdateCommand; struct parmlist_entry *param_opt; }; @@ -508,6 +509,7 @@ static struct parm_struct parm_table[] = { {"ntp signd socket directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szNTPSignDSocketDirectory), NULL, NULL }, {"rndc command", P_LIST, P_GLOBAL, GLOBAL_VAR(szRNDCCommand), NULL, NULL }, {"dns update command", P_LIST, P_GLOBAL, GLOBAL_VAR(szDNSUpdateCommand), NULL, NULL }, + {"spn update command", P_LIST, P_GLOBAL, GLOBAL_VAR(szSPNUpdateCommand), NULL, NULL }, {"nsupdate command", P_STRING, P_GLOBAL, GLOBAL_VAR(szNSUpdateCommand), NULL, NULL }, {NULL, P_BOOL, P_NONE, 0, NULL, NULL} @@ -662,6 +664,7 @@ _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, display_charset) _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, szPidDir) _PUBLIC_ FN_GLOBAL_LIST(lp_rndc_command, szRNDCCommand) _PUBLIC_ FN_GLOBAL_LIST(lp_dns_update_command, szDNSUpdateCommand) +_PUBLIC_ FN_GLOBAL_LIST(lp_spn_update_command, szSPNUpdateCommand) _PUBLIC_ FN_GLOBAL_STRING(lp_nsupdate_command, szNSUpdateCommand) _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, dcerpc_ep_servers) _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, server_services) @@ -2458,6 +2461,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) lp_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR); lp_do_global_parameter(lp_ctx, "rndc command", "/usr/sbin/rndc"); lp_do_global_parameter_var(lp_ctx, "dns update command", "%s/samba_dnsupdate", dyn_SBINDIR); + lp_do_global_parameter_var(lp_ctx, "spn update command", "%s/samba_spnupdate", dyn_SBINDIR); lp_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g"); for (i = 0; parm_table[i].label; i++) { diff --git a/source4/param/param.h b/source4/param/param.h index 5435941..8bb368f 100644 --- a/source4/param/param.h +++ b/source4/param/param.h @@ -132,6 +132,7 @@ const char *lp_socket_address(struct loadparm_context *); const char **lp_netbios_aliases(struct loadparm_context *); const char **lp_rndc_command(struct loadparm_context *); const char **lp_dns_update_command(struct loadparm_context *); +const char **lp_spn_update_command(struct loadparm_context *); bool lp_disable_netbios(struct loadparm_context *); bool lp_wins_support(struct loadparm_context *); bool lp_wins_dns_proxy(struct loadparm_context *); diff --git a/source4/script/installmisc.sh b/source4/script/installmisc.sh index d8fd156..f9ac073 100755 --- a/source4/script/installmisc.sh +++ b/source4/script/installmisc.sh @@ -57,7 +57,7 @@ do done echo "Installing sbin scripts from scripting/bin/*" -for p in upgradeprovision samba_dnsupdate +for p in upgradeprovision samba_dnsupdate samba_spnupdate do cp scripting/bin/$p $SBINDIR || exit 1 chmod a+x $SBINDIR/$p diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate index 3fe55e2..70fec25 100755 --- a/source4/scripting/bin/samba_dnsupdate +++ b/source4/scripting/bin/samba_dnsupdate @@ -150,7 +150,7 @@ def check_dns_name(d): for line in dns_file: line = line.strip() - if line[0] == "#": + if line == '' or line[0] == "#": continue if line.lower() == str(d).lower(): return True @@ -253,15 +253,12 @@ update_list = [] dns_list = [] # read each line, and check that the DNS name exists -line = file.readline() -while line: - line = line.rstrip().lstrip() - if line[0] == "#": - line = file.readline() +for line in file: + line = line.strip() + if line == '' or line[0] == "#": continue d = parse_dns_line(line, sub_vars) dns_list.append(d) - line = file.readline() # now expand the entries, if any are A record with ip set to $IP # then replace with multiple entries, one for each interface IP diff --git a/source4/scripting/bin/samba_spnupdate b/source4/scripting/bin/samba_spnupdate new file mode 100755 index 0000000..1971ea1 --- /dev/null +++ b/source4/scripting/bin/samba_spnupdate @@ -0,0 +1,137 @@ +#!/usr/bin/env python +# +# update our servicePrincipalName names from spn_update_list +# +# Copyright (C) Andrew Tridgell 2010 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +import os, sys + +# ensure we get messages out immediately, so they get in the samba logs, +# and don't get swallowed by a timeout +os.putenv('PYTHONUNBUFFERED', '1') + +# Find right directory when running from source tree +sys.path.insert(0, "bin/python") + +import samba, ldb +import optparse +from samba import getopt as options +from samba.auth import system_session +from samba.samdb import SamDB + +parser = optparse.OptionParser("samba_spnupdate") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +parser.add_option_group(options.VersionOptions(parser)) +parser.add_option("--verbose", action="store_true") + +creds = None +ccachename = None + +opts, args = parser.parse_args() + +if len(args) != 0: + parser.print_usage() + sys.exit(1) + +lp = sambaopts.get_loadparm() + +domain = lp.get("realm") +host = lp.get("netbios name") + + +# get the list of substitution vars +def get_subst_vars(samdb): + global lp + vars = {} + + vars['DNSDOMAIN'] = lp.get('realm').lower() + vars['HOSTNAME'] = lp.get('netbios name').lower() + "." + vars['DNSDOMAIN'] + vars['NETBIOSNAME'] = lp.get('netbios name').upper() + vars['WORKGROUP'] = lp.get('workgroup') + vars['NTDSGUID'] = samdb.get_ntds_GUID() + res = samdb.search(base=None, scope=ldb.SCOPE_BASE, attrs=["objectGUID"]) + guid = samdb.schema_format_value("objectGUID", res[0]['objectGUID'][0]) + vars['DOMAINGUID'] = guid + return vars + +try: + samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), lp=lp) +except ldb.LdbError, (num, msg): + print("Unable to open sam database %s : %s" % (lp.get("sam database")), msg) + sys.exit(1) + +# get the substitution dictionary +sub_vars = get_subst_vars(samdb) + +# get the list of SPN entries we should have +spn_update_list = lp.private_path('spn_update_list') + +file = open(spn_update_list, "r") + +spn_list = [] + +# build the spn list +for line in file: + line = line.strip() + if line == '' or line[0] == "#": + continue + line = samba.substitute_var(line, sub_vars) + spn_list.append(line) + +# get the current list of SPNs in our sam +res = samdb.search(base="", + expression='(&(objectClass=computer)(samaccountname=%s$))' % sub_vars['NETBIOSNAME'], + attrs=["servicePrincipalName"]) +if not res or len(res) != 1: + print("Failed to find computer object for %s$" % sub_vars['NETBIOSNAME']) + sys.exit(1) + +old_spns = [] +for s in res[0]['servicePrincipalName']: + old_spns.append(s) + +if opts.verbose: + print("Existing SPNs: %s" % old_spns) + +add_list = [] + +# work out what needs to be added +for s in spn_list: + in_list = False + for s2 in old_spns: + if s2.upper() == s.upper(): + in_list = True + break + if not in_list: + add_list.append(s) + +if opts.verbose: + print("New SPNs: %s" % add_list) + +if add_list == []: + if opts.verbose: + 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) diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 0757a72..8e79a8c 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -293,6 +293,7 @@ def provision_paths_from_lp(lp, dnsdomain): paths.privilege = os.path.join(paths.private_dir, "privilege.ldb") paths.dns = os.path.join(paths.private_dir, "dns", dnsdomain + ".zone") paths.dns_update_list = os.path.join(paths.private_dir, "dns_update_list") + paths.spn_update_list = os.path.join(paths.private_dir, "spn_update_list") 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") @@ -1556,6 +1557,9 @@ def create_zone_file(lp, message, paths, targetdir, setup_path, dnsdomain, # the substitution is done at runtime by samba_dnsupdate setup_file(setup_path("dns_update_list"), paths.dns_update_list, None) + # and the SPN update list + setup_file(setup_path("spn_update_list"), paths.spn_update_list, None) + if paths.bind_gid is not None: try: os.chown(dns_dir, -1, paths.bind_gid) @@ -1575,7 +1579,7 @@ def create_dns_update_list(lp, message, paths, setup_path): # note that we use no variable substitution on this file # the substitution is done at runtime by samba_dnsupdate setup_file(setup_path("dns_update_list"), paths.dns_update_list, None) - + setup_file(setup_path("spn_update_list"), paths.spn_update_list, None) def create_named_conf(paths, setup_path, realm, dnsdomain, private_dir): diff --git a/source4/scripting/wscript_build b/source4/scripting/wscript_build index 5911364..834e80b 100644 --- a/source4/scripting/wscript_build +++ b/source4/scripting/wscript_build @@ -1,7 +1,7 @@ #!/usr/bin/env python O755 = 493 -bld.INSTALL_FILES('${SBINDIR}','bin/upgradeprovision bin/samba_dnsupdate', +bld.INSTALL_FILES('${SBINDIR}','bin/upgradeprovision bin/samba_dnsupdate bin/samba_spnupdate', chmod=O755, python_fixup=True, flat=True) diff --git a/source4/setup/dns_update_list b/source4/setup/dns_update_list index 0e32cda..c69e155 100644 --- a/source4/setup/dns_update_list +++ b/source4/setup/dns_update_list @@ -1,3 +1,5 @@ +# this is a list of DNS entries which will be put into DNS using +# dynamic DNS update. It is processed by the samba_dnsupdate script A ${DNSDOMAIN} $IP A ${HOSTNAME} $IP CNAME ${NTDSGUID}._msdcs.${DNSDOMAIN} ${HOSTNAME} diff --git a/source4/setup/spn_update_list b/source4/setup/spn_update_list new file mode 100644 index 0000000..e015e35 --- /dev/null +++ b/source4/setup/spn_update_list @@ -0,0 +1,27 @@ +# this is a list of servicePrincipalName entries +# that we need to add on our account. It is processed by +# the samba_spnupdate script + +ldap/${HOSTNAME}/${DNSDOMAIN} +ldap/${HOSTNAME} +ldap/${NETBIOSNAME} +ldap/${HOSTNAME}/${WORKGROUP} +ldap/${NTDSGUID}._msdcs.${DNSDOMAIN} +ldap/${NETBIOSNAME}/${WORKGROUP} +E3514235-4B06-11D1-AB04-00C04FC2DCD2/${NTDSGUID}/${DNSDOMAIN} +HOST/${HOSTNAME}/${DNSDOMAIN} +HOST/${HOSTNAME} +HOST/${NETBIOSNAME} +HOST/${HOSTNAME}/${WORKGROUP} +HOST/${NETBIOSNAME}/${WORKGROUP} +RestrictedKrbHost/${NETBIOSNAME} +RestrictedKrbHost/${HOSTNAME} +GC/${HOSTNAME}/${DNSDOMAIN} +DNS/${HOSTNAME} + +# these are not supported yet +# Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/${HOSTNAME} +# TERMSRV/${HOSTNAME} +# TERMSRV/${NETBIOSNAME} +# ldap/${HOSTNAME}/DomainDnsZones.${DNSDOMAIN} +# ldap/${HOSTNAME}/ForestDnsZones.${DNSDOMAIN} -- Samba Shared Repository