Currently, verify_fqdn() function raises RuntimeError for every
problem with the hostname. This makes it difficult for tools
like ipa-replica-prepare to behave differently for a subset of
raised errors (for example to be able to create a DNS record for
new replica when verify_fqdn() reports a lookup error).

Implement own exceptions for verify_fqdn() that they can be safely
used to distinguish the error type.

https://fedorahosted.org/freeipa/ticket/1899

>From e93a70794e93264ef82756e21e8149403a9fc754 Mon Sep 17 00:00:00 2001
From: Martin Kosek <[email protected]>
Date: Tue, 4 Oct 2011 14:31:00 +0200
Subject: [PATCH] Improve ipa-replica-prepare DNS check

Currently, verify_fqdn() function raises RuntimeError for every
problem with the hostname. This makes it difficult for tools
like ipa-replica-prepare to behave differently for a subset of
raised errors (for example to be able to create a DNS record for
new replica when verify_fqdn() reports a lookup error).

Implement own exceptions for verify_fqdn() that they can be safely
used to distinguish the error type.

https://fedorahosted.org/freeipa/ticket/1899
---
 install/tools/ipa-ca-install      |    4 +-
 install/tools/ipa-replica-install |    4 +-
 install/tools/ipa-replica-prepare |    6 ++--
 install/tools/ipa-server-install  |   15 ++++---------
 ipaserver/install/installutils.py |   41 +++++++++++++++++++++++++-----------
 5 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index 37fa6269b91dcd1174225a93ac5974ddc04e5d3a..ad617200700124da07265531099656b7d4603fa3 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -30,7 +30,7 @@ from ipaserver.install import installutils, service
 from ipaserver.install import certs
 from ipaserver.install.installutils import HostnameLocalhost
 from ipaserver.install.installutils import ReplicaConfig, expand_replica_info, read_replica_info
-from ipaserver.install.installutils import get_host_name
+from ipaserver.install.installutils import get_host_name, BadHostError
 from ipaserver.install import dsinstance, cainstance
 from ipaserver.install.replication import replica_conn_check
 from ipapython import version
@@ -117,7 +117,7 @@ def main():
     config.dirman_password = dirman_password
     try:
         host = get_host_name(options.no_host_dns)
-    except RuntimeError, e:
+    except BadHostError, e:
         logging.error(str(e))
         sys.exit(1)
     if config.host_name != host:
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index 62380443afa228315ebe7c598fe0e5427c7afb93..c2a0de22323d559fa25f513b6297f40d9ae94e86 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -32,7 +32,7 @@ from ipaserver.install import bindinstance, httpinstance, ntpinstance, certs
 from ipaserver.install.replication import replica_conn_check
 from ipaserver.install.installutils import HostnameLocalhost, resolve_host
 from ipaserver.install.installutils import ReplicaConfig, expand_replica_info, read_replica_info
-from ipaserver.install.installutils import get_host_name
+from ipaserver.install.installutils import get_host_name, BadHostError
 from ipaserver.plugins.ldap2 import ldap2
 from ipaserver.install import cainstance
 from ipapython import version
@@ -328,7 +328,7 @@ def main():
     config.dirman_password = dirman_password
     try:
         host = get_host_name(options.no_host_dns)
-    except RuntimeError, e:
+    except BadHostError, e:
         logging.error(str(e))
         sys.exit(1)
     if config.host_name != host:
diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare
index 05115ac3ccdfdca87960025811dc992c5d6ab530..714f465d120083c502e9a83238f3bad61be3b443 100755
--- a/install/tools/ipa-replica-prepare
+++ b/install/tools/ipa-replica-prepare
@@ -29,7 +29,7 @@ from ipapython import ipautil
 from ipaserver.install import bindinstance, dsinstance, installutils, certs
 from ipaserver.install.bindinstance import add_zone, add_reverse_zone, add_fwd_rr, add_ptr_rr
 from ipaserver.install.replication import enable_replication_version_checking
-from ipaserver.install.installutils import resolve_host
+from ipaserver.install.installutils import resolve_host, BadHostError, HostLookupError
 from ipaserver.plugins.ldap2 import ldap2
 from ipapython import version
 from ipapython.config import IPAOptionParser
@@ -250,9 +250,9 @@ def main():
 
     try:
         installutils.verify_fqdn(replica_fqdn, system_name_check=False)
-    except RuntimeError, e:
+    except BadHostError, e:
         msg = str(e)
-        if msg.startswith('Unable to resolve host name'):
+        if isinstance(e, HostLookupError):
             if options.ip_address is None:
                 if bindinstance.dns_container_exists(api.env.host,
                     api.env.basedn):
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 504d6af50f70278864dacf44cac9e4bbc832e069..e4484b77c27364feff03847323735920a6814823 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -368,15 +368,10 @@ def read_host_name(host_default,no_host_dns=False):
     print ""
     if host_default == "":
         host_default = "master.example.com"
