On Mon, 2011-11-14 at 10:37 +0100, Martin Kosek wrote:
> On Fri, 2011-11-11 at 10:22 -0500, Rob Crittenden wrote:
> > Martin Kosek wrote:
> > > There are 2 patches improving our zone zonemgr:
> > >
> > > 1) ipa-server-install --zonemgr option validation and normalization +
> > > the same thing in ipa dnszone-add/mod --admin-email. They now allow and
> > > correctly process '.' in a local-part of the zonemgr e-mail (it is
> > > encoded as '\.'.
> > >
> > > How to test:
> > >
> > > ipa-server-install -p secret123 -a secret123 --setup-dns 
> > > --zonemgr=foo....@example.com
> > > OR if e-mail is passed in SOA format:
> > > ipa-server-install -p secret123 -a secret123 --setup-dns 
> > > --zonemgr='foo\.bar.example.com'
> > >
> > > In both cases, the zonemgr e-mail will be set to correct format: 'foo
> > > \.bar.example.com'.
> > >
> > > 2) Our default zonemgr is changed to follow RFC 2142 recommendation -
> > > hostmaster@<domain>
> > >
> > > hostmaster is an alias to root anyway (see /etc/aliases).
> > >
> > > Martin
> > 
> > NACK 166, this illegal address is allowed: foo\.bar\.baz\.com
> > 
> > ACK 167 when 166 is ready.
> > 
> > rob
> 
> Are you sure that you quoted the string in shell properly? It likes to
> eat backslashes when one is not cautious. The zonemgr value, including
> backslashes, should then show up in `ipa dnszone-show ZONE'.
> 
> This is my output:
> 
> # ipa dnszone-mod example.com --admin-email='foo\.bar\.baz\.com'
> ipa: ERROR: invalid 'admin_email': address domain is not fully qualified
> ("example.com" instead of just "example")
> 
> Anyway, attaching a rebased patch (it collided with my patch 120).
> 
> Martin

I rebased both patches. I also fixed a bug when ipa-replica-prepare
$HOST --ip-address=$IP was failing because None was passed as zonemgr.

Martin
>From ef2bec26932ee391bcdf20f9714dc2598da6b52e Mon Sep 17 00:00:00 2001
From: Martin Kosek <mko...@redhat.com>
Date: Wed, 23 Nov 2011 16:03:51 +0100
Subject: [PATCH 1/2] Improve zonemgr validator and normalizer

The validator has been improved to support better both SOA format
(e-mail address in a domain name format, without '@') and standard
e-mail format. Allow '\.' character in a SOA format encoding the
standard '.' in the local-part of an e-mail. Normalization code
has been moved to one common function.

https://fedorahosted.org/freeipa/ticket/2053
---
 ipalib/plugins/dns.py             |   11 +------
 ipalib/util.py                    |   50 +++++++++++++++++++++++++++++-------
 ipaserver/install/bindinstance.py |   13 ++++-----
 3 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index bfc8090ca5a9304c3c3b18c96a24087cce7fee86..e3522c9038ff559bcad3d5e6ca6720d59e431e7e 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -27,7 +27,7 @@ from ipalib import Command
 from ipalib import Flag, Bool, Int, List, Str, StrEnum
 from ipalib.plugins.baseldap import *
 from ipalib import _, ngettext
-from ipalib.util import validate_zonemgr, validate_hostname
+from ipalib.util import validate_zonemgr, normalize_zonemgr, validate_hostname
 from ipapython import dnsclient
 from ipapython.ipautil import valid_ip
 from ldap import explode_dn
@@ -152,13 +152,6 @@ def _rname_validator(ugettext, zonemgr):
         return unicode(e)
     return None
 
-# normalizer for admin email
-def _rname_normalizer(value):
-    value = value.replace('@', '.')
-    if not value.endswith('.'):
-        value += '.'
-    return value
-
 def _create_zone_serial(**kwargs):
     """Generate serial number for zones."""
     return int('%s01' % time.strftime('%Y%d%m'))
@@ -678,7 +671,7 @@ class dnszone(LDAPObject):
             label=_('Administrator e-mail address'),
             doc=_('Administrator e-mail address'),
             default_from=lambda idnsname: 'root.%s' % idnsname,
-            normalizer=_rname_normalizer,
+            normalizer=normalize_zonemgr,
         ),
         Int('idnssoaserial?',
             cli_name='serial',
diff --git a/ipalib/util.py b/ipalib/util.py
index b0574f9499681a551a588a76ce2654ef89dc5ec3..ffa2759421b1c3af814d4fb395e632bb69e48e82 100644
--- a/ipalib/util.py
+++ b/ipalib/util.py
@@ -196,33 +196,63 @@ def check_writable_file(filename):
     except (IOError, OSError), e:
         raise errors.FileError(reason=str(e))
 
+def normalize_zonemgr(zonemgr):
+    if not zonemgr:
+        # do not normalize empty or None value
+        return zonemgr
+    if '@' in zonemgr:
+        # local-part needs to be normalized
+        name, at, domain = zonemgr.partition('@')
+        name = name.replace('.', '\\.')
+        zonemgr = u''.join((name, u'.', domain))
+
+    if not zonemgr.endswith('.'):
+        zonemgr = zonemgr + u'.'
+
+    return zonemgr
 
 def validate_zonemgr(zonemgr):
     """ See RFC 1033, 1035 """
-    regex_domain = re.compile(r'^[a-z0-9][a-z0-9-]*$', re.IGNORECASE)
-    regex_name = re.compile(r'^[a-z0-9][a-z0-9-_]*$', re.IGNORECASE)
+    regex_domain = re.compile(r'^[a-z0-9]([a-z0-9-]?[a-z0-9])*$', re.IGNORECASE)
+    regex_local_part = re.compile(r'^[a-z0-9]([a-z0-9-_\.]?[a-z0-9])*$',
+                                    re.IGNORECASE)
+
+    local_part_errmsg = _('mail account may only include letters, numbers, -, _ and a dot. There may not be consecutive -, _ and . characters')
 
     if len(zonemgr) > 255:
         raise ValueError(_('cannot be longer that 255 characters'))
 
+    if zonemgr.endswith('.'):
+        zonemgr = zonemgr[:-1]
+
     if zonemgr.count('@') == 1:
-        name, dot, domain = zonemgr.partition('@')
+        local_part, dot, domain = zonemgr.partition('@')
+        if not regex_local_part.match(local_part):
+            raise ValueError(local_part_errmsg)
     elif zonemgr.count('@') > 1:
         raise ValueError(_('too many \'@\' characters'))
     else:
-        # address in SOA format already (without @)
-        name, dot, domain = zonemgr.partition('.')
+        last_fake_sep = zonemgr.rfind('\\.')
+        if last_fake_sep != -1: # there is a 'fake' local-part/domain separator
+            sep = zonemgr.find('.', last_fake_sep+2)
+            if sep == -1:
+                raise ValueError(_('address domain is not fully qualified ' \
+                          '("example.com" instead of just "example")'))
+            local_part = zonemgr[:sep]
+            domain = zonemgr[sep+1:]
 
-    if domain.endswith('.'):
-        domain = domain[:-1]
+            if not all(regex_local_part.match(part) for part in local_part.split('\\.')):
+                raise ValueError(local_part_errmsg)
+        else:
+            local_part, dot, domain = zonemgr.partition('.')
+
+            if not regex_local_part.match(local_part):
+                raise ValueError(local_part_errmsg)
 
     if '.' not in domain:
         raise ValueError(_('address domain is not fully qualified ' \
                           '("example.com" instead of just "example")'))
 
-    if not regex_name.match(name):
-        raise ValueError(_('mail account may only include letters, numbers, -, and _'))
-
     if not all(regex_domain.match(part) for part in domain.split(".")):
         raise ValueError(_('domain name may only include letters, numbers, and -'))
 
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 7da4a891bfbc0b495b030fd07b5c5bcda0b47119..f3844429e601d3c2cc0e307b5a0f2a3aadca6013 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -187,6 +187,9 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_addres
     if update_policy is None:
         update_policy = "grant %(realm)s krb5-self * A; grant %(realm)s krb5-self * AAAA;" % dict(realm=api.env.realm)
 
+    if zonemgr is None:
+        zonemgr = 'root.%s' % name
+
     if ns_hostname is None:
         # automatically retrieve list of DNS masters
         dns_masters = api.Object.dnsrecord.get_dns_masters()
@@ -298,10 +301,6 @@ def zonemgr_callback(option, opt_str, value, parser):
     except ValueError, e:
         parser.error("invalid zonemgr: " + unicode(e))
 
-    name = opt_str.replace('--','')
-    v = unicode(value, 'utf-8')
-    ia = IA5Str(name)
-    ia._convert_scalar(v)
     parser.values.zonemgr = value
 
 class DnsBackup(object):
@@ -387,10 +386,10 @@ class BindInstance(service.Service):
         self.zone_refresh = zone_refresh
         self.zone_notif = zone_notif
 
-        if zonemgr:
-            self.zonemgr = zonemgr.replace('@','.')
-        else:
+        if not zonemgr:
             self.zonemgr = 'root.%s.%s' % (self.host, self.domain)
+        else:
+            self.zonemgr = normalize_zonemgr(zonemgr)
 
         self.__setup_sub_dict()
 
-- 
1.7.7.3

>From 41ce37ff1cea147c1ea8f6744daf413e2ad3c5e6 Mon Sep 17 00:00:00 2001
From: Martin Kosek <mko...@redhat.com>
Date: Wed, 23 Nov 2011 16:09:29 +0100
Subject: [PATCH 2/2] Change default DNS zone manager to hostmaster

Change our default zone manager to hostmaster@<domain> (as per
RFC 2142 recommendation).

https://fedorahosted.org/freeipa/ticket/1981
---
 ipalib/plugins/dns.py             |    2 +-
 ipaserver/install/bindinstance.py |    4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index e3522c9038ff559bcad3d5e6ca6720d59e431e7e..b3a6abc671f2bec0b18308062e19460923238d8e 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -670,7 +670,7 @@ class dnszone(LDAPObject):
             cli_name='admin_email',
             label=_('Administrator e-mail address'),
             doc=_('Administrator e-mail address'),
-            default_from=lambda idnsname: 'root.%s' % idnsname,
+            default_from=lambda idnsname: 'hostmaster.%s' % idnsname,
             normalizer=normalize_zonemgr,
         ),
         Int('idnssoaserial?',
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index f3844429e601d3c2cc0e307b5a0f2a3aadca6013..b6dd7d34eb2e4b96ed1ddca7ee22a1eacc81cdf6 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -188,7 +188,7 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_addres
         update_policy = "grant %(realm)s krb5-self * A; grant %(realm)s krb5-self * AAAA;" % dict(realm=api.env.realm)
 
     if zonemgr is None:
-        zonemgr = 'root.%s' % name
+        zonemgr = 'hostmaster.%s' % name
 
     if ns_hostname is None:
         # automatically retrieve list of DNS masters
@@ -387,7 +387,7 @@ class BindInstance(service.Service):
         self.zone_notif = zone_notif
 
         if not zonemgr:
-            self.zonemgr = 'root.%s.%s' % (self.host, self.domain)
+            self.zonemgr = 'hostmaster.%s' % self.domain
         else:
             self.zonemgr = normalize_zonemgr(zonemgr)
 
-- 
1.7.7.3

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to