|
|
3280a9 |
From 788d7c69a446d1ae324b2c58daaa5d4fd5528748 Mon Sep 17 00:00:00 2001
|
|
|
ef1f48 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
ef1f48 |
Date: Wed, 20 Jan 2021 16:42:15 -0500
|
|
|
3280a9 |
Subject: [PATCH 1/3] Issue 5442 - Search results are different between RHDS10
|
|
|
ef1f48 |
and RHDS11
|
|
|
ef1f48 |
|
|
|
ef1f48 |
Bug Description: In 1.4.x we introduced a change that was overly strict about
|
|
|
ef1f48 |
how a search on a non-existent subtree returned its error code.
|
|
|
ef1f48 |
It was changed from returning an error 32 to an error 0 with
|
|
|
ef1f48 |
zero entries returned.
|
|
|
ef1f48 |
|
|
|
ef1f48 |
Fix Description: When finding the entry and processing acl's make sure to
|
|
|
ef1f48 |
gather the aci's that match the resource even if the resource
|
|
|
ef1f48 |
does not exist. This requires some extra checks when processing
|
|
|
ef1f48 |
the target attribute.
|
|
|
ef1f48 |
|
|
|
ef1f48 |
relates: https://github.com/389ds/389-ds-base/issues/4542
|
|
|
ef1f48 |
|
|
|
ef1f48 |
Reviewed by: firstyear, elkris, and tbordaz (Thanks!)
|
|
|
ef1f48 |
|
|
|
ef1f48 |
Apply Thierry's changes
|
|
|
ef1f48 |
|
|
|
ef1f48 |
round 2
|
|
|
ef1f48 |
|
|
|
ef1f48 |
Apply more suggestions from Thierry
|
|
|
ef1f48 |
---
|
|
|
ef1f48 |
dirsrvtests/tests/suites/acl/misc_test.py | 108 +++++++-
|
|
|
ef1f48 |
ldap/servers/plugins/acl/acl.c | 296 ++++++++++------------
|
|
|
ef1f48 |
ldap/servers/slapd/back-ldbm/findentry.c | 6 +-
|
|
|
ef1f48 |
src/lib389/lib389/_mapped_object.py | 4 +-
|
|
|
ef1f48 |
4 files changed, 239 insertions(+), 175 deletions(-)
|
|
|
ef1f48 |
|
|
|
ef1f48 |
diff --git a/dirsrvtests/tests/suites/acl/misc_test.py b/dirsrvtests/tests/suites/acl/misc_test.py
|
|
|
3280a9 |
index 5f0e3eb72..c640e60ad 100644
|
|
|
ef1f48 |
--- a/dirsrvtests/tests/suites/acl/misc_test.py
|
|
|
ef1f48 |
+++ b/dirsrvtests/tests/suites/acl/misc_test.py
|
|
|
3280a9 |
@@ -12,7 +12,7 @@ import ldap
|
|
|
ef1f48 |
import os
|
|
|
ef1f48 |
import pytest
|
|
|
ef1f48 |
|
|
|
ef1f48 |
-from lib389._constants import DEFAULT_SUFFIX, PW_DM
|
|
|
ef1f48 |
+from lib389._constants import DEFAULT_SUFFIX, PW_DM, DN_DM
|
|
|
ef1f48 |
from lib389.idm.user import UserAccount, UserAccounts
|
|
|
ef1f48 |
from lib389._mapped_object import DSLdapObject
|
|
|
ef1f48 |
from lib389.idm.account import Accounts, Anonymous
|
|
|
3280a9 |
@@ -408,14 +408,112 @@ def test_do_bind_as_201_distinct_users(topo, clean, aci_of_user):
|
|
|
ef1f48 |
user = uas.create_test_user(uid=i, gid=i)
|
|
|
ef1f48 |
user.set('userPassword', PW_DM)
|
|
|
ef1f48 |
|
|
|
ef1f48 |
- for i in range(len(uas.list())):
|
|
|
ef1f48 |
- uas.list()[i].bind(PW_DM)
|
|
|
ef1f48 |
+ users = uas.list()
|
|
|
ef1f48 |
+ for user in users:
|
|
|
ef1f48 |
+ user.bind(PW_DM)
|
|
|
ef1f48 |
|
|
|
ef1f48 |
ACLPlugin(topo.standalone).replace("nsslapd-aclpb-max-selected-acls", '220')
|
|
|
ef1f48 |
topo.standalone.restart()
|
|
|
ef1f48 |
|
|
|
ef1f48 |
- for i in range(len(uas.list())):
|
|
|
ef1f48 |
- uas.list()[i].bind(PW_DM)
|
|
|
ef1f48 |
+ users = uas.list()
|
|
|
ef1f48 |
+ for user in users:
|
|
|
ef1f48 |
+ user.bind(PW_DM)
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+def test_info_disclosure(request, topo):
|
|
|
ef1f48 |
+ """Test that a search returns 32 when base entry does not exist
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ :id: f6dec4c2-65a3-41e4-a4c0-146196863333
|
|
|
ef1f48 |
+ :setup: Standalone Instance
|
|
|
ef1f48 |
+ :steps:
|
|
|
ef1f48 |
+ 1. Add aci
|
|
|
ef1f48 |
+ 2. Add test user
|
|
|
ef1f48 |
+ 3. Bind as user and search for non-existent entry
|
|
|
ef1f48 |
+ :expectedresults:
|
|
|
ef1f48 |
+ 1. Success
|
|
|
ef1f48 |
+ 2. Success
|
|
|
ef1f48 |
+ 3. Error 32 is returned
|
|
|
ef1f48 |
+ """
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ ACI_TARGET = "(targetattr = \"*\")(target = \"ldap:///%s\")" % (DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ ACI_ALLOW = "(version 3.0; acl \"Read/Search permission for all users\"; allow (read,search)"
|
|
|
ef1f48 |
+ ACI_SUBJECT = "(userdn=\"ldap:///all\");)"
|
|
|
ef1f48 |
+ ACI = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ # Get current ACi's so we can restore them when we are done
|
|
|
ef1f48 |
+ suffix = Domain(topo.standalone, DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ preserved_acis = suffix.get_attr_vals_utf8('aci')
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ def finofaci():
|
|
|
ef1f48 |
+ domain = Domain(topo.standalone, DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ try:
|
|
|
ef1f48 |
+ domain.remove_all('aci')
|
|
|
ef1f48 |
+ domain.replace_values('aci', preserved_acis)
|
|
|
ef1f48 |
+ except:
|
|
|
ef1f48 |
+ pass
|
|
|
ef1f48 |
+ request.addfinalizer(finofaci)
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ # Remove aci's
|
|
|
ef1f48 |
+ suffix.remove_all('aci')
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ # Add test user
|
|
|
ef1f48 |
+ USER_DN = "uid=test,ou=people," + DEFAULT_SUFFIX
|
|
|
ef1f48 |
+ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ users.create(properties={
|
|
|
ef1f48 |
+ 'uid': 'test',
|
|
|
ef1f48 |
+ 'cn': 'test',
|
|
|
ef1f48 |
+ 'sn': 'test',
|
|
|
ef1f48 |
+ 'uidNumber': '1000',
|
|
|
ef1f48 |
+ 'gidNumber': '2000',
|
|
|
ef1f48 |
+ 'homeDirectory': '/home/test',
|
|
|
ef1f48 |
+ 'userPassword': PW_DM
|
|
|
ef1f48 |
+ })
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ # bind as user
|
|
|
ef1f48 |
+ conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ # Search fo existing base DN
|
|
|
ef1f48 |
+ test = Domain(conn, DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ try:
|
|
|
ef1f48 |
+ test.get_attr_vals_utf8_l('dc')
|
|
|
ef1f48 |
+ assert False
|
|
|
ef1f48 |
+ except IndexError:
|
|
|
ef1f48 |
+ pass
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ # Search for a non existent bases
|
|
|
ef1f48 |
+ subtree = Domain(conn, "ou=does_not_exist," + DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ try:
|
|
|
ef1f48 |
+ subtree.get_attr_vals_utf8_l('objectclass')
|
|
|
ef1f48 |
+ except IndexError:
|
|
|
ef1f48 |
+ pass
|
|
|
ef1f48 |
+ subtree = Domain(conn, "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ try:
|
|
|
ef1f48 |
+ subtree.get_attr_vals_utf8_l('objectclass')
|
|
|
ef1f48 |
+ except IndexError:
|
|
|
ef1f48 |
+ pass
|
|
|
ef1f48 |
+ # Try ONE level search instead of BASE
|
|
|
ef1f48 |
+ try:
|
|
|
ef1f48 |
+ Accounts(conn, "ou=does_not_exist," + DEFAULT_SUFFIX).filter("(objectclass=top)", ldap.SCOPE_ONELEVEL)
|
|
|
ef1f48 |
+ except IndexError:
|
|
|
ef1f48 |
+ pass
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ # add aci
|
|
|
ef1f48 |
+ suffix.add('aci', ACI)
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
+ # Search for a non existent entry which should raise an exception
|
|
|
ef1f48 |
+ with pytest.raises(ldap.NO_SUCH_OBJECT):
|
|
|
ef1f48 |
+ conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
|
|
|
ef1f48 |
+ subtree = Domain(conn, "ou=does_not_exist," + DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ subtree.get_attr_vals_utf8_l('objectclass')
|
|
|
ef1f48 |
+ with pytest.raises(ldap.NO_SUCH_OBJECT):
|
|
|
ef1f48 |
+ conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
|
|
|
ef1f48 |
+ subtree = Domain(conn, "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX)
|
|
|
ef1f48 |
+ subtree.get_attr_vals_utf8_l('objectclass')
|
|
|
ef1f48 |
+ with pytest.raises(ldap.NO_SUCH_OBJECT):
|
|
|
ef1f48 |
+ conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
|
|
|
ef1f48 |
+ DN = "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX
|
|
|
ef1f48 |
+ Accounts(conn, DN).filter("(objectclass=top)", ldap.SCOPE_ONELEVEL, strict=True)
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
|
|
|
ef1f48 |
if __name__ == "__main__":
|
|
|
3280a9 |
CURRENT_FILE = os.path.realpath(__file__)
|
|
|
ef1f48 |
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
|
|
|
ef1f48 |
index 41a909a18..4e811f73a 100644
|
|
|
ef1f48 |
--- a/ldap/servers/plugins/acl/acl.c
|
|
|
ef1f48 |
+++ b/ldap/servers/plugins/acl/acl.c
|
|
|
ef1f48 |
@@ -2111,10 +2111,11 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
aci_right = aci->aci_access;
|
|
|
ef1f48 |
res_right = aclpb->aclpb_access;
|
|
|
ef1f48 |
if (!(aci_right & res_right)) {
|
|
|
ef1f48 |
- /* If we are looking for read/search and the acl has read/search
|
|
|
ef1f48 |
- ** then go further because if targets match we may keep that
|
|
|
ef1f48 |
- ** acl in the entry cache list.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ /*
|
|
|
ef1f48 |
+ * If we are looking for read/search and the acl has read/search
|
|
|
ef1f48 |
+ * then go further because if targets match we may keep that
|
|
|
ef1f48 |
+ * acl in the entry cache list.
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (!((res_right & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) &&
|
|
|
ef1f48 |
(aci_right & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ)))) {
|
|
|
ef1f48 |
matches = ACL_FALSE;
|
|
|
ef1f48 |
@@ -2122,30 +2123,29 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
- /* first Let's see if the entry is under the subtree where the
|
|
|
ef1f48 |
- ** ACL resides. We can't let somebody affect a target beyond the
|
|
|
ef1f48 |
- ** scope of where the ACL resides
|
|
|
ef1f48 |
- ** Example: ACL is located in "ou=engineering, o=ace industry, c=us
|
|
|
ef1f48 |
- ** but if the target is "o=ace industry, c=us", then we are in trouble.
|
|
|
ef1f48 |
- **
|
|
|
ef1f48 |
- ** If the aci is in the rootdse and the entry is not, then we do not
|
|
|
ef1f48 |
- ** match--ie. acis in the rootdse do NOT apply below...for the moment.
|
|
|
ef1f48 |
- **
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ /*
|
|
|
ef1f48 |
+ * First Let's see if the entry is under the subtree where the
|
|
|
ef1f48 |
+ * ACL resides. We can't let somebody affect a target beyond the
|
|
|
ef1f48 |
+ * scope of where the ACL resides
|
|
|
ef1f48 |
+ * Example: ACL is located in "ou=engineering, o=ace industry, c=us
|
|
|
ef1f48 |
+ * but if the target is "o=ace industry, c=us", then we are in trouble.
|
|
|
ef1f48 |
+ *
|
|
|
ef1f48 |
+ * If the aci is in the rootdse and the entry is not, then we do not
|
|
|
ef1f48 |
+ * match--ie. acis in the rootdse do NOT apply below...for the moment.
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
res_ndn = slapi_sdn_get_ndn(aclpb->aclpb_curr_entry_sdn);
|
|
|
ef1f48 |
aci_ndn = slapi_sdn_get_ndn(aci->aci_sdn);
|
|
|
ef1f48 |
- if (!slapi_sdn_issuffix(aclpb->aclpb_curr_entry_sdn, aci->aci_sdn) || (!slapi_is_rootdse(res_ndn) && slapi_is_rootdse(aci_ndn))) {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
- /* cant' poke around */
|
|
|
ef1f48 |
+ if (!slapi_sdn_issuffix(aclpb->aclpb_curr_entry_sdn, aci->aci_sdn) ||
|
|
|
ef1f48 |
+ (!slapi_is_rootdse(res_ndn) && slapi_is_rootdse(aci_ndn)))
|
|
|
ef1f48 |
+ {
|
|
|
ef1f48 |
+ /* can't poke around */
|
|
|
ef1f48 |
matches = ACL_FALSE;
|
|
|
ef1f48 |
goto acl__resource_match_aci_EXIT;
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
- ** We have a single ACI which we need to find if it applies to
|
|
|
ef1f48 |
- ** the resource or not.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ * We have a single ACI which we need to find if it applies to the resource or not.
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if ((aci->aci_type & ACI_TARGET_DN) && (aclpb->aclpb_curr_entry_sdn)) {
|
|
|
ef1f48 |
char *avaType;
|
|
|
ef1f48 |
struct berval *avaValue;
|
|
|
ef1f48 |
@@ -2173,25 +2173,23 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
char *avaType;
|
|
|
ef1f48 |
struct berval *avaValue;
|
|
|
ef1f48 |
char logbuf[1024];
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
- /* We are evaluating the moddn permission.
|
|
|
ef1f48 |
- * The aci contains target_to and target_from
|
|
|
ef1f48 |
- *
|
|
|
ef1f48 |
- * target_to filter must be checked against the resource ndn that was stored in
|
|
|
ef1f48 |
- * aclpb->aclpb_curr_entry_sdn
|
|
|
ef1f48 |
- *
|
|
|
ef1f48 |
- * target_from filter must be check against the entry ndn that is in aclpb->aclpb_moddn_source_sdn
|
|
|
ef1f48 |
- * (sdn was stored in the pblock)
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ /*
|
|
|
ef1f48 |
+ * We are evaluating the moddn permission.
|
|
|
ef1f48 |
+ * The aci contains target_to and target_from
|
|
|
ef1f48 |
+ *
|
|
|
ef1f48 |
+ * target_to filter must be checked against the resource ndn that was stored in
|
|
|
ef1f48 |
+ * aclpb->aclpb_curr_entry_sdn
|
|
|
ef1f48 |
+ *
|
|
|
ef1f48 |
+ * target_from filter must be check against the entry ndn that is in aclpb->aclpb_moddn_source_sdn
|
|
|
ef1f48 |
+ * (sdn was stored in the pblock)
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (aci->target_to) {
|
|
|
ef1f48 |
f = aci->target_to;
|
|
|
ef1f48 |
dn_matched = ACL_TRUE;
|
|
|
ef1f48 |
|
|
|
ef1f48 |
/* Now check if the filter is a simple or substring filter */
|
|
|
ef1f48 |
if (aci->aci_type & ACI_TARGET_MODDN_TO_PATTERN) {
|
|
|
ef1f48 |
- /* This is a filter with substring
|
|
|
ef1f48 |
- * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ /* This is a filter with substring e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com */
|
|
|
ef1f48 |
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_to substring: %s\n",
|
|
|
ef1f48 |
slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
|
|
|
ef1f48 |
if ((rv = acl_match_substring(f, (char *)res_ndn, 0 /* match suffix */)) != ACL_TRUE) {
|
|
|
ef1f48 |
@@ -2204,9 +2202,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
} else {
|
|
|
ef1f48 |
- /* This is a filter without substring
|
|
|
ef1f48 |
- * e.g. ldap:///cn=accounts,dc=example,dc=com
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ /* This is a filter without substring e.g. ldap:///cn=accounts,dc=example,dc=com */
|
|
|
ef1f48 |
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_to: %s\n",
|
|
|
ef1f48 |
slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
|
|
|
ef1f48 |
slapi_filter_get_ava(f, &avaType, &avaValue);
|
|
|
ef1f48 |
@@ -2230,8 +2226,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
/* Now check if the filter is a simple or substring filter */
|
|
|
ef1f48 |
if (aci->aci_type & ACI_TARGET_MODDN_FROM_PATTERN) {
|
|
|
ef1f48 |
/* This is a filter with substring
|
|
|
ef1f48 |
- * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_from substring: %s\n",
|
|
|
ef1f48 |
slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
|
|
|
ef1f48 |
if ((rv = acl_match_substring(f, (char *)slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn), 0 /* match suffix */)) != ACL_TRUE) {
|
|
|
ef1f48 |
@@ -2243,11 +2239,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
goto acl__resource_match_aci_EXIT;
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
} else {
|
|
|
ef1f48 |
- /* This is a filter without substring
|
|
|
ef1f48 |
- * e.g. ldap:///cn=accounts,dc=example,dc=com
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ /* This is a filter without substring e.g. ldap:///cn=accounts,dc=example,dc=com */
|
|
|
ef1f48 |
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_from: %s\n",
|
|
|
ef1f48 |
slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
|
|
|
ef1f48 |
if (!slapi_dn_issuffix(slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn), avaValue->bv_val)) {
|
|
|
ef1f48 |
@@ -2269,10 +2262,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
if (aci->aci_type & ACI_TARGET_PATTERN) {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
f = aci->target;
|
|
|
ef1f48 |
dn_matched = ACL_TRUE;
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
if ((rv = acl_match_substring(f, (char *)res_ndn, 0 /* match suffux */)) != ACL_TRUE) {
|
|
|
ef1f48 |
dn_matched = ACL_FALSE;
|
|
|
ef1f48 |
if (rv == ACL_ERR) {
|
|
|
ef1f48 |
@@ -2296,7 +2287,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
* Is it a (target="ldap://cn=*,($dn),o=sun.com") kind of thing.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (aci->aci_type & ACI_TARGET_MACRO_DN) {
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
* See if the ($dn) component matches the string and
|
|
|
ef1f48 |
@@ -2306,8 +2297,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
* entry is the same one don't recalculate it--
|
|
|
ef1f48 |
* this flag only works for search right now, could
|
|
|
ef1f48 |
* also optimise for mods by making it work for mods.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if ((aclpb->aclpb_res_type & ACLPB_NEW_ENTRY) == 0) {
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
* Here same entry so just look up the matched value,
|
|
|
ef1f48 |
@@ -2356,8 +2346,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
* If there is already an entry for this aci in this
|
|
|
ef1f48 |
* aclpb then remove it--it's an old value for a
|
|
|
ef1f48 |
* different entry.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
acl_ht_add_and_freeOld(aclpb->aclpb_macro_ht,
|
|
|
ef1f48 |
(PLHashNumber)aci->aci_index,
|
|
|
ef1f48 |
matched_val);
|
|
|
ef1f48 |
@@ -2381,30 +2370,27 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
- ** Here, if there's a targetfilter field, see if it matches.
|
|
|
ef1f48 |
- **
|
|
|
ef1f48 |
- ** The commented out code below was an erroneous attempt to skip
|
|
|
ef1f48 |
- ** this test. It is wrong because: 1. you need to store
|
|
|
ef1f48 |
- ** whether the last test matched or not (you cannot just assume it did)
|
|
|
ef1f48 |
- ** and 2. It may not be the same aci, so the previous matched
|
|
|
ef1f48 |
- ** value is a function of the aci.
|
|
|
ef1f48 |
- ** May be interesting to build such a cache...but no evidence for
|
|
|
ef1f48 |
- ** for that right now. See Bug 383424.
|
|
|
ef1f48 |
- **
|
|
|
ef1f48 |
- **
|
|
|
ef1f48 |
- ** && ((aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST) ||
|
|
|
ef1f48 |
- ** (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY))
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ * Here, if there's a targetfilter field, see if it matches.
|
|
|
ef1f48 |
+ *
|
|
|
ef1f48 |
+ * The commented out code below was an erroneous attempt to skip
|
|
|
ef1f48 |
+ * this test. It is wrong because: 1. you need to store
|
|
|
ef1f48 |
+ * whether the last test matched or not (you cannot just assume it did)
|
|
|
ef1f48 |
+ * and 2. It may not be the same aci, so the previous matched
|
|
|
ef1f48 |
+ * value is a function of the aci.
|
|
|
ef1f48 |
+ * May be interesting to build such a cache...but no evidence for
|
|
|
ef1f48 |
+ * for that right now. See Bug 383424.
|
|
|
ef1f48 |
+ *
|
|
|
ef1f48 |
+ *
|
|
|
ef1f48 |
+ * && ((aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST) ||
|
|
|
ef1f48 |
+ * (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY))
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (aci->aci_type & ACI_TARGET_FILTER) {
|
|
|
ef1f48 |
int filter_matched = ACL_TRUE;
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
* Check for macros.
|
|
|
ef1f48 |
* For targetfilter we need to fake the lasinfo structure--it's
|
|
|
ef1f48 |
* created "naturally" for subjects but not targets.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (aci->aci_type & ACI_TARGET_FILTER_MACRO_DN) {
|
|
|
ef1f48 |
|
|
|
ef1f48 |
lasInfo *lasinfo = NULL;
|
|
|
ef1f48 |
@@ -2419,11 +2405,9 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
ACL_EVAL_TARGET_FILTER);
|
|
|
ef1f48 |
slapi_ch_free((void **)&lasinfo);
|
|
|
ef1f48 |
} else {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
if (slapi_vattr_filter_test(NULL, aclpb->aclpb_curr_entry,
|
|
|
ef1f48 |
aci->targetFilter,
|
|
|
ef1f48 |
- 0 /*don't do acess chk*/) != 0) {
|
|
|
ef1f48 |
+ 0 /*don't do access check*/) != 0) {
|
|
|
ef1f48 |
filter_matched = ACL_FALSE;
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
@@ -2450,7 +2434,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
* Check to see if we need to evaluate any targetattrfilters.
|
|
|
ef1f48 |
* They look as follows:
|
|
|
ef1f48 |
* (targetattrfilters="add=sn:(sn=rob) && gn:(gn!=byrne),
|
|
|
ef1f48 |
- * del=sn:(sn=rob) && gn:(gn=byrne)")
|
|
|
ef1f48 |
+ * del=sn:(sn=rob) && gn:(gn=byrne)")
|
|
|
ef1f48 |
*
|
|
|
ef1f48 |
* For ADD/DELETE:
|
|
|
ef1f48 |
* If theres's a targetattrfilter then each add/del filter
|
|
|
ef1f48 |
@@ -2458,29 +2442,25 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
* by each value of the attribute in the entry.
|
|
|
ef1f48 |
*
|
|
|
ef1f48 |
* For MODIFY:
|
|
|
ef1f48 |
- * If there's a targetattrfilter then the add/del filter
|
|
|
ef1f48 |
+ * If there's a targetattrfilter then the add/del filter
|
|
|
ef1f48 |
* must be satisfied by the attribute to be added/deleted.
|
|
|
ef1f48 |
* (MODIFY acl is evaluated one value at a time).
|
|
|
ef1f48 |
*
|
|
|
ef1f48 |
*
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (((aclpb->aclpb_access & SLAPI_ACL_ADD) &&
|
|
|
ef1f48 |
(aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) ||
|
|
|
ef1f48 |
((aclpb->aclpb_access & SLAPI_ACL_DELETE) &&
|
|
|
ef1f48 |
- (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS))) {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)))
|
|
|
ef1f48 |
+ {
|
|
|
ef1f48 |
Targetattrfilter **attrFilterArray = NULL;
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
Targetattrfilter *attrFilter = NULL;
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
Slapi_Attr *attr_ptr = NULL;
|
|
|
ef1f48 |
Slapi_Value *sval;
|
|
|
ef1f48 |
const struct berval *attrVal;
|
|
|
ef1f48 |
int k;
|
|
|
ef1f48 |
int done;
|
|
|
ef1f48 |
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
if ((aclpb->aclpb_access & SLAPI_ACL_ADD) &&
|
|
|
ef1f48 |
(aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) {
|
|
|
ef1f48 |
|
|
|
ef1f48 |
@@ -2497,28 +2477,20 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
|
|
|
ef1f48 |
while (attrFilterArray && attrFilterArray[num_attrs] && attr_matched) {
|
|
|
ef1f48 |
attrFilter = attrFilterArray[num_attrs];
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
- * If this filter applies to an attribute in the entry,
|
|
|
ef1f48 |
- * apply it to the entry.
|
|
|
ef1f48 |
- * Otherwise just ignore it.
|
|
|
ef1f48 |
- *
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
- if (slapi_entry_attr_find(aclpb->aclpb_curr_entry,
|
|
|
ef1f48 |
- attrFilter->attr_str,
|
|
|
ef1f48 |
- &attr_ptr) == 0) {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ * If this filter applies to an attribute in the entry,
|
|
|
ef1f48 |
+ * apply it to the entry.
|
|
|
ef1f48 |
+ * Otherwise just ignore it.
|
|
|
ef1f48 |
+ *
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
+ if (slapi_entry_attr_find(aclpb->aclpb_curr_entry, attrFilter->attr_str, &attr_ptr) == 0) {
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
- * This is an applicable filter.
|
|
|
ef1f48 |
- * The filter is to be appplied to the entry being added
|
|
|
ef1f48 |
- * or deleted.
|
|
|
ef1f48 |
- * The filter needs to be satisfied by _each_ occurence
|
|
|
ef1f48 |
- * of the attribute in the entry--otherwise you
|
|
|
ef1f48 |
- * could satisfy the filter and then put loads of other
|
|
|
ef1f48 |
- * values in on the back of it.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ * This is an applicable filter.
|
|
|
ef1f48 |
+ * The filter is to be applied to the entry being added or deleted.
|
|
|
ef1f48 |
+ * The filter needs to be satisfied by _each_ occurrence of the
|
|
|
ef1f48 |
+ * attribute in the entry--otherwise you could satisfy the filter
|
|
|
ef1f48 |
+ * and then put loads of other values in on the back of it.
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
sval = NULL;
|
|
|
ef1f48 |
attrVal = NULL;
|
|
|
ef1f48 |
k = slapi_attr_first_value(attr_ptr, &sval);
|
|
|
ef1f48 |
@@ -2528,12 +2500,11 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
|
|
|
ef1f48 |
if (acl__make_filter_test_entry(&aclpb->aclpb_filter_test_entry,
|
|
|
ef1f48 |
attrFilter->attr_str,
|
|
|
ef1f48 |
- (struct berval *)attrVal) == LDAP_SUCCESS) {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ (struct berval *)attrVal) == LDAP_SUCCESS)
|
|
|
ef1f48 |
+ {
|
|
|
ef1f48 |
attr_matched = acl__test_filter(aclpb->aclpb_filter_test_entry,
|
|
|
ef1f48 |
attrFilter->filter,
|
|
|
ef1f48 |
- 1 /* Do filter sense evaluation below */
|
|
|
ef1f48 |
- );
|
|
|
ef1f48 |
+ 1 /* Do filter sense evaluation below */);
|
|
|
ef1f48 |
done = !attr_matched;
|
|
|
ef1f48 |
slapi_entry_free(aclpb->aclpb_filter_test_entry);
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
@@ -2542,19 +2513,19 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
} /* while */
|
|
|
ef1f48 |
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
- * Here, we applied an applicable filter to the entry.
|
|
|
ef1f48 |
- * So if attr_matched is ACL_TRUE then every value
|
|
|
ef1f48 |
- * of the attribute in the entry satisfied the filter.
|
|
|
ef1f48 |
- * Otherwise, attr_matched is ACL_FALSE and not every
|
|
|
ef1f48 |
- * value satisfied the filter, so we will teminate the
|
|
|
ef1f48 |
- * scan of the filter list.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ * Here, we applied an applicable filter to the entry.
|
|
|
ef1f48 |
+ * So if attr_matched is ACL_TRUE then every value
|
|
|
ef1f48 |
+ * of the attribute in the entry satisfied the filter.
|
|
|
ef1f48 |
+ * Otherwise, attr_matched is ACL_FALSE and not every
|
|
|
ef1f48 |
+ * value satisfied the filter, so we will terminate the
|
|
|
ef1f48 |
+ * scan of the filter list.
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
num_attrs++;
|
|
|
ef1f48 |
} /* while */
|
|
|
ef1f48 |
|
|
|
ef1f48 |
-/*
|
|
|
ef1f48 |
+ /*
|
|
|
ef1f48 |
* Here, we've applied all the applicable filters to the entry.
|
|
|
ef1f48 |
* Each one must have been satisfied by all the values of the attribute.
|
|
|
ef1f48 |
* The result of this is stored in attr_matched.
|
|
|
ef1f48 |
@@ -2585,7 +2556,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
} else if (((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) &&
|
|
|
ef1f48 |
(aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) ||
|
|
|
ef1f48 |
((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) &&
|
|
|
ef1f48 |
- (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS))) {
|
|
|
ef1f48 |
+ (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)))
|
|
|
ef1f48 |
+ {
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
* Here, it's a modify add/del and we have attr filters.
|
|
|
ef1f48 |
* So, we need to scan the add/del filter list to find the filter
|
|
|
ef1f48 |
@@ -2629,11 +2601,10 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
* Otherwise, ignore the targetattrfilters.
|
|
|
ef1f48 |
*/
|
|
|
ef1f48 |
if (found) {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
if (acl__make_filter_test_entry(&aclpb->aclpb_filter_test_entry,
|
|
|
ef1f48 |
aclpb->aclpb_curr_attrEval->attrEval_name,
|
|
|
ef1f48 |
- aclpb->aclpb_curr_attrVal) == LDAP_SUCCESS) {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ aclpb->aclpb_curr_attrVal) == LDAP_SUCCESS)
|
|
|
ef1f48 |
+ {
|
|
|
ef1f48 |
attr_matched = acl__test_filter(aclpb->aclpb_filter_test_entry,
|
|
|
ef1f48 |
attrFilter->filter,
|
|
|
ef1f48 |
1 /* Do filter sense evaluation below */
|
|
|
ef1f48 |
@@ -2651,20 +2622,21 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
* Here this attribute appeared and was matched in a
|
|
|
ef1f48 |
* targetattrfilters list, so record this fact so we do
|
|
|
ef1f48 |
* not have to scan the targetattr list for the attribute.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
|
|
|
ef1f48 |
attr_matched_in_targetattrfilters = 1;
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
} /* targetvaluefilters */
|
|
|
ef1f48 |
|
|
|
ef1f48 |
|
|
|
ef1f48 |
- /* There are 3 cases by which acis are selected.
|
|
|
ef1f48 |
- ** 1) By scanning the whole list and picking based on the resource.
|
|
|
ef1f48 |
- ** 2) By picking a subset of the list which will be used for the whole
|
|
|
ef1f48 |
- ** acl evaluation.
|
|
|
ef1f48 |
- ** 3) A finer granularity, i.e, a selected list of acls which will be
|
|
|
ef1f48 |
- ** used for only that entry's evaluation.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ /*
|
|
|
ef1f48 |
+ * There are 3 cases by which acis are selected.
|
|
|
ef1f48 |
+ * 1) By scanning the whole list and picking based on the resource.
|
|
|
ef1f48 |
+ * 2) By picking a subset of the list which will be used for the whole
|
|
|
ef1f48 |
+ * acl evaluation.
|
|
|
ef1f48 |
+ * 3) A finer granularity, i.e, a selected list of acls which will be
|
|
|
ef1f48 |
+ * used for only that entry's evaluation.
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (!(skip_attrEval) && (aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_ENTRY_LIST) &&
|
|
|
ef1f48 |
(res_right & SLAPI_ACL_SEARCH) &&
|
|
|
ef1f48 |
((aci->aci_access & SLAPI_ACL_READ) || (aci->aci_access & SLAPI_ACL_SEARCH))) {
|
|
|
ef1f48 |
@@ -2680,7 +2652,6 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
/* If we are suppose to skip attr eval, then let's skip it */
|
|
|
ef1f48 |
if ((aclpb->aclpb_access & SLAPI_ACL_SEARCH) && (!skip_attrEval) &&
|
|
|
ef1f48 |
(aclpb->aclpb_res_type & ACLPB_NEW_ENTRY)) {
|
|
|
ef1f48 |
@@ -2697,9 +2668,10 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
goto acl__resource_match_aci_EXIT;
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
- /* We need to check again because we don't want to select this handle
|
|
|
ef1f48 |
- ** if the right doesn't match for now.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ /*
|
|
|
ef1f48 |
+ * We need to check again because we don't want to select this handle
|
|
|
ef1f48 |
+ * if the right doesn't match for now.
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (!(aci_right & res_right)) {
|
|
|
ef1f48 |
matches = ACL_FALSE;
|
|
|
ef1f48 |
goto acl__resource_match_aci_EXIT;
|
|
|
ef1f48 |
@@ -2718,20 +2690,16 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
* rbyrneXXX if we had a proper permission for modrdn eg SLAPI_ACL_MODRDN
|
|
|
ef1f48 |
* then we would not need this crappy way of telling it was a MODRDN
|
|
|
ef1f48 |
* request ie. SLAPI_ACL_WRITE && !(c_attrEval).
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
c_attrEval = aclpb->aclpb_curr_attrEval;
|
|
|
ef1f48 |
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
* If we've already matched on targattrfilter then do not
|
|
|
ef1f48 |
* bother to look at the attrlist.
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if (!attr_matched_in_targetattrfilters) {
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
/* match target attr */
|
|
|
ef1f48 |
- if ((c_attrEval) &&
|
|
|
ef1f48 |
- (aci->aci_type & ACI_TARGET_ATTR)) {
|
|
|
ef1f48 |
+ if ((c_attrEval) && (aci->aci_type & ACI_TARGET_ATTR)) {
|
|
|
ef1f48 |
/* there is a target ATTR */
|
|
|
ef1f48 |
Targetattr **attrArray = aci->targetAttr;
|
|
|
ef1f48 |
Targetattr *attr = NULL;
|
|
|
ef1f48 |
@@ -2773,46 +2741,43 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
matches = (attr_matched ? ACL_TRUE : ACL_FALSE);
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
-
|
|
|
ef1f48 |
aclpb->aclpb_state &= ~ACLPB_ATTR_STAR_MATCHED;
|
|
|
ef1f48 |
/* figure out how it matched, i.e star matched */
|
|
|
ef1f48 |
- if (matches && star_matched && num_attrs == 1 &&
|
|
|
ef1f48 |
- !(aclpb->aclpb_state & ACLPB_FOUND_ATTR_RULE))
|
|
|
ef1f48 |
+ if (matches && star_matched && num_attrs == 1 && !(aclpb->aclpb_state & ACLPB_FOUND_ATTR_RULE)) {
|
|
|
ef1f48 |
aclpb->aclpb_state |= ACLPB_ATTR_STAR_MATCHED;
|
|
|
ef1f48 |
- else {
|
|
|
ef1f48 |
+ } else {
|
|
|
ef1f48 |
/* we are here means that there is a specific
|
|
|
ef1f48 |
- ** attr in the rule for this resource.
|
|
|
ef1f48 |
- ** We need to avoid this case
|
|
|
ef1f48 |
- ** Rule 1: (targetattr = "uid")
|
|
|
ef1f48 |
- ** Rule 2: (targetattr = "*")
|
|
|
ef1f48 |
- ** we cannot use STAR optimization
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ * attr in the rule for this resource.
|
|
|
ef1f48 |
+ * We need to avoid this case
|
|
|
ef1f48 |
+ * Rule 1: (targetattr = "uid")
|
|
|
ef1f48 |
+ * Rule 2: (targetattr = "*")
|
|
|
ef1f48 |
+ * we cannot use STAR optimization
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
aclpb->aclpb_state |= ACLPB_FOUND_ATTR_RULE;
|
|
|
ef1f48 |
aclpb->aclpb_state &= ~ACLPB_ATTR_STAR_MATCHED;
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
- } else if ((c_attrEval) ||
|
|
|
ef1f48 |
- (aci->aci_type & ACI_TARGET_ATTR)) {
|
|
|
ef1f48 |
+ } else if ((c_attrEval) || (aci->aci_type & ACI_TARGET_ATTR)) {
|
|
|
ef1f48 |
if ((aci_right & ACL_RIGHTS_TARGETATTR_NOT_NEEDED) &&
|
|
|
ef1f48 |
(aclpb->aclpb_access & ACL_RIGHTS_TARGETATTR_NOT_NEEDED)) {
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
- ** Targetattr rule doesn't make any sense
|
|
|
ef1f48 |
- ** in this case. So select this rule
|
|
|
ef1f48 |
- ** default: matches = ACL_TRUE;
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ * Targetattr rule doesn't make any sense
|
|
|
ef1f48 |
+ * in this case. So select this rule
|
|
|
ef1f48 |
+ * default: matches = ACL_TRUE;
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
;
|
|
|
ef1f48 |
- } else if (aci_right & SLAPI_ACL_WRITE &&
|
|
|
ef1f48 |
+ } else if ((aci_right & SLAPI_ACL_WRITE) &&
|
|
|
ef1f48 |
(aci->aci_type & ACI_TARGET_ATTR) &&
|
|
|
ef1f48 |
!(c_attrEval) &&
|
|
|
ef1f48 |
(aci->aci_type & ACI_HAS_ALLOW_RULE)) {
|
|
|
ef1f48 |
/* We need to handle modrdn operation. Modrdn doesn't
|
|
|
ef1f48 |
- ** change any attrs but changes the RDN and so (attr=NULL).
|
|
|
ef1f48 |
- ** Here we found an acl which has a targetattr but
|
|
|
ef1f48 |
- ** the resource doesn't need one. In that case, we should
|
|
|
ef1f48 |
- ** consider this acl.
|
|
|
ef1f48 |
- ** the opposite is true if it is a deny rule, only a deny without
|
|
|
ef1f48 |
- ** any targetattr should deny modrdn
|
|
|
ef1f48 |
- ** default: matches = ACL_TRUE;
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ * change any attrs but changes the RDN and so (attr=NULL).
|
|
|
ef1f48 |
+ * Here we found an acl which has a targetattr but
|
|
|
ef1f48 |
+ * the resource doesn't need one. In that case, we should
|
|
|
ef1f48 |
+ * consider this acl.
|
|
|
ef1f48 |
+ * the opposite is true if it is a deny rule, only a deny without
|
|
|
ef1f48 |
+ * any targetattr should deny modrdn
|
|
|
ef1f48 |
+ * default: matches = ACL_TRUE;
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
;
|
|
|
ef1f48 |
} else {
|
|
|
ef1f48 |
matches = ACL_FALSE;
|
|
|
ef1f48 |
@@ -2821,16 +2786,16 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
|
|
ef1f48 |
} /* !attr_matched_in_targetattrfilters */
|
|
|
ef1f48 |
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
- ** Here we are testing if we find a entry test rule (which should
|
|
|
ef1f48 |
- ** be rare). In that case, just remember it. An entry test rule
|
|
|
ef1f48 |
- ** doesn't have "(targetattr)".
|
|
|
ef1f48 |
- */
|
|
|
ef1f48 |
+ * Here we are testing if we find a entry test rule (which should
|
|
|
ef1f48 |
+ * be rare). In that case, just remember it. An entry test rule
|
|
|
ef1f48 |
+ * doesn't have "(targetattr)".
|
|
|
ef1f48 |
+ */
|
|
|
ef1f48 |
if ((aclpb->aclpb_state & ACLPB_EVALUATING_FIRST_ATTR) &&
|
|
|
ef1f48 |
(!(aci->aci_type & ACI_TARGET_ATTR))) {
|
|
|
ef1f48 |
aclpb->aclpb_state |= ACLPB_FOUND_A_ENTRY_TEST_RULE;
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
-/*
|
|
|
ef1f48 |
+ /*
|
|
|
ef1f48 |
* Generic exit point for this routine:
|
|
|
ef1f48 |
* matches is ACL_TRUE if the aci matches the target of the resource,
|
|
|
ef1f48 |
* ACL_FALSE othrewise.
|
|
|
ef1f48 |
@@ -2853,6 +2818,7 @@ acl__resource_match_aci_EXIT:
|
|
|
ef1f48 |
|
|
|
ef1f48 |
return (matches);
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
+
|
|
|
ef1f48 |
/* Macro to determine if the cached result is valid or not. */
|
|
|
ef1f48 |
#define ACL_CACHED_RESULT_VALID(result) \
|
|
|
ef1f48 |
(((result & ACLPB_CACHE_READ_RES_ALLOW) && \
|
|
|
ef1f48 |
diff --git a/ldap/servers/slapd/back-ldbm/findentry.c b/ldap/servers/slapd/back-ldbm/findentry.c
|
|
|
ef1f48 |
index 6e53a0aea..bff751c88 100644
|
|
|
ef1f48 |
--- a/ldap/servers/slapd/back-ldbm/findentry.c
|
|
|
ef1f48 |
+++ b/ldap/servers/slapd/back-ldbm/findentry.c
|
|
|
ef1f48 |
@@ -93,7 +93,6 @@ find_entry_internal_dn(
|
|
|
ef1f48 |
size_t tries = 0;
|
|
|
ef1f48 |
int isroot = 0;
|
|
|
ef1f48 |
int op_type;
|
|
|
ef1f48 |
- char *errbuf = NULL;
|
|
|
ef1f48 |
|
|
|
ef1f48 |
/* get the managedsait ldap message control */
|
|
|
ef1f48 |
slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
|
|
|
ef1f48 |
@@ -207,8 +206,8 @@ find_entry_internal_dn(
|
|
|
ef1f48 |
break;
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
if (acl_type > 0) {
|
|
|
ef1f48 |
- err = plugin_call_acl_plugin(pb, me->ep_entry, NULL, NULL, acl_type,
|
|
|
ef1f48 |
- ACLPLUGIN_ACCESS_DEFAULT, &errbuf);
|
|
|
ef1f48 |
+ char *dummy_attr = "1.1";
|
|
|
ef1f48 |
+ err = slapi_access_allowed(pb, me->ep_entry, dummy_attr, NULL, acl_type);
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
if (((acl_type > 0) && err) || (op_type == SLAPI_OPERATION_BIND)) {
|
|
|
ef1f48 |
/*
|
|
|
ef1f48 |
@@ -237,7 +236,6 @@ find_entry_internal_dn(
|
|
|
ef1f48 |
CACHE_RETURN(&inst->inst_cache, &me);
|
|
|
ef1f48 |
}
|
|
|
ef1f48 |
|
|
|
ef1f48 |
- slapi_ch_free_string(&errbuf);
|
|
|
ef1f48 |
slapi_log_err(SLAPI_LOG_TRACE, "find_entry_internal_dn", "<= Not found (%s)\n",
|
|
|
ef1f48 |
slapi_sdn_get_dn(sdn));
|
|
|
ef1f48 |
return (NULL);
|
|
|
ef1f48 |
diff --git a/src/lib389/lib389/_mapped_object.py b/src/lib389/lib389/_mapped_object.py
|
|
|
ef1f48 |
index c60837601..ca6ea6ef8 100644
|
|
|
ef1f48 |
--- a/src/lib389/lib389/_mapped_object.py
|
|
|
ef1f48 |
+++ b/src/lib389/lib389/_mapped_object.py
|
|
|
ef1f48 |
@@ -1190,7 +1190,7 @@ class DSLdapObjects(DSLogging, DSLints):
|
|
|
ef1f48 |
# Now actually commit the creation req
|
|
|
ef1f48 |
return co.ensure_state(rdn, properties, self._basedn)
|
|
|
ef1f48 |
|
|
|
ef1f48 |
- def filter(self, search, scope=None):
|
|
|
ef1f48 |
+ def filter(self, search, scope=None, strict=False):
|
|
|
ef1f48 |
# This will yield and & filter for objectClass with as many terms as needed.
|
|
|
ef1f48 |
if search:
|
|
|
ef1f48 |
search_filter = _gen_and([self._get_objectclass_filter(), search])
|
|
|
ef1f48 |
@@ -1211,5 +1211,7 @@ class DSLdapObjects(DSLogging, DSLints):
|
|
|
ef1f48 |
insts = [self._entry_to_instance(dn=r.dn, entry=r) for r in results]
|
|
|
ef1f48 |
except ldap.NO_SUCH_OBJECT:
|
|
|
ef1f48 |
# There are no objects to select from, se we return an empty array
|
|
|
ef1f48 |
+ if strict:
|
|
|
ef1f48 |
+ raise ldap.NO_SUCH_OBJECT
|
|
|
ef1f48 |
insts = []
|
|
|
ef1f48 |
return insts
|
|
|
ef1f48 |
--
|
|
|
ef1f48 |
2.26.2
|
|
|
ef1f48 |
|