summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
authorTomas Babej <tbabej@redhat.com>2012-10-26 07:43:05 -0400
committerMartin Kosek <mkosek@redhat.com>2012-12-17 15:29:35 +0100
commit389854756b717b171430bf2f8c57f310d05a5188 (patch)
tree1a99f98c50a8ffc755a52a474843ffd27e362764 /ipalib
parentfa6be6d8db985d6c85c819fe62c0a1edac63fd40 (diff)
downloadfreeipa-389854756b717b171430bf2f8c57f310d05a5188.tar.gz
freeipa-389854756b717b171430bf2f8c57f310d05a5188.tar.xz
freeipa-389854756b717b171430bf2f8c57f310d05a5188.zip
Forbid overlapping rid ranges for the same id range
Creating an id range with overlapping primary and secondary rid range using idrange-add or idrange-mod command now raises ValidationError. Unit tests have been added to test_range_plugin.py. https://fedorahosted.org/freeipa/ticket/3171
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/plugins/idrange.py79
1 files changed, 69 insertions, 10 deletions
diff --git a/ipalib/plugins/idrange.py b/ipalib/plugins/idrange.py
index 754708117..84e1057ac 100644
--- a/ipalib/plugins/idrange.py
+++ b/ipalib/plugins/idrange.py
@@ -277,6 +277,25 @@ class idrange(LDAPObject):
raise errors.ValidationError(name='domain SID',
error=_('SID is not recognized as a valid SID for a trusted domain'))
+ # checks that primary and secondary rid ranges do not overlap
+ def are_rid_ranges_overlapping(self, rid_base, secondary_rid_base, size):
+
+ # if any of these is None, the check does not apply
+ if any(attr is None for attr in (rid_base, secondary_rid_base, size)):
+ return False
+
+ # sort the bases
+ if rid_base > secondary_rid_base:
+ rid_base, secondary_rid_base = secondary_rid_base, rid_base
+
+ # rid_base is now <= secondary_rid_base,
+ # so the following check is sufficient
+ if rid_base + size <= secondary_rid_base:
+ return False
+ else:
+ return True
+
+
class idrange_add(LDAPCreate):
__doc__ = _("""
Add new ID range.
@@ -315,27 +334,39 @@ class idrange_add(LDAPCreate):
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
- if 'ipanttrusteddomainsid' in options:
- if 'ipasecondarybaserid' in options:
+ is_set = lambda x: (x in entry_attrs) and (x is not None)
+
+ if is_set('ipanttrusteddomainsid'):
+ if is_set('ipasecondarybaserid'):
raise errors.ValidationError(name='ID Range setup',
- error=_('Options dom_sid and secondary_rid_base cannot ' \
+ error=_('Options dom_sid and secondary_rid_base cannot '
'be used together'))
- if 'ipabaserid' not in options:
+ if not is_set('ipabaserid'):
raise errors.ValidationError(name='ID Range setup',
- error=_('Options dom_sid and rid_base must ' \
+ error=_('Options dom_sid and rid_base must '
'be used together'))
# Validate SID as the one of trusted domains
self.obj.validate_trusted_domain_sid(options['ipanttrusteddomainsid'])
# Finally, add trusted AD domain range object class
entry_attrs['objectclass'].append('ipatrustedaddomainrange')
+
else:
- if (('ipasecondarybaserid' in options) != ('ipabaserid' in options)):
+ if is_set('ipasecondarybaserid') != is_set('ipabaserid'):
raise errors.ValidationError(name='ID Range setup',
- error=_('Options secondary_rid_base and rid_base must ' \
+ error=_('Options secondary_rid_base and rid_base must '
'be used together'))
+ if is_set('ipabaserid') and is_set('ipasecondarybaserid'):
+ if self.obj.are_rid_ranges_overlapping(
+ entry_attrs['ipabaserid'],
+ entry_attrs['ipasecondarybaserid'],
+ entry_attrs['ipaidrangesize']):
+ raise errors.ValidationError(name='ID Range setup',
+ error=_("Primary RID range and secondary RID range"
+ " cannot overlap"))
+
entry_attrs['objectclass'].append('ipadomainidrange')
return dn
@@ -377,7 +408,7 @@ class idrange_find(LDAPSearch):
return (filters, base_dn, ldap.SCOPE_ONELEVEL)
def post_callback(self, ldap, entries, truncated, *args, **options):
- for dn,entry in entries:
+ for dn, entry in entries:
self.obj.handle_iparangetype(entry, options)
return truncated
@@ -403,15 +434,43 @@ class idrange_mod(LDAPUpdate):
assert isinstance(dn, DN)
attrs_list.append('objectclass')
+ is_set = lambda x: (x in entry_attrs) and (x is not None)
+
try:
- (old_dn, old_attrs) = ldap.get_entry(dn, ['ipabaseid', 'ipaidrangesize'])
+ (old_dn, old_attrs) = ldap.get_entry(dn,
+ ['ipabaseid',
+ 'ipaidrangesize',
+ 'ipabaserid',
+ 'ipasecondarybaserid'])
except errors.NotFound:
self.obj.handle_not_found(*keys)
- if 'ipanttrusteddomainsid' in options:
+ if is_set('ipanttrusteddomainsid'):
# Validate SID as the one of trusted domains
self.obj.validate_trusted_domain_sid(options['ipanttrusteddomainsid'])
+ # ensure that primary and secondary rid ranges do not overlap
+ if all((base in entry_attrs) or (base in old_attrs)
+ for base in ('ipabaserid', 'ipasecondarybaserid')):
+
+ # make sure we are working with updated attributes
+ rid_range_attributes = ('ipabaserid', 'ipasecondarybaserid', 'ipaidrangesize')
+ updated_values = dict()
+
+ for attr in rid_range_attributes:
+ if is_set(attr):
+ updated_values[attr] = entry_attrs[attr]
+ else:
+ updated_values[attr] = int(old_attrs[attr][0])
+
+ if self.obj.are_rid_ranges_overlapping(
+ updated_values['ipabaserid'],
+ updated_values['ipasecondarybaserid'],
+ updated_values['ipaidrangesize']):
+ raise errors.ValidationError(name='ID Range setup',
+ error=_("Primary RID range and secondary RID range"
+ " cannot overlap"))
+
old_base_id = int(old_attrs.get('ipabaseid', [0])[0])
old_range_size = int(old_attrs.get('ipaidrangesize', [0])[0])
new_base_id = entry_attrs.get('ipabaseid')