-    while True:
-        host_name = user_input("Server host name", host_default, allow_empty = False)
-        print ""
-        try:
-            verify_fqdn(host_name,no_host_dns)
-        except Exception, e:
-            raise e
-        else:
-            break
+    host_name = user_input("Server host name", host_default, allow_empty = False)
+    print ""
+    verify_fqdn(host_name,no_host_dns)
+
     return host_name
 
 def read_domain_name(domain_name, unattended):
@@ -723,7 +718,7 @@ def main():
             host_name = host_default
         else:
             host_name = read_host_name(host_default,options.no_host_dns)
-    except RuntimeError, e:
+    except BadHostError, e:
         sys.exit(str(e) + "\n")
 
     host_name = host_name.lower()
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index 44292fd4c303c0caa5d77e525dd1041095543b51..5772f1a4d16ea83406958dc32b005eab79e9f8b0 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -38,7 +38,19 @@ from ipapython import ipautil, dnsclient, sysrestore
 # Used to determine install status
 IPA_MODULES = ['httpd', 'ipa_kpasswd', 'dirsrv', 'pki-cad', 'pkids', 'install', 'krb5kdc', 'ntpd', 'named']
 
-class HostnameLocalhost(Exception):
+class BadHostError(Exception):
+    pass
+
+class HostLookupError(BadHostError):
+    pass
+
+class HostForwardLookupError(HostLookupError):
+    pass
+
+class HostReverseLookupError(HostLookupError):
+    pass
+
+class HostnameLocalhost(HostLookupError):
     pass
 
 class ReplicaConfig:
@@ -119,22 +131,25 @@ def verify_dns_records(host_name, responses, resaddr, family):
 
 def verify_fqdn(host_name, no_host_dns=False, system_name_check=True):
     """
-    Verify that the given host name is fully-qualified.
+    Run fqdn checks for given host:
+        - test hostname format
+        - test that hostname is fully qualified
+        - test forward and reverse hostname DNS lookup
 
-    Raises `RuntimeError` if the host name is not fully-qualified.
+    Raises `BadHostError` or derived Exceptions if there is an error
 
     :param host_name: The host name to verify.
-    :param no_host_dns: If true, skip DNS resolution of the host name.
+    :param no_host_dns: If true, skip DNS resolution tests of the host name.
     :param system_name_check: If true, check if the host name matches the system host name.
     """
     if len(host_name.split(".")) < 2 or host_name == "localhost.localdomain":
-        raise RuntimeError("Invalid hostname '%s', must be fully-qualified." % host_name)
+        raise BadHostError("Invalid hostname '%s', must be fully-qualified." % host_name)
 
     if host_name != host_name.lower():
-        raise RuntimeError("Invalid hostname '%s', must be lower-case." % host_name)
+        raise BadHostError("Invalid hostname '%s', must be lower-case." % host_name)
 
     if ipautil.valid_ip(host_name):
-        raise RuntimeError("IP address not allowed as a hostname")
+        raise BadHostError("IP address not allowed as a hostname")
 
     if system_name_check:
         system_host_name = socket.gethostname()
@@ -149,28 +164,28 @@ def verify_fqdn(host_name, no_host_dns=False, system_name_check=True):
     try:
         hostaddr = socket.getaddrinfo(host_name, None)
     except:
-        raise RuntimeError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
+        raise HostForwardLookupError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
 
     if len(hostaddr) == 0:
-        raise RuntimeError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
+        raise HostForwardLookupError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
 
     for a in hostaddr:
         if a[4][0] == '127.0.0.1' or a[4][0] == '::1':
-            raise RuntimeError("The IPA Server hostname must not resolve to localhost (%s). A routable IP address must be used. Check /etc/hosts to see if %s is an alias for %s" % (a[4][0], host_name, a[4][0]))
+            raise HostForwardLookupError("The IPA Server hostname must not resolve to localhost (%s). A routable IP address must be used. Check /etc/hosts to see if %s is an alias for %s" % (a[4][0], host_name, a[4][0]))
         try:
             resaddr = a[4][0]
             revname = socket.gethostbyaddr(a[4][0])[0]
         except:
-            raise RuntimeError("Unable to resolve the reverse ip address, check /etc/hosts or DNS name resolution")
+            raise HostReverseLookupError("Unable to resolve the reverse ip address, check /etc/hosts or DNS name resolution")
         if revname != host_name:
-            raise RuntimeError("The host name %s does not match the reverse lookup %s" % (host_name, revname))
+            raise HostReverseLookupError("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 and AAAA names are allowed.")
+                raise HostReverseLookupError("The IPA Server Hostname cannot be a CNAME, only A and AAAA names are allowed.")
 
     # Verify that it is a DNS A or AAAA record
     rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_A)
-- 
1.7.6.2

_______________________________________________
Freeipa-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to