diff --git a/ipa-client/ipaclient/ipadiscovery.py b/ipa-client/ipaclient/ipadiscovery.py index 2bd1519..8f478c0 100644 --- a/ipa-client/ipaclient/ipadiscovery.py +++ b/ipa-client/ipaclient/ipadiscovery.py @@ -19,7 +19,7 @@ import socket import logging -import ipa.dnsclient +import dns.resolver import ldap from ldap import LDAPError @@ -193,56 +193,50 @@ class IPADiscovery: servers = "" rserver = "" - qname = "_ldap._tcp."+tdomain - # terminate the name - if not qname.endswith("."): - qname += "." - results = ipa.dnsclient.query(qname, ipa.dnsclient.DNS_C_IN, ipa.dnsclient.DNS_T_SRV) - + qname = "_ldap._tcp." + tdomain + try: + results = dns.resolver.query(qname, dns.rdatatype.SRV) + except: + return "" + for result in results: - if result.dns_type == ipa.dnsclient.DNS_T_SRV: - rserver = result.rdata.server.rstrip(".") - if result.rdata.port and result.rdata.port != 389: - rserver += ":" + str(result.rdata.port) - if servers: - servers += "," + rserver - else: - servers = rserver - break + rserver = result.target.to_text(True) + if result.port and result.port != 389: + rserver += ":" + str(result.port) + if servers: + servers += "," + rserver + else: + servers = rserver return servers def ipadnssearchkrb(self, tdomain): realm = "" kdc = "" - # now, check for a Kerberos realm the local host or domain is in - qname = "_kerberos." + tdomain - # terminate the name - if not qname.endswith("."): - qname += "." - results = ipa.dnsclient.query(qname, ipa.dnsclient.DNS_C_IN, ipa.dnsclient.DNS_T_TXT) - - for result in results: - if result.dns_type == ipa.dnsclient.DNS_T_TXT: - realm = result.rdata.data - if realm: - break - - if realm: - # now fetch server information for the realm - qname = "_kerberos._udp." + tdomain - # terminate the name - if not qname.endswith("."): - qname += "." - results = ipa.dnsclient.query(qname, ipa.dnsclient.DNS_C_IN, ipa.dnsclient.DNS_T_SRV) + try: + # now, check for a Kerberos realm the local host or domain is in + qname = "_kerberos." + tdomain + results = dns.resolver.query(qname, dns.rdatatype.TXT, dns.rdataclass.IN) + for result in results: - if result.dns_type == ipa.dnsclient.DNS_T_SRV: - qname = result.rdata.server.rstrip(".") - if result.rdata.port and result.rdata.port != 88: - qname += ":" + str(result.rdata.port) + if result.rdtype == dns.rdatatype.TXT: + realm = result.strings[0] + if realm: + break + + if realm: + # now fetch server information for the realm + qname = "_kerberos._udp." + tdomain + results = dns.resolver.query(qname, dns.rdatatype.SRV, dns.rdataclass.IN) + for result in results: + qname = result.target.to_text(True) + if result.port and result.port != 88: + qname += ":" + str(result.port) if kdc: kdc += "," + qname else: kdc = qname + except: + pass return [realm, kdc] diff --git a/ipa-python/README b/ipa-python/README index 99fcccc..7c139c0 100644 --- a/ipa-python/README +++ b/ipa-python/README @@ -4,11 +4,10 @@ geared currently towards command-line tools. A brief overview: aci.py - a basic LDAP ACI parser for doing delegations. -config.py - identify the IPA server domain and realm. It uses dnsclient to +config.py - identify the IPA server domain and realm. It uses pythondns to try to detect this information first and will fall back to /etc/ipa/ipa.conf if that fails. ipaadminutil.py - routines to help reduce the number of entries from a search -dnsclient.py - find IPA information via DNS ipaclient.py - the main interface for any command-line tools. When initialized if transport is True then it means the IPA server is on the diff --git a/ipa-python/config.py b/ipa-python/config.py index 5a9770e..b310b60 100644 --- a/ipa-python/config.py +++ b/ipa-python/config.py @@ -22,7 +22,7 @@ from optparse import OptionParser import krbV import socket -import ipa.dnsclient +import dns.resolver import re class IPAConfigError(Exception): @@ -78,7 +78,6 @@ def __parse_config(): pass def __discover_config(): - rl = 0 try: if not config.default_realm: krbctx = krbV.default_context() @@ -86,33 +85,26 @@ def __discover_config(): if not config.default_realm: return False - if not config.default_domain: - #try once with REALM -> domain - dom_name = config.default_realm.lower() - name = "_ldap._tcp."+dom_name+"." - rs = ipa.dnsclient.query(name, ipa.dnsclient.DNS_C_IN, ipa.dnsclient.DNS_T_SRV) - rl = len(rs) - if rl == 0: - #try cycling on domain components of FQDN - dom_name = socket.getfqdn() - while rl == 0: - tok = dom_name.find(".") - if tok == -1: - return False - dom_name = dom_name[tok+1:] - name = "_ldap._tcp." + dom_name + "." - rs = ipa.dnsclient.query(name, ipa.dnsclient.DNS_C_IN, ipa.dnsclient.DNS_T_SRV) - rl = len(rs) - - config.default_domain = dom_name - - if rl == 0: - name = "_ldap._tcp."+config.default_domain+"." - rs = ipa.dnsclient.query(name, ipa.dnsclient.DNS_C_IN, ipa.dnsclient.DNS_T_SRV) - - for r in rs: - if r.dns_type == ipa.dnsclient.DNS_T_SRV: - rsrv = r.rdata.server.rstrip(".") + if config.default_domain: + dom_names = [config.default_domain] + else: + dom_names = [config.default_realm.lower()] + fqdn_components = socket.getfqdn().split(".") + for i in range(0, len(fqdn_components)): + dom_names.append(".".join(fqdn_components[i:])) + + for name in dom_names: + try: + results = dns.resolver.query("_ldap._tcp." + name, dns.rdatatype.SRV) + except dns.resolver.NoAnswer: + pass + else: + config.default_domain = name + break + + for result in results: + if result.rdtype == dns.rdatatype.SRV: + rsrv = result.target.to_text(True) config.default_server.append(rsrv) except: diff --git a/ipa-server/ipaserver/installutils.py b/ipa-server/ipaserver/installutils.py index ee3c1c7..5b34bf0 100644 --- a/ipa-server/ipaserver/installutils.py +++ b/ipa-server/ipaserver/installutils.py @@ -30,7 +30,8 @@ import struct import fcntl from ipa import ipautil -from ipa import dnsclient +import dns.resolver +import dns.reversename def get_fqdn(): fqdn = "" @@ -67,22 +68,28 @@ def verify_fqdn(host_name): raise RuntimeError("The host name %s does not match the reverse lookup %s" % (host_name, revname)) # Verify this is NOT a CNAME - rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_CNAME) - if len(rs) != 0: - for rsn in rs: - if rsn.dns_type == dnsclient.DNS_T_CNAME: - raise RuntimeError("The IPA Server Hostname cannot be a CNAME, only A names are allowed.") + try: + results = dns.resolver.query(host_name, dns.rdatatype.CNAME) + except dns.resolver.NoAnswer: + pass + except: + raise RuntimeError("Unable to resolve host name, check /etc/hosts or DNS name resolution") + else: + raise RuntimeError("The IPA Server Hostname cannot be a CNAME, only A names are allowed.") # Verify that it is a DNS A record - rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_A) - if len(rs) == 0: + try: + results = dns.resolver.query(host_name) + except dns.resolver.NoAnswer: print "Warning: Hostname (%s) not found in DNS" % host_name return + except: + raise RuntimeError("Unable to resolve host name, check /etc/hosts or DNS name resolution") rec = None - for rsn in rs: - if rsn.dns_type == dnsclient.DNS_T_A: - rec = rsn + for result in results.response.answer: + if result.rdtype == dns.rdatatype.A: + rec = result break if rec == None: @@ -90,26 +97,15 @@ def verify_fqdn(host_name): return # Compare the forward and reverse - forward = rec.dns_name + forward = rec.name.to_text() - addr = socket.inet_ntoa(struct.pack('