# and don't get swallowed by a timeout
os.environ['PYTHONUNBUFFERED'] = '1'
-# forcing GMT avoids a problem in some timezones with kerberos. Both MIT
+# forcing GMT avoids a problem in some timezones with kerberos. Both MIT and
# heimdal can get mutual authentication errors due to the 24 second difference
# between UTC and GMT when using some zone files (eg. the PDT zone from
# the US)
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
+from samba.dnsresolver import DNSResolver
import dns.resolver
import dns.exception
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))
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()
(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
- for, starting with the SOA. The SOA is the correct answer, but
+ to, starting with the SOA. The SOA is the correct answer, but
old Samba domains (4.6 and prior) do not maintain this value,
so continue with the NS servers as well until we get one that
the KDC will issue a ticket to.
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
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."""
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'
- resolver = dns.resolver.Resolver(filename=resolv_conf, configure=True)
+ resolv_conf = os.getenv('RESOLV_CONF', default='/etc/resolv.conf')
+ resolver = DNSResolver(filename=resolv_conf, configure=True)
if d is not None and d.nameservers != []:
resolver.nameservers = d.nameservers
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.resolve(name, name_type)
def check_dns_name(d):
"""check that a DNS entry exists."""
except IOError:
return False
- for line in dns_file:
- line = line.strip()
- if line == '' or line[0] == "#":
- continue
- if line.lower() == str(d).lower():
- return True
+ with dns_file:
+ for line in dns_file:
+ line = line.strip()
+ if line == '' or line[0] == "#":
+ continue
+ if line.lower() == str(d).lower():
+ return True
return False
try:
rfile = open(opts.use_file, 'r+')
except IOError:
# Perhaps create it
- rfile = open(opts.use_file, 'w+')
+ open(opts.use_file, 'w+').close()
# Open it for reading again, in case someone else got to it first
rfile = open(opts.use_file, 'r+')
fcntl.lockf(rfile, fcntl.LOCK_EX)
(file_dir, file_name) = os.path.split(opts.use_file)
(tmp_fd, tmpfile) = tempfile.mkstemp(dir=file_dir, prefix=file_name, suffix="XXXXXX")
wfile = os.fdopen(tmp_fd, 'a')
- rfile.seek(0)
for line in rfile:
if op == "delete":
l = parse_dns_line(line, {})
wfile.write(line)
if op == "add":
wfile.write(str(d)+"\n")
+ rfile.close()
+ wfile.close()
os.rename(tmpfile, opts.use_file)
- fcntl.lockf(rfile, fcntl.LOCK_UN)
return
if opts.verbose:
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]
try:
cmd = cmd_dns()
if opts.verbose:
- print("Calling samba-tool dns %s -k no -P %s" % (op, args))
- ret = cmd._run("dns", op, "-k", "no", "-P", *args)
+ print(f'Calling samba-tool dns {op} --use-kerberos off -P {args}')
+ command, args = cmd._resolve("dns", op, "--use-kerberos", "off", "-P", *args)
+ ret = command._run(*args)
if ret == -1:
if opts.fail_immediately:
sys.exit(1)
else:
name.dns_register = False
dns_names.names = [ name ]
- site_name = text_type(sub_vars['SITE'])
+ site_name = sub_vars['SITE']
global error_count
# 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
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_list:
+ 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 = {}
cfile = open(dns_update_cache, 'r+')
except IOError:
# Perhaps create it
- cfile = open(dns_update_cache, 'w+')
+ open(dns_update_cache, 'w+').close()
# Open it for reading again, in case someone else got to it first
cfile = open(dns_update_cache, 'r+')
fcntl.lockf(cfile, fcntl.LOCK_EX)
cache_list.append(c)
cache_set.add(str(c))
+cfile.close()
+
site_specific_rec = []
# read each line, and check that the DNS name exists
dns_list.append(d)
dup_set.add(str(d))
+file.close()
+
# Perform automatic site coverage by default
auto_coverage = True
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:
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:
if opts.verbose:
print("skip delete (rodc): %s" % d)
continue
- if not d.type in [ 'A', 'AAAA' ]:
+ if d.type not in [ 'A', 'AAAA' ]:
if opts.verbose:
print("delete (rodc): %s" % d)
call_rodc_update(d, op="delete")
if opts.verbose:
print("skip (rodc): %s" % d)
continue
- if not d.type in [ 'A', 'AAAA' ]:
+ if d.type not in [ 'A', 'AAAA' ]:
if opts.verbose:
print("update (rodc): %s" % d)
call_rodc_update(d)
if opts.verbose:
print("Adding %s to %s" % (str(d), file_name))
wfile.write(str(d)+"\n")
+ wfile.close()
os.rename(tmpfile, dns_update_cache)
-fcntl.lockf(cfile, fcntl.LOCK_UN)
# delete the ccache if we created it
if ccachename is not None: