diff options
author | Martin Kosek <mkosek@redhat.com> | 2012-02-28 09:05:01 +0100 |
---|---|---|
committer | Martin Kosek <mkosek@redhat.com> | 2012-02-29 18:52:58 +0100 |
commit | 7db1da1d6524aba1319d83bb711c59968557de5f (patch) | |
tree | 293ead5ab8f19c36a02f73dc3532cf0f63d281bb /ipalib/plugins | |
parent | 4e9a2e0983a92829f497bb3ba6b3ab7b6db2967d (diff) | |
download | freeipa-7db1da1d6524aba1319d83bb711c59968557de5f.tar.gz freeipa-7db1da1d6524aba1319d83bb711c59968557de5f.tar.xz freeipa-7db1da1d6524aba1319d83bb711c59968557de5f.zip |
Improve hostname and domain name validation
DNS plugin did not check DNS zone and DNS record validity and
user was thus able to create domains like "foo bar" or other
invalid DNS labels which would really confuse both user and
bind-dyndb-ldap plugin.
This patch at first consolidates hostname/domain name validators
so that they use common functions and we don't have regular
expressions and other checks defined in several places. These
new cleaned validators are then used for zone/record name
validation.
https://fedorahosted.org/freeipa/ticket/2384
Diffstat (limited to 'ipalib/plugins')
-rw-r--r-- | ipalib/plugins/dns.py | 39 | ||||
-rw-r--r-- | ipalib/plugins/host.py | 21 |
2 files changed, 35 insertions, 25 deletions
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py index af23e03c3..44fced643 100644 --- a/ipalib/plugins/dns.py +++ b/ipalib/plugins/dns.py @@ -28,7 +28,8 @@ from ipalib import Command from ipalib.parameters import Flag, Bool, Int, Decimal, Str, StrEnum, Any from ipalib.plugins.baseldap import * from ipalib import _, ngettext -from ipalib.util import validate_zonemgr, normalize_zonemgr, validate_hostname +from ipalib.util import (validate_zonemgr, normalize_zonemgr, + validate_hostname, validate_dns_label, validate_domain_name) from ipapython import dnsclient from ipapython.ipautil import valid_ip, CheckedIPAddress from ldap import explode_dn @@ -299,7 +300,7 @@ def _normalize_bind_aci(bind_acis): acis += u';' return acis -def _domain_name_validator(ugettext, value): +def _bind_hostname_validator(ugettext, value): try: # Allow domain name which is not fully qualified. These are supported # in bind and then translated as <non-fqdn-name>.<domain>. @@ -310,6 +311,22 @@ def _domain_name_validator(ugettext, value): return None +def _dns_record_name_validator(ugettext, value): + if value == _dns_zone_record: + return + + try: + map(lambda label:validate_dns_label(label, allow_underscore=True), \ + value.split(u'.')) + except ValueError, e: + return unicode(e) + +def _domain_name_validator(ugettext, value): + try: + validate_domain_name(value) + except ValueError, e: + return unicode(e) + def _hostname_validator(ugettext, value): try: validate_hostname(value) @@ -777,7 +794,7 @@ class AFSDBRecord(DNSRecord): maxvalue=65535, ), Str('hostname', - _domain_name_validator, + _bind_hostname_validator, label=_('Hostname'), ), ) @@ -816,7 +833,7 @@ class CNAMERecord(DNSRecord): rfc = 1035 parts = ( Str('hostname', - _domain_name_validator, + _bind_hostname_validator, label=_('Hostname'), doc=_('A hostname which this alias hostname points to'), ), @@ -837,7 +854,7 @@ class DNAMERecord(DNSRecord): rfc = 2672 parts = ( Str('target', - _domain_name_validator, + _bind_hostname_validator, label=_('Target'), ), ) @@ -916,7 +933,7 @@ class KXRecord(DNSRecord): maxvalue=65535, ), Str('exchanger', - _domain_name_validator, + _bind_hostname_validator, label=_('Exchanger'), doc=_('A host willing to act as a key exchanger'), ), @@ -1057,7 +1074,7 @@ class MXRecord(DNSRecord): maxvalue=65535, ), Str('exchanger', - _domain_name_validator, + _bind_hostname_validator, label=_('Exchanger'), doc=_('A host willing to act as a mail exchanger'), ), @@ -1069,7 +1086,7 @@ class NSRecord(DNSRecord): parts = ( Str('hostname', - _domain_name_validator, + _bind_hostname_validator, label=_('Hostname'), ), ) @@ -1083,7 +1100,7 @@ class NSECRecord(DNSRecord): parts = ( Str('next', - _domain_name_validator, + _bind_hostname_validator, label=_('Next Domain Name'), ), StrEnum('types+', @@ -1181,7 +1198,7 @@ def _srv_target_validator(ugettext, value): if value == u'.': # service not available return - return _domain_name_validator(ugettext, value) + return _bind_hostname_validator(ugettext, value) class SRVRecord(DNSRecord): rrtype = 'SRV' @@ -1426,6 +1443,7 @@ class dnszone(LDAPObject): takes_params = ( Str('idnsname', + _domain_name_validator, cli_name='name', label=_('Zone name'), doc=_('Zone name (FQDN)'), @@ -1742,6 +1760,7 @@ class dnsrecord(LDAPObject): takes_params = ( Str('idnsname', + _dns_record_name_validator, cli_name='name', label=_('Record name'), doc=_('Record name'), diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py index df9ad7370..0ff5237fa 100644 --- a/ipalib/plugins/host.py +++ b/ipalib/plugins/host.py @@ -31,7 +31,9 @@ from ipalib.plugins.baseldap import * from ipalib.plugins.service import split_principal from ipalib.plugins.service import validate_certificate from ipalib.plugins.service import set_certificate_attrs -from ipalib.plugins.dns import dns_container_exists, _record_types, add_records_for_host_validation, add_records_for_host +from ipalib.plugins.dns import (dns_container_exists, _record_types, + add_records_for_host_validation, add_records_for_host, + _hostname_validator, get_reverse_zone) from ipalib.plugins.dns import get_reverse_zone from ipalib import _, ngettext from ipalib import x509 @@ -97,14 +99,6 @@ EXAMPLES: ipa host-add-managedby --hosts=test2 test """) -def validate_host(ugettext, fqdn): - """ - Require at least one dot in the hostname (to support localhost.localdomain) - """ - if fqdn.find('.') == -1: - return _('Fully-qualified hostname required') - return None - def remove_fwd_ptr(ipaddr, host, domain, recordtype): api.log.debug('deleting ipaddr %s' % ipaddr) try: @@ -225,10 +219,7 @@ class host(LDAPObject): label_singular = _('Host') takes_params = ( - Str('fqdn', validate_host, - pattern='^[a-zA-Z0-9][a-zA-Z0-9-\.]{0,254}$', - pattern_errmsg='may only include letters, numbers, and -', - maxlength=255, + Str('fqdn', _hostname_validator, cli_name='hostname', label=_('Host name'), primary_key=True, @@ -481,7 +472,7 @@ class host_del(LDAPDelete): def pre_callback(self, ldap, dn, *keys, **options): # If we aren't given a fqdn, find it - if validate_host(None, keys[-1]) is not None: + if _hostname_validator(None, keys[-1]) is not None: hostentry = api.Command['host_show'](keys[-1])['result'] fqdn = hostentry['fqdn'][0] else: @@ -856,7 +847,7 @@ class host_disable(LDAPQuery): ldap = self.obj.backend # If we aren't given a fqdn, find it - if validate_host(None, keys[-1]) is not None: + if _hostname_validator(None, keys[-1]) is not None: hostentry = api.Command['host_show'](keys[-1])['result'] fqdn = hostentry['fqdn'][0] else: |