summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2012-05-23 11:00:24 -0400
committerMartin Kosek <mkosek@redhat.com>2012-05-30 08:46:21 +0200
commit8d00d7c13038abc152afbd46c96108753506fb77 (patch)
tree8d5242dee69fce097b05f961c2b104f82275213b
parentd62b2d9be5a1162f5fdb255aa4f361ce048722fa (diff)
downloadfreeipa-8d00d7c13038abc152afbd46c96108753506fb77.tar.gz
freeipa-8d00d7c13038abc152afbd46c96108753506fb77.tar.xz
freeipa-8d00d7c13038abc152afbd46c96108753506fb77.zip
Enforce sizelimit in permission-find, post_callback returns truncated
We actually perform two searches in permission-find. The first looks for matches within the permission object itself. The second looks at matches in the underlying aci. We need to break out in two places. The first is if we find enough matches in the permission itself. The second when we are appending matches from acis. The post_callback() definition needed to be modified to return the truncated value so a plugin author can modify that value. https://fedorahosted.org/freeipa/ticket/2322
-rw-r--r--ipalib/plugins/baseldap.py6
-rw-r--r--ipalib/plugins/dns.py4
-rw-r--r--ipalib/plugins/entitle.py1
-rw-r--r--ipalib/plugins/host.py4
-rw-r--r--ipalib/plugins/hostgroup.py3
-rw-r--r--ipalib/plugins/permission.py18
-rw-r--r--ipalib/plugins/pwpolicy.py2
-rw-r--r--ipalib/plugins/selinuxusermap.py3
-rw-r--r--ipalib/plugins/service.py3
-rw-r--r--ipalib/plugins/user.py3
-rw-r--r--tests/test_xmlrpc/test_permission_plugin.py74
11 files changed, 110 insertions, 11 deletions
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 58d53fd0d..93852a2dd 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -1857,9 +1857,9 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
for callback in self.POST_CALLBACKS:
if hasattr(callback, 'im_self'):
- callback(ldap, entries, truncated, *args, **options)
+ truncated = callback(ldap, entries, truncated, *args, **options)
else:
- callback(self, ldap, entries, truncated, *args, **options)
+ truncated = callback(self, ldap, entries, truncated, *args, **options)
if self.sort_result_entries:
if self.obj.primary_key:
@@ -1884,7 +1884,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
return (filters, base_dn, scope)
def post_callback(self, ldap, entries, truncated, *args, **options):
- pass
+ return truncated
def exc_callback(self, args, options, exc, call_func, *call_args, **call_kwargs):
raise exc
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index e26332d46..e2b5995b9 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -132,7 +132,7 @@ EXAMPLES:
SRV record: 0 3 389 fast.example.com, 0 1 389 slow.example.com, 1 1 389 backup.example.com
- Modify SRV record '0 3 389 fast.example.com'? Yes/No (default No):
+ Modify SRV record '0 3 389 fast.example.com'? Yes/No (default No):
Modify SRV record '0 1 389 slow.example.com'? Yes/No (default No): y
SRV Priority [0]: (keep the default value)
SRV Weight [1]: 2 (modified value)
@@ -2589,6 +2589,8 @@ class dnsrecord_find(LDAPSearch):
for entry in entries:
self.obj.postprocess_record(entry[1], **options)
+ return truncated
+
api.register(dnsrecord_find)
class dns_resolve(Command):
diff --git a/ipalib/plugins/entitle.py b/ipalib/plugins/entitle.py
index 6ade854c3..5ccdb6510 100644
--- a/ipalib/plugins/entitle.py
+++ b/ipalib/plugins/entitle.py
@@ -461,6 +461,7 @@ class entitle_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if len(entries) == 0:
raise errors.NotRegisteredError()
+ return truncated
api.register(entitle_find)
diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
index 662cff311..96b73cc55 100644
--- a/ipalib/plugins/host.py
+++ b/ipalib/plugins/host.py
@@ -769,7 +769,7 @@ class host_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
- return
+ return truncated
for entry in entries:
(dn, entry_attrs) = entry
set_certificate_attrs(entry_attrs)
@@ -785,6 +785,8 @@ class host_find(LDAPSearch):
output_sshpubkey(ldap, dn, entry_attrs)
+ return truncated
+
api.register(host_find)
diff --git a/ipalib/plugins/hostgroup.py b/ipalib/plugins/hostgroup.py
index 2a9a0a533..b68c45842 100644
--- a/ipalib/plugins/hostgroup.py
+++ b/ipalib/plugins/hostgroup.py
@@ -182,10 +182,11 @@ class hostgroup_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
- return
+ return truncated
for entry in entries:
(dn, entry_attrs) = entry
self.obj.suppress_netgroup_memberof(dn, entry_attrs)
+ return truncated
api.register(hostgroup_find)
diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py
index 18fdcdddf..a484ff640 100644
--- a/ipalib/plugins/permission.py
+++ b/ipalib/plugins/permission.py
@@ -351,7 +351,7 @@ class permission_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.pop('pkey_only', False):
- return
+ return truncated
for entry in entries:
(dn, attrs) = entry
try:
@@ -363,6 +363,15 @@ class permission_find(LDAPSearch):
attrs[attr] = aci[attr]
except errors.NotFound:
self.debug('ACI not found for %s' % attrs['cn'][0])
+ if truncated:
+ # size/time limit met, no need to search acis
+ return truncated
+
+ if 'sizelimit' in options:
+ max_entries = options['sizelimit']
+ else:
+ config = ldap.get_ipa_config()[1]
+ max_entries = config['ipasearchrecordslimit']
# Now find all the ACIs that match. Once we find them, add any that
# aren't already in the list along with their permission info.
@@ -398,7 +407,12 @@ class permission_find(LDAPSearch):
dn = permission['dn']
del permission['dn']
if (dn, permission) not in entries:
- entries.append((dn, permission))
+ if len(entries) < max_entries:
+ entries.append((dn, permission))
+ else:
+ truncated = True
+ break
+ return truncated
api.register(permission_find)
diff --git a/ipalib/plugins/pwpolicy.py b/ipalib/plugins/pwpolicy.py
index 7be590f2e..77e6f2c79 100644
--- a/ipalib/plugins/pwpolicy.py
+++ b/ipalib/plugins/pwpolicy.py
@@ -498,4 +498,6 @@ class pwpolicy_find(LDAPSearch):
except KeyError:
pass
+ return truncated
+
api.register(pwpolicy_find)
diff --git a/ipalib/plugins/selinuxusermap.py b/ipalib/plugins/selinuxusermap.py
index e6179cee9..160e68c96 100644
--- a/ipalib/plugins/selinuxusermap.py
+++ b/ipalib/plugins/selinuxusermap.py
@@ -318,10 +318,11 @@ all=True)['result']
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
- return
+ return truncated
for entry in entries:
(dn, attrs) = entry
self.obj._convert_seealso(ldap, attrs, **options)
+ return truncated
api.register(selinuxusermap_find)
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
index 333d5bbf3..24a0a0f87 100644
--- a/ipalib/plugins/service.py
+++ b/ipalib/plugins/service.py
@@ -399,11 +399,12 @@ class service_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
- return
+ return truncated
for entry in entries:
(dn, entry_attrs) = entry
self.obj.get_password_attributes(ldap, dn, entry_attrs)
set_certificate_attrs(entry_attrs)
+ return truncated
api.register(service_find)
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 2e069bde3..b48e68022 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -625,13 +625,14 @@ class user_find(LDAPSearch):
def post_callback(self, ldap, entries, truncated, *args, **options):
if options.get('pkey_only', False):
- return
+ return truncated
for entry in entries:
(dn, attrs) = entry
self.obj._convert_manager(attrs, **options)
self.obj.get_password_attributes(ldap, dn, attrs)
convert_nsaccountlock(attrs)
output_sshpubkey(ldap, dn, attrs)
+ return truncated
msg_summary = ngettext(
'%(count)d user matched', '%(count)d users matched', 0
diff --git a/tests/test_xmlrpc/test_permission_plugin.py b/tests/test_xmlrpc/test_permission_plugin.py
index 28db7dc2f..d8ff14903 100644
--- a/tests/test_xmlrpc/test_permission_plugin.py
+++ b/tests/test_xmlrpc/test_permission_plugin.py
@@ -387,6 +387,80 @@ class test_permission(Declarative):
dict(
+ desc='Search for %r with a limit of 1 (truncated)' % permission1,
+ command=('permission_find', [permission1], dict(sizelimit=1)),
+ expected=dict(
+ count=1,
+ truncated=True,
+ summary=u'1 permission matched',
+ result=[
+ {
+ 'dn': lambda x: DN(x) == permission1_dn,
+ 'cn': [permission1],
+ 'member_privilege': [privilege1],
+ 'type': u'user',
+ 'permissions': [u'write'],
+ },
+ ],
+ ),
+ ),
+
+
+ dict(
+ desc='Search for %r with a limit of 2' % permission1,
+ command=('permission_find', [permission1], dict(sizelimit=2)),
+ expected=dict(
+ count=2,
+ truncated=False,
+ summary=u'2 permissions matched',
+ result=[
+ {
+ 'dn': lambda x: DN(x) == permission1_dn,
+ 'cn': [permission1],
+ 'member_privilege': [privilege1],
+ 'type': u'user',
+ 'permissions': [u'write'],
+ },
+ {
+ 'dn': lambda x: DN(x) == permission2_dn,
+ 'cn': [permission2],
+ 'type': u'user',
+ 'permissions': [u'write'],
+ },
+ ],
+ ),
+ ),
+
+
+ # This tests setting truncated to True in the post_callback of
+ # permission_find(). The return order in LDAP is not guaranteed
+ # but in practice this is the first entry it finds. This is subject
+ # to change.
+ dict(
+ desc='Search for permissions by attr with a limit of 1 (truncated)',
+ command=('permission_find', [], dict(attrs=u'ipaenabledflag',
+ sizelimit=1)),
+ expected=dict(
+ count=1,
+ truncated=True,
+ summary=u'1 permission matched',
+ result=[
+ {
+ 'dn': lambda x: DN(x) == DN(('cn', 'Modify HBAC rule'),
+ api.env.container_permission,api.env.basedn),
+ 'cn': [u'Modify HBAC rule'],
+ 'member_privilege': [u'HBAC Administrator'],
+ 'permissions' : [u'write'],
+ 'attrs': [u'servicecategory', u'sourcehostcategory', u'cn', u'description', u'ipaenabledflag', u'accesstime', u'usercategory', u'hostcategory', u'accessruletype', u'sourcehost'],
+ 'subtree' : u'ldap:///ipauniqueid=*,cn=hbac,%s' % api.env.basedn,
+ 'memberindirect': [u'cn=hbac administrator,cn=privileges,cn=pbac,%s' % api.env.basedn, u'cn=it security specialist,cn=roles,cn=accounts,%s' % api.env.basedn],
+ },
+ ],
+ ),
+ ),
+
+
+ dict(
desc='Update %r' % permission1,
command=(
'permission_mod', [permission1], dict(permissions=u'read', memberof=u'ipausers')