mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add --zonemgr/--admin-mail validator
Do at least a basic validation of DNS zone manager mail address. Do not require '@' to be in the mail address as the SOA record stores this value without it and people may be used to configure it that way. '@' is always removed by the installer/dns plugin before the DNS zone is created. https://fedorahosted.org/freeipa/ticket/1966
This commit is contained in:
6
API.txt
6
API.txt
@@ -854,7 +854,7 @@ args: 1,19,3
|
|||||||
arg: Str('idnsname', attribute=True, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, required=True)
|
arg: Str('idnsname', attribute=True, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, required=True)
|
||||||
option: Str('name_from_ip', _validate_ipnet, attribute=True, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, required=False)
|
option: Str('name_from_ip', _validate_ipnet, attribute=True, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, required=False)
|
||||||
option: Str('idnssoamname', attribute=True, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, required=True)
|
option: Str('idnssoamname', attribute=True, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, required=True)
|
||||||
option: Str('idnssoarname', attribute=True, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, required=True)
|
option: Str('idnssoarname', _rname_validator, attribute=True, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, required=True)
|
||||||
option: Int('idnssoaserial', attribute=True, autofill=True, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, required=False)
|
option: Int('idnssoaserial', attribute=True, autofill=True, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, required=False)
|
||||||
option: Int('idnssoarefresh', attribute=True, autofill=True, cli_name='refresh', default=3600, label=Gettext('SOA refresh', domain='ipa', localedir=None), minvalue=0, multivalue=False, required=False)
|
option: Int('idnssoarefresh', attribute=True, autofill=True, cli_name='refresh', default=3600, label=Gettext('SOA refresh', domain='ipa', localedir=None), minvalue=0, multivalue=False, required=False)
|
||||||
option: Int('idnssoaretry', attribute=True, autofill=True, cli_name='retry', default=900, label=Gettext('SOA retry', domain='ipa', localedir=None), minvalue=0, multivalue=False, required=False)
|
option: Int('idnssoaretry', attribute=True, autofill=True, cli_name='retry', default=900, label=Gettext('SOA retry', domain='ipa', localedir=None), minvalue=0, multivalue=False, required=False)
|
||||||
@@ -899,7 +899,7 @@ arg: Str('criteria?', noextrawhitespace=False)
|
|||||||
option: Str('idnsname', attribute=True, autofill=False, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, query=True, required=False)
|
option: Str('idnsname', attribute=True, autofill=False, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, query=True, required=False)
|
||||||
option: Str('name_from_ip', _validate_ipnet, attribute=True, autofill=False, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
|
option: Str('name_from_ip', _validate_ipnet, attribute=True, autofill=False, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
|
||||||
option: Str('idnssoamname', attribute=True, autofill=False, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
|
option: Str('idnssoamname', attribute=True, autofill=False, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, query=True, required=False)
|
||||||
option: Str('idnssoarname', attribute=True, autofill=False, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, query=True, required=False)
|
option: Str('idnssoarname', _rname_validator, attribute=True, autofill=False, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, query=True, required=False)
|
||||||
option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, query=True, required=False)
|
option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, query=True, required=False)
|
||||||
option: Int('idnssoarefresh', attribute=True, autofill=False, cli_name='refresh', default=3600, label=Gettext('SOA refresh', domain='ipa', localedir=None), minvalue=0, multivalue=False, query=True, required=False)
|
option: Int('idnssoarefresh', attribute=True, autofill=False, cli_name='refresh', default=3600, label=Gettext('SOA refresh', domain='ipa', localedir=None), minvalue=0, multivalue=False, query=True, required=False)
|
||||||
option: Int('idnssoaretry', attribute=True, autofill=False, cli_name='retry', default=900, label=Gettext('SOA retry', domain='ipa', localedir=None), minvalue=0, multivalue=False, query=True, required=False)
|
option: Int('idnssoaretry', attribute=True, autofill=False, cli_name='retry', default=900, label=Gettext('SOA retry', domain='ipa', localedir=None), minvalue=0, multivalue=False, query=True, required=False)
|
||||||
@@ -925,7 +925,7 @@ args: 1,18,3
|
|||||||
arg: Str('idnsname', attribute=True, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, query=True, required=True)
|
arg: Str('idnsname', attribute=True, cli_name='name', default_from=DefaultFrom(<lambda>, 'name_from_ip'), label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=<lambda>, primary_key=True, query=True, required=True)
|
||||||
option: Str('name_from_ip', _validate_ipnet, attribute=True, autofill=False, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, required=False)
|
option: Str('name_from_ip', _validate_ipnet, attribute=True, autofill=False, cli_name='name_from_ip', label=Gettext('Reverse zone IP network', domain='ipa', localedir=None), multivalue=False, required=False)
|
||||||
option: Str('idnssoamname', attribute=True, autofill=False, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, required=False)
|
option: Str('idnssoamname', attribute=True, autofill=False, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, required=False)
|
||||||
option: Str('idnssoarname', attribute=True, autofill=False, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, required=False)
|
option: Str('idnssoarname', _rname_validator, attribute=True, autofill=False, cli_name='admin_email', default_from=DefaultFrom(<lambda>, 'idnsname'), label=Gettext('Administrator e-mail address', domain='ipa', localedir=None), multivalue=False, normalizer=_rname_normalizer, required=False)
|
||||||
option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, required=False)
|
option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', create_default=_create_zone_serial, label=Gettext('SOA serial', domain='ipa', localedir=None), minvalue=1, multivalue=False, required=False)
|
||||||
option: Int('idnssoarefresh', attribute=True, autofill=False, cli_name='refresh', default=3600, label=Gettext('SOA refresh', domain='ipa', localedir=None), minvalue=0, multivalue=False, required=False)
|
option: Int('idnssoarefresh', attribute=True, autofill=False, cli_name='refresh', default=3600, label=Gettext('SOA refresh', domain='ipa', localedir=None), minvalue=0, multivalue=False, required=False)
|
||||||
option: Int('idnssoaretry', attribute=True, autofill=False, cli_name='retry', default=900, label=Gettext('SOA retry', domain='ipa', localedir=None), minvalue=0, multivalue=False, required=False)
|
option: Int('idnssoaretry', attribute=True, autofill=False, cli_name='retry', default=900, label=Gettext('SOA retry', domain='ipa', localedir=None), minvalue=0, multivalue=False, required=False)
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ def parse_options():
|
|||||||
parser.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
|
parser.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
|
||||||
parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
|
parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
|
||||||
default=False, help="Do not create reverse DNS zone")
|
default=False, help="Do not create reverse DNS zone")
|
||||||
parser.add_option("--zonemgr", dest="zonemgr",
|
parser.add_option("--zonemgr", action="callback", callback=bindinstance.zonemgr_callback,
|
||||||
|
type="string",
|
||||||
help="DNS zone manager e-mail address. Defaults to root")
|
help="DNS zone manager e-mail address. Defaults to root")
|
||||||
parser.add_option("--zone-notif", dest="zone_notif",
|
parser.add_option("--zone-notif", dest="zone_notif",
|
||||||
action="store_true", default=False,
|
action="store_true", default=False,
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ from ipaserver.plugins.ldap2 import ldap2
|
|||||||
from ipapython import sysrestore
|
from ipapython import sysrestore
|
||||||
from ipapython.ipautil import *
|
from ipapython.ipautil import *
|
||||||
from ipalib import api, errors, util
|
from ipalib import api, errors, util
|
||||||
from ipalib.parameters import IA5Str
|
|
||||||
from ipapython.config import IPAOptionParser
|
from ipapython.config import IPAOptionParser
|
||||||
from ipalib.dn import DN
|
from ipalib.dn import DN
|
||||||
from ipalib.x509 import load_certificate_from_file, load_certificate_chain_from_file
|
from ipalib.x509 import load_certificate_from_file, load_certificate_chain_from_file
|
||||||
@@ -76,16 +75,6 @@ VALID_SUBJECT_ATTRS = ['cn', 'st', 'o', 'ou', 'dnqualifier', 'c',
|
|||||||
'incorporationlocality', 'incorporationstate',
|
'incorporationlocality', 'incorporationstate',
|
||||||
'incorporationcountry', 'businesscategory']
|
'incorporationcountry', 'businesscategory']
|
||||||
|
|
||||||
def zonemgr_callback(option, opt_str, value, parser):
|
|
||||||
"""
|
|
||||||
Make sure the zonemgr is an IA5String.
|
|
||||||
"""
|
|
||||||
name = opt_str.replace('--','')
|
|
||||||
v = unicode(value, 'utf-8')
|
|
||||||
ia = IA5Str(name)
|
|
||||||
ia._convert_scalar(v)
|
|
||||||
parser.values.zonemgr = value
|
|
||||||
|
|
||||||
def subject_callback(option, opt_str, value, parser):
|
def subject_callback(option, opt_str, value, parser):
|
||||||
"""
|
"""
|
||||||
Make sure the certificate subject base is a valid DN
|
Make sure the certificate subject base is a valid DN
|
||||||
@@ -195,7 +184,7 @@ def parse_options():
|
|||||||
dns_group.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
|
dns_group.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
|
||||||
dns_group.add_option("--no-reverse", dest="no_reverse", action="store_true",
|
dns_group.add_option("--no-reverse", dest="no_reverse", action="store_true",
|
||||||
default=False, help="Do not create reverse DNS zone")
|
default=False, help="Do not create reverse DNS zone")
|
||||||
dns_group.add_option("--zonemgr", action="callback", callback=zonemgr_callback,
|
dns_group.add_option("--zonemgr", action="callback", callback=bindinstance.zonemgr_callback,
|
||||||
type="string",
|
type="string",
|
||||||
help="DNS zone manager e-mail address. Defaults to root")
|
help="DNS zone manager e-mail address. Defaults to root")
|
||||||
dns_group.add_option("--zone-notif", dest="zone_notif",
|
dns_group.add_option("--zone-notif", dest="zone_notif",
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from ipalib import Command
|
|||||||
from ipalib import Flag, Int, List, Str, StrEnum
|
from ipalib import Flag, Int, List, Str, StrEnum
|
||||||
from ipalib.plugins.baseldap import *
|
from ipalib.plugins.baseldap import *
|
||||||
from ipalib import _, ngettext
|
from ipalib import _, ngettext
|
||||||
|
from ipalib.util import validate_zonemgr
|
||||||
from ipapython import dnsclient
|
from ipapython import dnsclient
|
||||||
from ipapython.ipautil import valid_ip
|
from ipapython.ipautil import valid_ip
|
||||||
from ldap import explode_dn
|
from ldap import explode_dn
|
||||||
@@ -136,6 +137,13 @@ _record_attributes = [str('%srecord' % t.lower()) for t in _record_types]
|
|||||||
# supported DNS classes, IN = internet, rest is almost never used
|
# supported DNS classes, IN = internet, rest is almost never used
|
||||||
_record_classes = (u'IN', u'CS', u'CH', u'HS')
|
_record_classes = (u'IN', u'CS', u'CH', u'HS')
|
||||||
|
|
||||||
|
def _rname_validator(ugettext, zonemgr):
|
||||||
|
try:
|
||||||
|
validate_zonemgr(zonemgr)
|
||||||
|
except ValueError, e:
|
||||||
|
return unicode(e)
|
||||||
|
return None
|
||||||
|
|
||||||
# normalizer for admin email
|
# normalizer for admin email
|
||||||
def _rname_normalizer(value):
|
def _rname_normalizer(value):
|
||||||
value = value.replace('@', '.')
|
value = value.replace('@', '.')
|
||||||
@@ -323,6 +331,7 @@ class dnszone(LDAPObject):
|
|||||||
doc=_('Authoritative nameserver domain name'),
|
doc=_('Authoritative nameserver domain name'),
|
||||||
),
|
),
|
||||||
Str('idnssoarname',
|
Str('idnssoarname',
|
||||||
|
_rname_validator,
|
||||||
cli_name='admin_email',
|
cli_name='admin_email',
|
||||||
label=_('Administrator e-mail address'),
|
label=_('Administrator e-mail address'),
|
||||||
doc=_('Administrator e-mail address'),
|
doc=_('Administrator e-mail address'),
|
||||||
|
|||||||
@@ -203,3 +203,33 @@ def check_writable_file(filename):
|
|||||||
fp.close()
|
fp.close()
|
||||||
except (IOError, OSError), e:
|
except (IOError, OSError), e:
|
||||||
raise errors.FileError(reason=str(e))
|
raise errors.FileError(reason=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
if len(zonemgr) > 255:
|
||||||
|
raise ValueError(_('cannot be longer that 255 characters'))
|
||||||
|
|
||||||
|
if zonemgr.count('@') == 1:
|
||||||
|
name, dot, domain = zonemgr.partition('@')
|
||||||
|
elif zonemgr.count('@') > 1:
|
||||||
|
raise ValueError(_('too many \'@\' characters'))
|
||||||
|
else:
|
||||||
|
# address in SOA format already (without @)
|
||||||
|
name, dot, domain = zonemgr.partition('.')
|
||||||
|
|
||||||
|
if domain.endswith('.'):
|
||||||
|
domain = domain[:-1]
|
||||||
|
|
||||||
|
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 -'))
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ from ipaserver.install.installutils import resolve_host
|
|||||||
from ipapython import sysrestore
|
from ipapython import sysrestore
|
||||||
from ipapython import ipautil
|
from ipapython import ipautil
|
||||||
from ipalib.constants import DNS_ZONE_REFRESH
|
from ipalib.constants import DNS_ZONE_REFRESH
|
||||||
|
from ipalib.parameters import IA5Str
|
||||||
|
from ipalib.util import validate_zonemgr
|
||||||
|
|
||||||
import ipalib
|
import ipalib
|
||||||
from ipalib import api, util, errors
|
from ipalib import api, util, errors
|
||||||
@@ -286,6 +288,21 @@ def get_rr(zone, name, type):
|
|||||||
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def zonemgr_callback(option, opt_str, value, parser):
|
||||||
|
"""
|
||||||
|
Properly validate and convert --zonemgr Option to IA5String
|
||||||
|
"""
|
||||||
|
# validate the value first
|
||||||
|
try:
|
||||||
|
validate_zonemgr(value)
|
||||||
|
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):
|
class DnsBackup(object):
|
||||||
def __init__(self, service):
|
def __init__(self, service):
|
||||||
|
|||||||
Reference in New Issue
Block a user