X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source4%2Fscripting%2Fbin%2Fsamba_dnsupdate;h=fcd4cc5b7da326e10f2e5c323b942d4e0fc3860d;hb=a3cd31532125ccb537af6cd9d27c761b7da4b03a;hp=b22dde8360b4b84bd88287a9f770f9bda5bc6bd5;hpb=a19d5bd771c1727b037d28d24af0b85e49bdafb2;p=samba.git diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate index b22dde8360b..fcd4cc5b7da 100755 --- a/source4/scripting/bin/samba_dnsupdate +++ b/source4/scripting/bin/samba_dnsupdate @@ -49,8 +49,7 @@ from samba.dcerpc import netlogon, winbind from samba.netcmd.dns import cmd_dns from samba import gensec from samba.kcc import kcc_utils -from samba.compat import get_string -from samba.compat import text_type +from samba.common import get_string import ldb import dns.resolver @@ -60,7 +59,7 @@ default_ttl = 900 am_rodc = False error_count = 0 -parser = optparse.OptionParser("samba_dnsupdate") +parser = optparse.OptionParser("samba_dnsupdate [options]") sambaopts = options.SambaOptions(parser) parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) @@ -91,35 +90,22 @@ lp = sambaopts.get_loadparm() domain = lp.get("realm") host = lp.get("netbios name") -if opts.all_interfaces: - all_interfaces = True -else: - all_interfaces = False +all_interfaces = opts.all_interfaces -if opts.current_ip: - IPs = opts.current_ip -else: - IPs = samba.interface_ips(lp, all_interfaces) +IPs = opts.current_ip or samba.interface_ips(lp, bool(all_interfaces)) or [] nsupdate_cmd = lp.get('nsupdate command') dns_zone_scavenging = lp.get("dns zone scavenging") if len(IPs) == 0: - print("No IP interfaces - skipping DNS updates") + print("No IP interfaces - skipping DNS updates\n") + parser.print_usage() sys.exit(0) -if opts.rpc_server_ip: - rpc_server_ip = opts.rpc_server_ip -else: - rpc_server_ip = IPs[0] +rpc_server_ip = opts.rpc_server_ip or IPs[0] -IP6s = [] -IP4s = [] -for i in IPs: - if i.find(':') != -1: - IP6s.append(i) - else: - IP4s.append(i) +IP6s = [ip for ip in IPs if ':' in ip] +IP4s = [ip for ip in IPs if ':' not in ip] smb_conf = sambaopts.get_loadparm_path() @@ -132,23 +118,18 @@ def get_possible_rw_dns_server(creds, domain): (4.6 and prior) do not maintain this value, so add NS servers as well""" - hostnames = [] ans_soa = check_one_dns_name(domain, 'SOA') - # Actually there is only one - for i in range(len(ans_soa)): - hostnames.append(str(ans_soa[i].mname).rstrip('.')) + hosts_soa = [str(a.mname).rstrip('.') for a in ans_soa] # This is not strictly legit, but old Samba domains may have an # unmaintained SOA record, so go for any NS that we can get a # ticket to. ans_ns = check_one_dns_name(domain, 'NS') - # Actually there is only one - for i in range(len(ans_ns)): - hostnames.append(str(ans_ns[i].target).rstrip('.')) + hosts_ns = [str(a.target).rstrip('.') for a in ans_ns] - return hostnames + return hosts_soa + hosts_ns def get_krb5_rw_dns_server(creds, domain): """Get a list of read-write DNS servers that we can obtain a ticket @@ -160,8 +141,7 @@ def get_krb5_rw_dns_server(creds, domain): rw_dns_servers = get_possible_rw_dns_server(creds, domain) # Actually there is only one - for i in range(len(rw_dns_servers)): - target_hostname = str(rw_dns_servers[i]) + for i, target_hostname in enumerate(rw_dns_servers): settings = {} settings["lp_ctx"] = lp settings["target_hostname"] = target_hostname @@ -181,9 +161,8 @@ def get_krb5_rw_dns_server(creds, domain): return target_hostname except RuntimeError: # Only raise an exception if they all failed - if i != len(rw_dns_servers) - 1: - pass - raise + if i == len(rw_dns_servers) - 1: + raise def get_credentials(lp): """# get credentials if we haven't got them already.""" @@ -278,9 +257,7 @@ def hostname_match(h1, h2): return h1.lower().rstrip('.') == h2.lower().rstrip('.') def get_resolver(d=None): - resolv_conf = os.getenv('RESOLV_CONF') - if not resolv_conf: - resolv_conf = '/etc/resolv.conf' + resolv_conf = os.getenv('RESOLV_CONF', default='/etc/resolv.conf') resolver = dns.resolver.Resolver(filename=resolv_conf, configure=True) if d is not None and d.nameservers != []: @@ -290,11 +267,10 @@ def get_resolver(d=None): def check_one_dns_name(name, name_type, d=None): resolver = get_resolver(d) - if d is not None and len(d.nameservers) == 0: + if d and not d.nameservers: d.nameservers = resolver.nameservers - - ans = resolver.query(name, name_type) - return ans + # dns.resolver.Answer + return resolver.query(name, name_type) def check_dns_name(d): """check that a DNS entry exists.""" @@ -443,10 +419,10 @@ def call_nsupdate(d, op="add"): assert(op in ["add", "delete"]) - if opts.verbose: - print("Calling nsupdate for %s (%s)" % (d, op)) - if opts.use_file is not None: + if opts.verbose: + print("Use File instead of nsupdate for %s (%s)" % (d, op)) + try: rfile = open(opts.use_file, 'r+') except IOError: @@ -471,37 +447,27 @@ def call_nsupdate(d, op="add"): fcntl.lockf(rfile, fcntl.LOCK_UN) return + if opts.verbose: + print("Calling nsupdate for %s (%s)" % (d, op)) + normalised_name = d.name.rstrip('.') + '.' (tmp_fd, tmpfile) = tempfile.mkstemp() f = os.fdopen(tmp_fd, 'w') - # Getting this line right is really important. When we are under - # resolv_wrapper, then we want to use RESOLV_CONF and the - # nameserver therein. The issue is that this parameter forces us - # to only ever use that server, and not some other server that the - # NS record may point to, even as we get a ticket to that other - # server. - # - # Therefore we must not set this in production, instead we want - # to find the name of a SOA for the zone and use that server. - - if os.getenv('RESOLV_CONF') and d.nameservers != []: - f.write('server %s\n' % d.nameservers[0]) - else: - resolver = get_resolver(d) + resolver = get_resolver(d) - # Local the zone for this name - zone = dns.resolver.zone_for_name(normalised_name, - resolver=resolver) + # Local the zone for this name + zone = dns.resolver.zone_for_name(normalised_name, + resolver=resolver) - # Now find the SOA, or if we can't get a ticket to the SOA, - # any server with an NS record we can get a ticket for. - # - # Thanks to the Kerberos Credentials cache this is not - # expensive inside the loop - server = get_krb5_rw_dns_server(creds, zone) - f.write('server %s\n' % server) + # Now find the SOA, or if we can't get a ticket to the SOA, + # any server with an NS record we can get a ticket for. + # + # Thanks to the Kerberos Credentials cache this is not + # expensive inside the loop + server = get_krb5_rw_dns_server(creds, zone) + f.write('server %s\n' % server) if d.type == "A": f.write("update %s %s %u A %s\n" % (op, normalised_name, default_ttl, d.ip)) @@ -600,15 +566,10 @@ def call_samba_tool(d, op="add", zone=None): args = [rpc_server_ip, zone, short_name, "AAAA", d.ip] if d.type == "SRV": if op == "add" and d.existing_port is not None: - print("Not handling modify of exising SRV %s using samba-tool" % d) + print("Not handling modify of existing SRV %s using samba-tool" % d) return False - op = "update" - args = [rpc_server_ip, zone, short_name, "SRV", - "%s %s %s %s" % (d.existing_weight, - d.existing_port, "0", "100"), - "%s %s %s %s" % (d.dest, d.port, "0", "100")] - else: - args = [rpc_server_ip, zone, short_name, "SRV", "%s %s %s %s" % (d.dest, d.port, "0", "100")] + args = [rpc_server_ip, zone, short_name, "SRV", + "%s %s %s %s" % (d.dest, d.port, "0", "100")] if d.type == "CNAME": if d.existing_cname_target is None: args = [rpc_server_ip, zone, short_name, "CNAME", d.dest] @@ -643,6 +604,14 @@ def call_samba_tool(d, op="add", zone=None): print("Failed 'samba-tool dns' based update: %s : %s" % (str(d), estr)) raise +irpc_wb = None +def cached_irpc_wb(lp): + global irpc_wb + if irpc_wb is not None: + return irpc_wb + irpc_wb = winbind.winbind("irpc:winbind_server", lp) + return irpc_wb + def rodc_dns_update(d, t, op): '''a single DNS update via the RODC netlogon call''' global sub_vars @@ -662,7 +631,7 @@ def rodc_dns_update(d, t, op): netlogon.NlDnsGenericGcAtSite : netlogon.NlDnsDomainNameAlias } - w = winbind.winbind("irpc:winbind_server", lp) + w = cached_irpc_wb(lp) dns_names = netlogon.NL_DNS_NAME_INFO_ARRAY() dns_names.count = 1 name = netlogon.NL_DNS_NAME_INFO() @@ -677,7 +646,7 @@ def rodc_dns_update(d, t, op): else: name.dns_register = False dns_names.names = [ name ] - site_name = text_type(sub_vars['SITE']) + site_name = sub_vars['SITE'] global error_count @@ -690,6 +659,9 @@ def rodc_dns_update(d, t, op): print("Error setting DNS entry of type %u: %s: %s" % (t, d, reason)) error_count = error_count + 1 + if opts.verbose: + print("Called netlogon RODC update for %s" % d) + if error_count != 0 and opts.fail_immediately: sys.exit(1) @@ -726,15 +698,9 @@ def call_rodc_update(d, op="add"): # get the list of DNS entries we should have -if opts.update_list: - dns_update_list = opts.update_list -else: - dns_update_list = lp.private_path('dns_update_list') +dns_update_list = opts.update_list or lp.private_path('dns_update_list') -if opts.update_cache: - dns_update_cache = opts.update_cache -else: - dns_update_cache = lp.private_path('dns_update_cache') +dns_update_cache = opts.update_cache or lp.private_path('dns_update_cache') krb5conf = None # only change the krb5.conf if we are not in selftest @@ -744,7 +710,18 @@ if 'SOCKET_WRAPPER_DIR' not in os.environ: krb5conf = lp.private_path('krb5.conf') os.environ['KRB5_CONFIG'] = krb5conf -file = open(dns_update_list, "r") +try: + file = open(dns_update_list, "r") +except OSError as e: + if opts.update_cache: + print("The specified update list does not exist") + else: + print("The server update list was not found, " + "and --update-list was not provided.") + print(e) + print() + parser.print_usage() + sys.exit(1) if opts.nosubs: sub_vars = {} @@ -894,7 +871,7 @@ else: use_samba_tool = opts.use_samba_tool use_nsupdate = opts.use_nsupdate # get our krb5 creds -if len(delete_list) != 0 or len(update_list) != 0 and not opts.nocreds: +if (delete_list or update_list) and not opts.nocreds: try: creds = get_credentials(lp) except RuntimeError as e: @@ -914,7 +891,7 @@ if len(delete_list) != 0 or len(update_list) != 0 and not opts.nocreds: for d in delete_list: if d.rpc or (not use_nsupdate and use_samba_tool): if opts.verbose: - print("update (samba-tool): %s" % d) + print("delete (samba-tool): %s" % d) call_samba_tool(d, op="delete", zone=d.zone) elif am_rodc: @@ -969,6 +946,7 @@ if rebuild_cache: if opts.verbose: print("Adding %s to %s" % (str(d), file_name)) wfile.write(str(d)+"\n") + wfile.flush() os.rename(tmpfile, dns_update_cache) fcntl.lockf(cfile, fcntl.LOCK_UN)