e3ffab
From 453332215667d6ff9595e6dedeeb3ed5ba7e5bdf Mon Sep 17 00:00:00 2001
e3ffab
From: Martin Basti <mbasti@redhat.com>
e3ffab
Date: Thu, 27 Nov 2014 14:16:23 +0100
e3ffab
Subject: [PATCH] Throw zonemgr error message before installation proceeds
e3ffab
e3ffab
Ticket: https://fedorahosted.org/freeipa/ticket/4771
e3ffab
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
e3ffab
---
e3ffab
 ipalib/parameters.py | 35 +++++------------------------------
e3ffab
 ipalib/util.py       | 45 +++++++++++++++++++++++++++++++++++++++++++++
e3ffab
 2 files changed, 50 insertions(+), 30 deletions(-)
e3ffab
e3ffab
diff --git a/ipalib/parameters.py b/ipalib/parameters.py
e3ffab
index 0cf14a4cd2900459ccd5d6d52912960c642223aa..7fa55fd6a6854ffa97da211ca5ef04b7ad974dc4 100644
e3ffab
--- a/ipalib/parameters.py
e3ffab
+++ b/ipalib/parameters.py
e3ffab
@@ -112,7 +112,7 @@ from errors import ConversionError, RequirementError, ValidationError
e3ffab
 from errors import PasswordMismatch, Base64DecodeError
e3ffab
 from constants import TYPE_ERROR, CALLABLE_ERROR, LDAP_GENERALIZED_TIME_FORMAT
e3ffab
 from text import Gettext, FixMe
e3ffab
-from util import json_serialize
e3ffab
+from util import json_serialize, validate_idna_domain
e3ffab
 from ipapython.dn import DN
e3ffab
 from ipapython.dnsutil import DNSName
e3ffab
 import dns.name
e3ffab
@@ -1950,36 +1950,11 @@ class DNSNameParam(Param):
e3ffab
             error = None
e3ffab
 
e3ffab
             try:
e3ffab
-                domain_name = DNSName(value)
e3ffab
-            except dns.name.BadEscape:
e3ffab
-                error = _('invalid escape code in domain name')
e3ffab
-            except dns.name.EmptyLabel:
e3ffab
-                error = _('empty DNS label')
e3ffab
-            except dns.name.NameTooLong:
e3ffab
-                error = _('domain name cannot be longer than 255 characters')
e3ffab
-            except dns.name.LabelTooLong:
e3ffab
-                error = _('DNS label cannot be longer than 63 characters')
e3ffab
-            except dns.exception.SyntaxError:
e3ffab
-                error = _('invalid domain name')
e3ffab
-            else:
e3ffab
-                #compare if IDN normalized and original domain match
e3ffab
-                #there is N:1 mapping between unicode and IDNA names
e3ffab
-                #user should use normalized names to avoid mistakes
e3ffab
-                labels = re.split(u'[.\uff0e\u3002\uff61]', value, flags=re.UNICODE)
e3ffab
-                try:
e3ffab
-                    map(lambda label: label.encode("ascii"), labels)
e3ffab
-                except UnicodeError:
e3ffab
-                    # IDNA
e3ffab
-                    is_nonnorm = any(encodings.idna.nameprep(x) != x for x in labels)
e3ffab
-                    if is_nonnorm:
e3ffab
-                        error = _("domain name '%(domain)s' should be normalized to"
e3ffab
-                          ": %(normalized)s") % {
e3ffab
-                          'domain': value,
e3ffab
-                          'normalized': '.'.join([encodings.idna.nameprep(x) for x in labels])}
e3ffab
-            if error:
e3ffab
+                validate_idna_domain(value)
e3ffab
+            except ValueError as e:
e3ffab
                 raise ConversionError(name=self.get_param_name(), index=index,
e3ffab
-                                      error=error)
e3ffab
-            value = domain_name
e3ffab
+                                      error=unicode(e))
e3ffab
+            value = DNSName(value)
e3ffab
 
e3ffab
             if self.only_absolute and not value.is_absolute():
e3ffab
                 value = value.make_absolute()
e3ffab
diff --git a/ipalib/util.py b/ipalib/util.py
e3ffab
index 7a283106d70ba6a3e25cc7129d57b44b80876882..2c17d80a0427a5c7e45a6a0b64fa1f4d39fffa8a 100644
e3ffab
--- a/ipalib/util.py
e3ffab
+++ b/ipalib/util.py
e3ffab
@@ -28,6 +28,7 @@ import socket
e3ffab
 import re
e3ffab
 import decimal
e3ffab
 import dns
e3ffab
+import encodings
e3ffab
 import netaddr
e3ffab
 from types import NoneType
e3ffab
 from weakref import WeakKeyDictionary
e3ffab
@@ -277,6 +278,7 @@ def validate_zonemgr(zonemgr):
e3ffab
 
e3ffab
 def validate_zonemgr_str(zonemgr):
e3ffab
     zonemgr = normalize_zonemgr(zonemgr)
e3ffab
+    validate_idna_domain(zonemgr)
e3ffab
     zonemgr = DNSName(zonemgr)
e3ffab
     return validate_zonemgr(zonemgr)
e3ffab
 
e3ffab
@@ -589,3 +591,46 @@ def validate_dnssec_forwarder(ip_addr):
e3ffab
         return False
e3ffab
 
e3ffab
     return True
e3ffab
+
e3ffab
+
e3ffab
+def validate_idna_domain(value):
e3ffab
+    """
e3ffab
+    Validate if value is valid IDNA domain.
e3ffab
+
e3ffab
+    If domain is not valid, raises ValueError
e3ffab
+    :param value:
e3ffab
+    :return:
e3ffab
+    """
e3ffab
+    error = None
e3ffab
+
e3ffab
+    try:
e3ffab
+        DNSName(value)
e3ffab
+    except dns.name.BadEscape:
e3ffab
+        error = _('invalid escape code in domain name')
e3ffab
+    except dns.name.EmptyLabel:
e3ffab
+        error = _('empty DNS label')
e3ffab
+    except dns.name.NameTooLong:
e3ffab
+        error = _('domain name cannot be longer than 255 characters')
e3ffab
+    except dns.name.LabelTooLong:
e3ffab
+        error = _('DNS label cannot be longer than 63 characters')
e3ffab
+    except dns.exception.SyntaxError:
e3ffab
+        error = _('invalid domain name')
e3ffab
+    else:
e3ffab
+        #compare if IDN normalized and original domain match
e3ffab
+        #there is N:1 mapping between unicode and IDNA names
e3ffab
+        #user should use normalized names to avoid mistakes
e3ffab
+        labels = re.split(u'[.\uff0e\u3002\uff61]', value, flags=re.UNICODE)
e3ffab
+        try:
e3ffab
+            map(lambda label: label.encode("ascii"), labels)
e3ffab
+        except UnicodeError:
e3ffab
+            # IDNA
e3ffab
+            is_nonnorm = any(encodings.idna.nameprep(x) != x for x in labels)
e3ffab
+            if is_nonnorm:
e3ffab
+                error = _("domain name '%(domain)s' should be normalized to"
e3ffab
+                          ": %(normalized)s") % {
e3ffab
+                          'domain': value,
e3ffab
+                          'normalized': '.'.join([encodings.idna.nameprep(x)
e3ffab
+                                                  for x in labels])}
e3ffab
+
e3ffab
+    if error:
e3ffab
+        raise ValueError(error)
e3ffab
-- 
e3ffab
2.1.0
e3ffab