import 389-ds-base-1.4.3.8-7.module+el8.3.0+10310+6e88d919
This commit is contained in:
parent
b342bd146c
commit
6b2663c36d
@ -0,0 +1,95 @@
|
|||||||
|
From 340b81a59cee365e7300e57c1ca5f4866373954c Mon Sep 17 00:00:00 2001
|
||||||
|
From: tbordaz <tbordaz@redhat.com>
|
||||||
|
Date: Wed, 16 Dec 2020 16:30:28 +0100
|
||||||
|
Subject: [PATCH 1/4] Issue 4480 - Unexpected info returned to ldap request
|
||||||
|
(#4491)
|
||||||
|
|
||||||
|
Bug description:
|
||||||
|
If the bind entry does not exist, the bind result info
|
||||||
|
reports that 'No such entry'. It should not give any
|
||||||
|
information if the target entry exists or not
|
||||||
|
|
||||||
|
Fix description:
|
||||||
|
Does not return any additional information during a bind
|
||||||
|
|
||||||
|
relates: https://github.com/389ds/389-ds-base/issues/4480
|
||||||
|
|
||||||
|
Reviewed by: William Brown, Viktor Ashirov, Mark Reynolds (thank you all)
|
||||||
|
|
||||||
|
Platforms tested: F31
|
||||||
|
---
|
||||||
|
dirsrvtests/tests/suites/basic/basic_test.py | 30 ++++++++++++++++++++
|
||||||
|
ldap/servers/slapd/back-ldbm/ldbm_config.c | 2 +-
|
||||||
|
ldap/servers/slapd/result.c | 2 +-
|
||||||
|
3 files changed, 32 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/basic/basic_test.py b/dirsrvtests/tests/suites/basic/basic_test.py
|
||||||
|
index 120207321..e9afa1e7e 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/basic/basic_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/basic/basic_test.py
|
||||||
|
@@ -1400,6 +1400,36 @@ def test_dscreate_multiple_dashes_name(dscreate_long_instance):
|
||||||
|
assert not dscreate_long_instance.exists()
|
||||||
|
|
||||||
|
|
||||||
|
+def test_bind_invalid_entry(topology_st):
|
||||||
|
+ """Test the failing bind does not return information about the entry
|
||||||
|
+
|
||||||
|
+ :id: 5cd9b083-eea6-426b-84ca-83c26fc49a6f
|
||||||
|
+
|
||||||
|
+ :setup: Standalone instance
|
||||||
|
+
|
||||||
|
+ :steps:
|
||||||
|
+ 1: bind as non existing entry
|
||||||
|
+ 2: check that bind info does not report 'No such entry'
|
||||||
|
+
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1: pass
|
||||||
|
+ 2: pass
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ topology_st.standalone.restart()
|
||||||
|
+ INVALID_ENTRY="cn=foooo,%s" % DEFAULT_SUFFIX
|
||||||
|
+ try:
|
||||||
|
+ topology_st.standalone.simple_bind_s(INVALID_ENTRY, PASSWORD)
|
||||||
|
+ except ldap.LDAPError as e:
|
||||||
|
+ log.info('test_bind_invalid_entry: Failed to bind as %s (expected)' % INVALID_ENTRY)
|
||||||
|
+ log.info('exception description: ' + e.args[0]['desc'])
|
||||||
|
+ if 'info' in e.args[0]:
|
||||||
|
+ log.info('exception info: ' + e.args[0]['info'])
|
||||||
|
+ assert e.args[0]['desc'] == 'Invalid credentials'
|
||||||
|
+ assert 'info' not in e.args[0]
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ log.info('test_bind_invalid_entry: PASSED')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# Run isolated
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
|
||||||
|
index 88c186359..dee5fc088 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
|
||||||
|
@@ -1266,7 +1266,7 @@ ldbm_config_search_entry_callback(Slapi_PBlock *pb __attribute__((unused)),
|
||||||
|
if (attrs) {
|
||||||
|
for (size_t i = 0; attrs[i]; i++) {
|
||||||
|
if (ldbm_config_moved_attr(attrs[i])) {
|
||||||
|
- slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "at least one required attribute has been moved to the BDB scecific configuration entry");
|
||||||
|
+ slapi_pblock_set(pb, SLAPI_RESULT_TEXT, "at least one required attribute has been moved to the BDB scecific configuration entry");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
|
||||||
|
index 61efb6f8d..40c5dcc57 100644
|
||||||
|
--- a/ldap/servers/slapd/result.c
|
||||||
|
+++ b/ldap/servers/slapd/result.c
|
||||||
|
@@ -355,7 +355,7 @@ send_ldap_result_ext(
|
||||||
|
if (text) {
|
||||||
|
pbtext = text;
|
||||||
|
} else {
|
||||||
|
- slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &pbtext);
|
||||||
|
+ slapi_pblock_get(pb, SLAPI_RESULT_TEXT, &pbtext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation == NULL) {
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,782 @@
|
|||||||
|
From 2923940ffa0db88df986dd00d74ad812ccd71188 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mark Reynolds <mreynolds@redhat.com>
|
||||||
|
Date: Wed, 20 Jan 2021 16:42:15 -0500
|
||||||
|
Subject: [PATCH 2/4] Issue 5442 - Search results are different between RHDS10
|
||||||
|
and RHDS11
|
||||||
|
|
||||||
|
Bug Description: In 1.4.x we introduced a change that was overly strict about
|
||||||
|
how a search on a non-existent subtree returned its error code.
|
||||||
|
It was changed from returning an error 32 to an error 0 with
|
||||||
|
zero entries returned.
|
||||||
|
|
||||||
|
Fix Description: When finding the entry and processing acl's make sure to
|
||||||
|
gather the aci's that match the resource even if the resource
|
||||||
|
does not exist. This requires some extra checks when processing
|
||||||
|
the target attribute.
|
||||||
|
|
||||||
|
relates: https://github.com/389ds/389-ds-base/issues/4542
|
||||||
|
|
||||||
|
Reviewed by: firstyear, elkris, and tbordaz (Thanks!)
|
||||||
|
|
||||||
|
Apply Thierry's changes
|
||||||
|
|
||||||
|
round 2
|
||||||
|
|
||||||
|
Apply more suggestions from Thierry
|
||||||
|
---
|
||||||
|
dirsrvtests/tests/suites/acl/misc_test.py | 108 +++++++-
|
||||||
|
ldap/servers/plugins/acl/acl.c | 296 ++++++++++------------
|
||||||
|
ldap/servers/slapd/back-ldbm/findentry.c | 6 +-
|
||||||
|
src/lib389/lib389/_mapped_object.py | 4 +-
|
||||||
|
4 files changed, 239 insertions(+), 175 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/acl/misc_test.py b/dirsrvtests/tests/suites/acl/misc_test.py
|
||||||
|
index 8f122b7a7..b64961c0c 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/acl/misc_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/acl/misc_test.py
|
||||||
|
@@ -11,7 +11,7 @@
|
||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
-from lib389._constants import DEFAULT_SUFFIX, PW_DM
|
||||||
|
+from lib389._constants import DEFAULT_SUFFIX, PW_DM, DN_DM
|
||||||
|
from lib389.idm.user import UserAccount, UserAccounts
|
||||||
|
from lib389._mapped_object import DSLdapObject
|
||||||
|
from lib389.idm.account import Accounts, Anonymous
|
||||||
|
@@ -399,14 +399,112 @@ def test_do_bind_as_201_distinct_users(topo, clean, aci_of_user):
|
||||||
|
user = uas.create_test_user(uid=i, gid=i)
|
||||||
|
user.set('userPassword', PW_DM)
|
||||||
|
|
||||||
|
- for i in range(len(uas.list())):
|
||||||
|
- uas.list()[i].bind(PW_DM)
|
||||||
|
+ users = uas.list()
|
||||||
|
+ for user in users:
|
||||||
|
+ user.bind(PW_DM)
|
||||||
|
|
||||||
|
ACLPlugin(topo.standalone).replace("nsslapd-aclpb-max-selected-acls", '220')
|
||||||
|
topo.standalone.restart()
|
||||||
|
|
||||||
|
- for i in range(len(uas.list())):
|
||||||
|
- uas.list()[i].bind(PW_DM)
|
||||||
|
+ users = uas.list()
|
||||||
|
+ for user in users:
|
||||||
|
+ user.bind(PW_DM)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def test_info_disclosure(request, topo):
|
||||||
|
+ """Test that a search returns 32 when base entry does not exist
|
||||||
|
+
|
||||||
|
+ :id: f6dec4c2-65a3-41e4-a4c0-146196863333
|
||||||
|
+ :setup: Standalone Instance
|
||||||
|
+ :steps:
|
||||||
|
+ 1. Add aci
|
||||||
|
+ 2. Add test user
|
||||||
|
+ 3. Bind as user and search for non-existent entry
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1. Success
|
||||||
|
+ 2. Success
|
||||||
|
+ 3. Error 32 is returned
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ ACI_TARGET = "(targetattr = \"*\")(target = \"ldap:///%s\")" % (DEFAULT_SUFFIX)
|
||||||
|
+ ACI_ALLOW = "(version 3.0; acl \"Read/Search permission for all users\"; allow (read,search)"
|
||||||
|
+ ACI_SUBJECT = "(userdn=\"ldap:///all\");)"
|
||||||
|
+ ACI = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT
|
||||||
|
+
|
||||||
|
+ # Get current ACi's so we can restore them when we are done
|
||||||
|
+ suffix = Domain(topo.standalone, DEFAULT_SUFFIX)
|
||||||
|
+ preserved_acis = suffix.get_attr_vals_utf8('aci')
|
||||||
|
+
|
||||||
|
+ def finofaci():
|
||||||
|
+ domain = Domain(topo.standalone, DEFAULT_SUFFIX)
|
||||||
|
+ try:
|
||||||
|
+ domain.remove_all('aci')
|
||||||
|
+ domain.replace_values('aci', preserved_acis)
|
||||||
|
+ except:
|
||||||
|
+ pass
|
||||||
|
+ request.addfinalizer(finofaci)
|
||||||
|
+
|
||||||
|
+ # Remove aci's
|
||||||
|
+ suffix.remove_all('aci')
|
||||||
|
+
|
||||||
|
+ # Add test user
|
||||||
|
+ USER_DN = "uid=test,ou=people," + DEFAULT_SUFFIX
|
||||||
|
+ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
|
||||||
|
+ users.create(properties={
|
||||||
|
+ 'uid': 'test',
|
||||||
|
+ 'cn': 'test',
|
||||||
|
+ 'sn': 'test',
|
||||||
|
+ 'uidNumber': '1000',
|
||||||
|
+ 'gidNumber': '2000',
|
||||||
|
+ 'homeDirectory': '/home/test',
|
||||||
|
+ 'userPassword': PW_DM
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
+ # bind as user
|
||||||
|
+ conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
|
||||||
|
+
|
||||||
|
+ # Search fo existing base DN
|
||||||
|
+ test = Domain(conn, DEFAULT_SUFFIX)
|
||||||
|
+ try:
|
||||||
|
+ test.get_attr_vals_utf8_l('dc')
|
||||||
|
+ assert False
|
||||||
|
+ except IndexError:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ # Search for a non existent bases
|
||||||
|
+ subtree = Domain(conn, "ou=does_not_exist," + DEFAULT_SUFFIX)
|
||||||
|
+ try:
|
||||||
|
+ subtree.get_attr_vals_utf8_l('objectclass')
|
||||||
|
+ except IndexError:
|
||||||
|
+ pass
|
||||||
|
+ subtree = Domain(conn, "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX)
|
||||||
|
+ try:
|
||||||
|
+ subtree.get_attr_vals_utf8_l('objectclass')
|
||||||
|
+ except IndexError:
|
||||||
|
+ pass
|
||||||
|
+ # Try ONE level search instead of BASE
|
||||||
|
+ try:
|
||||||
|
+ Accounts(conn, "ou=does_not_exist," + DEFAULT_SUFFIX).filter("(objectclass=top)", ldap.SCOPE_ONELEVEL)
|
||||||
|
+ except IndexError:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ # add aci
|
||||||
|
+ suffix.add('aci', ACI)
|
||||||
|
+
|
||||||
|
+ # Search for a non existent entry which should raise an exception
|
||||||
|
+ with pytest.raises(ldap.NO_SUCH_OBJECT):
|
||||||
|
+ conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
|
||||||
|
+ subtree = Domain(conn, "ou=does_not_exist," + DEFAULT_SUFFIX)
|
||||||
|
+ subtree.get_attr_vals_utf8_l('objectclass')
|
||||||
|
+ with pytest.raises(ldap.NO_SUCH_OBJECT):
|
||||||
|
+ conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
|
||||||
|
+ subtree = Domain(conn, "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX)
|
||||||
|
+ subtree.get_attr_vals_utf8_l('objectclass')
|
||||||
|
+ with pytest.raises(ldap.NO_SUCH_OBJECT):
|
||||||
|
+ conn = UserAccount(topo.standalone, USER_DN).bind(PW_DM)
|
||||||
|
+ DN = "ou=also does not exist,ou=does_not_exist," + DEFAULT_SUFFIX
|
||||||
|
+ Accounts(conn, DN).filter("(objectclass=top)", ldap.SCOPE_ONELEVEL, strict=True)
|
||||||
|
+
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
|
||||||
|
index 41a909a18..4e811f73a 100644
|
||||||
|
--- a/ldap/servers/plugins/acl/acl.c
|
||||||
|
+++ b/ldap/servers/plugins/acl/acl.c
|
||||||
|
@@ -2111,10 +2111,11 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
aci_right = aci->aci_access;
|
||||||
|
res_right = aclpb->aclpb_access;
|
||||||
|
if (!(aci_right & res_right)) {
|
||||||
|
- /* If we are looking for read/search and the acl has read/search
|
||||||
|
- ** then go further because if targets match we may keep that
|
||||||
|
- ** acl in the entry cache list.
|
||||||
|
- */
|
||||||
|
+ /*
|
||||||
|
+ * If we are looking for read/search and the acl has read/search
|
||||||
|
+ * then go further because if targets match we may keep that
|
||||||
|
+ * acl in the entry cache list.
|
||||||
|
+ */
|
||||||
|
if (!((res_right & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) &&
|
||||||
|
(aci_right & (SLAPI_ACL_SEARCH | SLAPI_ACL_READ)))) {
|
||||||
|
matches = ACL_FALSE;
|
||||||
|
@@ -2122,30 +2123,29 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
- /* first Let's see if the entry is under the subtree where the
|
||||||
|
- ** ACL resides. We can't let somebody affect a target beyond the
|
||||||
|
- ** scope of where the ACL resides
|
||||||
|
- ** Example: ACL is located in "ou=engineering, o=ace industry, c=us
|
||||||
|
- ** but if the target is "o=ace industry, c=us", then we are in trouble.
|
||||||
|
- **
|
||||||
|
- ** If the aci is in the rootdse and the entry is not, then we do not
|
||||||
|
- ** match--ie. acis in the rootdse do NOT apply below...for the moment.
|
||||||
|
- **
|
||||||
|
- */
|
||||||
|
+ /*
|
||||||
|
+ * First Let's see if the entry is under the subtree where the
|
||||||
|
+ * ACL resides. We can't let somebody affect a target beyond the
|
||||||
|
+ * scope of where the ACL resides
|
||||||
|
+ * Example: ACL is located in "ou=engineering, o=ace industry, c=us
|
||||||
|
+ * but if the target is "o=ace industry, c=us", then we are in trouble.
|
||||||
|
+ *
|
||||||
|
+ * If the aci is in the rootdse and the entry is not, then we do not
|
||||||
|
+ * match--ie. acis in the rootdse do NOT apply below...for the moment.
|
||||||
|
+ */
|
||||||
|
res_ndn = slapi_sdn_get_ndn(aclpb->aclpb_curr_entry_sdn);
|
||||||
|
aci_ndn = slapi_sdn_get_ndn(aci->aci_sdn);
|
||||||
|
- if (!slapi_sdn_issuffix(aclpb->aclpb_curr_entry_sdn, aci->aci_sdn) || (!slapi_is_rootdse(res_ndn) && slapi_is_rootdse(aci_ndn))) {
|
||||||
|
-
|
||||||
|
- /* cant' poke around */
|
||||||
|
+ if (!slapi_sdn_issuffix(aclpb->aclpb_curr_entry_sdn, aci->aci_sdn) ||
|
||||||
|
+ (!slapi_is_rootdse(res_ndn) && slapi_is_rootdse(aci_ndn)))
|
||||||
|
+ {
|
||||||
|
+ /* can't poke around */
|
||||||
|
matches = ACL_FALSE;
|
||||||
|
goto acl__resource_match_aci_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
- ** We have a single ACI which we need to find if it applies to
|
||||||
|
- ** the resource or not.
|
||||||
|
- */
|
||||||
|
+ * We have a single ACI which we need to find if it applies to the resource or not.
|
||||||
|
+ */
|
||||||
|
if ((aci->aci_type & ACI_TARGET_DN) && (aclpb->aclpb_curr_entry_sdn)) {
|
||||||
|
char *avaType;
|
||||||
|
struct berval *avaValue;
|
||||||
|
@@ -2173,25 +2173,23 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
char *avaType;
|
||||||
|
struct berval *avaValue;
|
||||||
|
char logbuf[1024];
|
||||||
|
-
|
||||||
|
- /* We are evaluating the moddn permission.
|
||||||
|
- * The aci contains target_to and target_from
|
||||||
|
- *
|
||||||
|
- * target_to filter must be checked against the resource ndn that was stored in
|
||||||
|
- * aclpb->aclpb_curr_entry_sdn
|
||||||
|
- *
|
||||||
|
- * target_from filter must be check against the entry ndn that is in aclpb->aclpb_moddn_source_sdn
|
||||||
|
- * (sdn was stored in the pblock)
|
||||||
|
- */
|
||||||
|
+ /*
|
||||||
|
+ * We are evaluating the moddn permission.
|
||||||
|
+ * The aci contains target_to and target_from
|
||||||
|
+ *
|
||||||
|
+ * target_to filter must be checked against the resource ndn that was stored in
|
||||||
|
+ * aclpb->aclpb_curr_entry_sdn
|
||||||
|
+ *
|
||||||
|
+ * target_from filter must be check against the entry ndn that is in aclpb->aclpb_moddn_source_sdn
|
||||||
|
+ * (sdn was stored in the pblock)
|
||||||
|
+ */
|
||||||
|
if (aci->target_to) {
|
||||||
|
f = aci->target_to;
|
||||||
|
dn_matched = ACL_TRUE;
|
||||||
|
|
||||||
|
/* Now check if the filter is a simple or substring filter */
|
||||||
|
if (aci->aci_type & ACI_TARGET_MODDN_TO_PATTERN) {
|
||||||
|
- /* This is a filter with substring
|
||||||
|
- * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
|
||||||
|
- */
|
||||||
|
+ /* This is a filter with substring e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com */
|
||||||
|
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_to substring: %s\n",
|
||||||
|
slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
|
||||||
|
if ((rv = acl_match_substring(f, (char *)res_ndn, 0 /* match suffix */)) != ACL_TRUE) {
|
||||||
|
@@ -2204,9 +2202,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
- /* This is a filter without substring
|
||||||
|
- * e.g. ldap:///cn=accounts,dc=example,dc=com
|
||||||
|
- */
|
||||||
|
+ /* This is a filter without substring e.g. ldap:///cn=accounts,dc=example,dc=com */
|
||||||
|
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_to: %s\n",
|
||||||
|
slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
|
||||||
|
slapi_filter_get_ava(f, &avaType, &avaValue);
|
||||||
|
@@ -2230,8 +2226,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
/* Now check if the filter is a simple or substring filter */
|
||||||
|
if (aci->aci_type & ACI_TARGET_MODDN_FROM_PATTERN) {
|
||||||
|
/* This is a filter with substring
|
||||||
|
- * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
|
||||||
|
- */
|
||||||
|
+ * e.g. ldap:///uid=*,cn=accounts,dc=example,dc=com
|
||||||
|
+ */
|
||||||
|
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_from substring: %s\n",
|
||||||
|
slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
|
||||||
|
if ((rv = acl_match_substring(f, (char *)slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn), 0 /* match suffix */)) != ACL_TRUE) {
|
||||||
|
@@ -2243,11 +2239,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
goto acl__resource_match_aci_EXIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-
|
||||||
|
} else {
|
||||||
|
- /* This is a filter without substring
|
||||||
|
- * e.g. ldap:///cn=accounts,dc=example,dc=com
|
||||||
|
- */
|
||||||
|
+ /* This is a filter without substring e.g. ldap:///cn=accounts,dc=example,dc=com */
|
||||||
|
slapi_log_err(SLAPI_LOG_ACL, plugin_name, "acl__resource_match_aci - moddn target_from: %s\n",
|
||||||
|
slapi_filter_to_string(f, logbuf, sizeof(logbuf)));
|
||||||
|
if (!slapi_dn_issuffix(slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn), avaValue->bv_val)) {
|
||||||
|
@@ -2269,10 +2262,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aci->aci_type & ACI_TARGET_PATTERN) {
|
||||||
|
-
|
||||||
|
f = aci->target;
|
||||||
|
dn_matched = ACL_TRUE;
|
||||||
|
-
|
||||||
|
if ((rv = acl_match_substring(f, (char *)res_ndn, 0 /* match suffux */)) != ACL_TRUE) {
|
||||||
|
dn_matched = ACL_FALSE;
|
||||||
|
if (rv == ACL_ERR) {
|
||||||
|
@@ -2296,7 +2287,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is it a (target="ldap://cn=*,($dn),o=sun.com") kind of thing.
|
||||||
|
- */
|
||||||
|
+ */
|
||||||
|
if (aci->aci_type & ACI_TARGET_MACRO_DN) {
|
||||||
|
/*
|
||||||
|
* See if the ($dn) component matches the string and
|
||||||
|
@@ -2306,8 +2297,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
* entry is the same one don't recalculate it--
|
||||||
|
* this flag only works for search right now, could
|
||||||
|
* also optimise for mods by making it work for mods.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
+ */
|
||||||
|
if ((aclpb->aclpb_res_type & ACLPB_NEW_ENTRY) == 0) {
|
||||||
|
/*
|
||||||
|
* Here same entry so just look up the matched value,
|
||||||
|
@@ -2356,8 +2346,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
* If there is already an entry for this aci in this
|
||||||
|
* aclpb then remove it--it's an old value for a
|
||||||
|
* different entry.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
+ */
|
||||||
|
acl_ht_add_and_freeOld(aclpb->aclpb_macro_ht,
|
||||||
|
(PLHashNumber)aci->aci_index,
|
||||||
|
matched_val);
|
||||||
|
@@ -2381,30 +2370,27 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
- ** Here, if there's a targetfilter field, see if it matches.
|
||||||
|
- **
|
||||||
|
- ** The commented out code below was an erroneous attempt to skip
|
||||||
|
- ** this test. It is wrong because: 1. you need to store
|
||||||
|
- ** whether the last test matched or not (you cannot just assume it did)
|
||||||
|
- ** and 2. It may not be the same aci, so the previous matched
|
||||||
|
- ** value is a function of the aci.
|
||||||
|
- ** May be interesting to build such a cache...but no evidence for
|
||||||
|
- ** for that right now. See Bug 383424.
|
||||||
|
- **
|
||||||
|
- **
|
||||||
|
- ** && ((aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST) ||
|
||||||
|
- ** (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY))
|
||||||
|
- */
|
||||||
|
+ * Here, if there's a targetfilter field, see if it matches.
|
||||||
|
+ *
|
||||||
|
+ * The commented out code below was an erroneous attempt to skip
|
||||||
|
+ * this test. It is wrong because: 1. you need to store
|
||||||
|
+ * whether the last test matched or not (you cannot just assume it did)
|
||||||
|
+ * and 2. It may not be the same aci, so the previous matched
|
||||||
|
+ * value is a function of the aci.
|
||||||
|
+ * May be interesting to build such a cache...but no evidence for
|
||||||
|
+ * for that right now. See Bug 383424.
|
||||||
|
+ *
|
||||||
|
+ *
|
||||||
|
+ * && ((aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_LIST) ||
|
||||||
|
+ * (aclpb->aclpb_res_type & ACLPB_NEW_ENTRY))
|
||||||
|
+ */
|
||||||
|
if (aci->aci_type & ACI_TARGET_FILTER) {
|
||||||
|
int filter_matched = ACL_TRUE;
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* Check for macros.
|
||||||
|
* For targetfilter we need to fake the lasinfo structure--it's
|
||||||
|
* created "naturally" for subjects but not targets.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
-
|
||||||
|
+ */
|
||||||
|
if (aci->aci_type & ACI_TARGET_FILTER_MACRO_DN) {
|
||||||
|
|
||||||
|
lasInfo *lasinfo = NULL;
|
||||||
|
@@ -2419,11 +2405,9 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
ACL_EVAL_TARGET_FILTER);
|
||||||
|
slapi_ch_free((void **)&lasinfo);
|
||||||
|
} else {
|
||||||
|
-
|
||||||
|
-
|
||||||
|
if (slapi_vattr_filter_test(NULL, aclpb->aclpb_curr_entry,
|
||||||
|
aci->targetFilter,
|
||||||
|
- 0 /*don't do acess chk*/) != 0) {
|
||||||
|
+ 0 /*don't do access check*/) != 0) {
|
||||||
|
filter_matched = ACL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2450,7 +2434,7 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
* Check to see if we need to evaluate any targetattrfilters.
|
||||||
|
* They look as follows:
|
||||||
|
* (targetattrfilters="add=sn:(sn=rob) && gn:(gn!=byrne),
|
||||||
|
- * del=sn:(sn=rob) && gn:(gn=byrne)")
|
||||||
|
+ * del=sn:(sn=rob) && gn:(gn=byrne)")
|
||||||
|
*
|
||||||
|
* For ADD/DELETE:
|
||||||
|
* If theres's a targetattrfilter then each add/del filter
|
||||||
|
@@ -2458,29 +2442,25 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
* by each value of the attribute in the entry.
|
||||||
|
*
|
||||||
|
* For MODIFY:
|
||||||
|
- * If there's a targetattrfilter then the add/del filter
|
||||||
|
+ * If there's a targetattrfilter then the add/del filter
|
||||||
|
* must be satisfied by the attribute to be added/deleted.
|
||||||
|
* (MODIFY acl is evaluated one value at a time).
|
||||||
|
*
|
||||||
|
*
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
+ */
|
||||||
|
if (((aclpb->aclpb_access & SLAPI_ACL_ADD) &&
|
||||||
|
(aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) ||
|
||||||
|
((aclpb->aclpb_access & SLAPI_ACL_DELETE) &&
|
||||||
|
- (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS))) {
|
||||||
|
-
|
||||||
|
+ (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)))
|
||||||
|
+ {
|
||||||
|
Targetattrfilter **attrFilterArray = NULL;
|
||||||
|
-
|
||||||
|
Targetattrfilter *attrFilter = NULL;
|
||||||
|
-
|
||||||
|
Slapi_Attr *attr_ptr = NULL;
|
||||||
|
Slapi_Value *sval;
|
||||||
|
const struct berval *attrVal;
|
||||||
|
int k;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
-
|
||||||
|
if ((aclpb->aclpb_access & SLAPI_ACL_ADD) &&
|
||||||
|
(aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) {
|
||||||
|
|
||||||
|
@@ -2497,28 +2477,20 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
|
||||||
|
while (attrFilterArray && attrFilterArray[num_attrs] && attr_matched) {
|
||||||
|
attrFilter = attrFilterArray[num_attrs];
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
- * If this filter applies to an attribute in the entry,
|
||||||
|
- * apply it to the entry.
|
||||||
|
- * Otherwise just ignore it.
|
||||||
|
- *
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
- if (slapi_entry_attr_find(aclpb->aclpb_curr_entry,
|
||||||
|
- attrFilter->attr_str,
|
||||||
|
- &attr_ptr) == 0) {
|
||||||
|
-
|
||||||
|
+ * If this filter applies to an attribute in the entry,
|
||||||
|
+ * apply it to the entry.
|
||||||
|
+ * Otherwise just ignore it.
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+ if (slapi_entry_attr_find(aclpb->aclpb_curr_entry, attrFilter->attr_str, &attr_ptr) == 0) {
|
||||||
|
/*
|
||||||
|
- * This is an applicable filter.
|
||||||
|
- * The filter is to be appplied to the entry being added
|
||||||
|
- * or deleted.
|
||||||
|
- * The filter needs to be satisfied by _each_ occurence
|
||||||
|
- * of the attribute in the entry--otherwise you
|
||||||
|
- * could satisfy the filter and then put loads of other
|
||||||
|
- * values in on the back of it.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
+ * This is an applicable filter.
|
||||||
|
+ * The filter is to be applied to the entry being added or deleted.
|
||||||
|
+ * The filter needs to be satisfied by _each_ occurrence of the
|
||||||
|
+ * attribute in the entry--otherwise you could satisfy the filter
|
||||||
|
+ * and then put loads of other values in on the back of it.
|
||||||
|
+ */
|
||||||
|
sval = NULL;
|
||||||
|
attrVal = NULL;
|
||||||
|
k = slapi_attr_first_value(attr_ptr, &sval);
|
||||||
|
@@ -2528,12 +2500,11 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
|
||||||
|
if (acl__make_filter_test_entry(&aclpb->aclpb_filter_test_entry,
|
||||||
|
attrFilter->attr_str,
|
||||||
|
- (struct berval *)attrVal) == LDAP_SUCCESS) {
|
||||||
|
-
|
||||||
|
+ (struct berval *)attrVal) == LDAP_SUCCESS)
|
||||||
|
+ {
|
||||||
|
attr_matched = acl__test_filter(aclpb->aclpb_filter_test_entry,
|
||||||
|
attrFilter->filter,
|
||||||
|
- 1 /* Do filter sense evaluation below */
|
||||||
|
- );
|
||||||
|
+ 1 /* Do filter sense evaluation below */);
|
||||||
|
done = !attr_matched;
|
||||||
|
slapi_entry_free(aclpb->aclpb_filter_test_entry);
|
||||||
|
}
|
||||||
|
@@ -2542,19 +2513,19 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
} /* while */
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Here, we applied an applicable filter to the entry.
|
||||||
|
- * So if attr_matched is ACL_TRUE then every value
|
||||||
|
- * of the attribute in the entry satisfied the filter.
|
||||||
|
- * Otherwise, attr_matched is ACL_FALSE and not every
|
||||||
|
- * value satisfied the filter, so we will teminate the
|
||||||
|
- * scan of the filter list.
|
||||||
|
- */
|
||||||
|
+ * Here, we applied an applicable filter to the entry.
|
||||||
|
+ * So if attr_matched is ACL_TRUE then every value
|
||||||
|
+ * of the attribute in the entry satisfied the filter.
|
||||||
|
+ * Otherwise, attr_matched is ACL_FALSE and not every
|
||||||
|
+ * value satisfied the filter, so we will terminate the
|
||||||
|
+ * scan of the filter list.
|
||||||
|
+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
num_attrs++;
|
||||||
|
} /* while */
|
||||||
|
|
||||||
|
-/*
|
||||||
|
+ /*
|
||||||
|
* Here, we've applied all the applicable filters to the entry.
|
||||||
|
* Each one must have been satisfied by all the values of the attribute.
|
||||||
|
* The result of this is stored in attr_matched.
|
||||||
|
@@ -2585,7 +2556,8 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
} else if (((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) &&
|
||||||
|
(aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) ||
|
||||||
|
((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) &&
|
||||||
|
- (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS))) {
|
||||||
|
+ (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)))
|
||||||
|
+ {
|
||||||
|
/*
|
||||||
|
* Here, it's a modify add/del and we have attr filters.
|
||||||
|
* So, we need to scan the add/del filter list to find the filter
|
||||||
|
@@ -2629,11 +2601,10 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
* Otherwise, ignore the targetattrfilters.
|
||||||
|
*/
|
||||||
|
if (found) {
|
||||||
|
-
|
||||||
|
if (acl__make_filter_test_entry(&aclpb->aclpb_filter_test_entry,
|
||||||
|
aclpb->aclpb_curr_attrEval->attrEval_name,
|
||||||
|
- aclpb->aclpb_curr_attrVal) == LDAP_SUCCESS) {
|
||||||
|
-
|
||||||
|
+ aclpb->aclpb_curr_attrVal) == LDAP_SUCCESS)
|
||||||
|
+ {
|
||||||
|
attr_matched = acl__test_filter(aclpb->aclpb_filter_test_entry,
|
||||||
|
attrFilter->filter,
|
||||||
|
1 /* Do filter sense evaluation below */
|
||||||
|
@@ -2651,20 +2622,21 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
* Here this attribute appeared and was matched in a
|
||||||
|
* targetattrfilters list, so record this fact so we do
|
||||||
|
* not have to scan the targetattr list for the attribute.
|
||||||
|
- */
|
||||||
|
+ */
|
||||||
|
|
||||||
|
attr_matched_in_targetattrfilters = 1;
|
||||||
|
}
|
||||||
|
} /* targetvaluefilters */
|
||||||
|
|
||||||
|
|
||||||
|
- /* There are 3 cases by which acis are selected.
|
||||||
|
- ** 1) By scanning the whole list and picking based on the resource.
|
||||||
|
- ** 2) By picking a subset of the list which will be used for the whole
|
||||||
|
- ** acl evaluation.
|
||||||
|
- ** 3) A finer granularity, i.e, a selected list of acls which will be
|
||||||
|
- ** used for only that entry's evaluation.
|
||||||
|
- */
|
||||||
|
+ /*
|
||||||
|
+ * There are 3 cases by which acis are selected.
|
||||||
|
+ * 1) By scanning the whole list and picking based on the resource.
|
||||||
|
+ * 2) By picking a subset of the list which will be used for the whole
|
||||||
|
+ * acl evaluation.
|
||||||
|
+ * 3) A finer granularity, i.e, a selected list of acls which will be
|
||||||
|
+ * used for only that entry's evaluation.
|
||||||
|
+ */
|
||||||
|
if (!(skip_attrEval) && (aclpb->aclpb_state & ACLPB_SEARCH_BASED_ON_ENTRY_LIST) &&
|
||||||
|
(res_right & SLAPI_ACL_SEARCH) &&
|
||||||
|
((aci->aci_access & SLAPI_ACL_READ) || (aci->aci_access & SLAPI_ACL_SEARCH))) {
|
||||||
|
@@ -2680,7 +2652,6 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
/* If we are suppose to skip attr eval, then let's skip it */
|
||||||
|
if ((aclpb->aclpb_access & SLAPI_ACL_SEARCH) && (!skip_attrEval) &&
|
||||||
|
(aclpb->aclpb_res_type & ACLPB_NEW_ENTRY)) {
|
||||||
|
@@ -2697,9 +2668,10 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
goto acl__resource_match_aci_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* We need to check again because we don't want to select this handle
|
||||||
|
- ** if the right doesn't match for now.
|
||||||
|
- */
|
||||||
|
+ /*
|
||||||
|
+ * We need to check again because we don't want to select this handle
|
||||||
|
+ * if the right doesn't match for now.
|
||||||
|
+ */
|
||||||
|
if (!(aci_right & res_right)) {
|
||||||
|
matches = ACL_FALSE;
|
||||||
|
goto acl__resource_match_aci_EXIT;
|
||||||
|
@@ -2718,20 +2690,16 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
* rbyrneXXX if we had a proper permission for modrdn eg SLAPI_ACL_MODRDN
|
||||||
|
* then we would not need this crappy way of telling it was a MODRDN
|
||||||
|
* request ie. SLAPI_ACL_WRITE && !(c_attrEval).
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
+ */
|
||||||
|
c_attrEval = aclpb->aclpb_curr_attrEval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we've already matched on targattrfilter then do not
|
||||||
|
* bother to look at the attrlist.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
+ */
|
||||||
|
if (!attr_matched_in_targetattrfilters) {
|
||||||
|
-
|
||||||
|
/* match target attr */
|
||||||
|
- if ((c_attrEval) &&
|
||||||
|
- (aci->aci_type & ACI_TARGET_ATTR)) {
|
||||||
|
+ if ((c_attrEval) && (aci->aci_type & ACI_TARGET_ATTR)) {
|
||||||
|
/* there is a target ATTR */
|
||||||
|
Targetattr **attrArray = aci->targetAttr;
|
||||||
|
Targetattr *attr = NULL;
|
||||||
|
@@ -2773,46 +2741,43 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
matches = (attr_matched ? ACL_TRUE : ACL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
aclpb->aclpb_state &= ~ACLPB_ATTR_STAR_MATCHED;
|
||||||
|
/* figure out how it matched, i.e star matched */
|
||||||
|
- if (matches && star_matched && num_attrs == 1 &&
|
||||||
|
- !(aclpb->aclpb_state & ACLPB_FOUND_ATTR_RULE))
|
||||||
|
+ if (matches && star_matched && num_attrs == 1 && !(aclpb->aclpb_state & ACLPB_FOUND_ATTR_RULE)) {
|
||||||
|
aclpb->aclpb_state |= ACLPB_ATTR_STAR_MATCHED;
|
||||||
|
- else {
|
||||||
|
+ } else {
|
||||||
|
/* we are here means that there is a specific
|
||||||
|
- ** attr in the rule for this resource.
|
||||||
|
- ** We need to avoid this case
|
||||||
|
- ** Rule 1: (targetattr = "uid")
|
||||||
|
- ** Rule 2: (targetattr = "*")
|
||||||
|
- ** we cannot use STAR optimization
|
||||||
|
- */
|
||||||
|
+ * attr in the rule for this resource.
|
||||||
|
+ * We need to avoid this case
|
||||||
|
+ * Rule 1: (targetattr = "uid")
|
||||||
|
+ * Rule 2: (targetattr = "*")
|
||||||
|
+ * we cannot use STAR optimization
|
||||||
|
+ */
|
||||||
|
aclpb->aclpb_state |= ACLPB_FOUND_ATTR_RULE;
|
||||||
|
aclpb->aclpb_state &= ~ACLPB_ATTR_STAR_MATCHED;
|
||||||
|
}
|
||||||
|
- } else if ((c_attrEval) ||
|
||||||
|
- (aci->aci_type & ACI_TARGET_ATTR)) {
|
||||||
|
+ } else if ((c_attrEval) || (aci->aci_type & ACI_TARGET_ATTR)) {
|
||||||
|
if ((aci_right & ACL_RIGHTS_TARGETATTR_NOT_NEEDED) &&
|
||||||
|
(aclpb->aclpb_access & ACL_RIGHTS_TARGETATTR_NOT_NEEDED)) {
|
||||||
|
/*
|
||||||
|
- ** Targetattr rule doesn't make any sense
|
||||||
|
- ** in this case. So select this rule
|
||||||
|
- ** default: matches = ACL_TRUE;
|
||||||
|
- */
|
||||||
|
+ * Targetattr rule doesn't make any sense
|
||||||
|
+ * in this case. So select this rule
|
||||||
|
+ * default: matches = ACL_TRUE;
|
||||||
|
+ */
|
||||||
|
;
|
||||||
|
- } else if (aci_right & SLAPI_ACL_WRITE &&
|
||||||
|
+ } else if ((aci_right & SLAPI_ACL_WRITE) &&
|
||||||
|
(aci->aci_type & ACI_TARGET_ATTR) &&
|
||||||
|
!(c_attrEval) &&
|
||||||
|
(aci->aci_type & ACI_HAS_ALLOW_RULE)) {
|
||||||
|
/* We need to handle modrdn operation. Modrdn doesn't
|
||||||
|
- ** change any attrs but changes the RDN and so (attr=NULL).
|
||||||
|
- ** Here we found an acl which has a targetattr but
|
||||||
|
- ** the resource doesn't need one. In that case, we should
|
||||||
|
- ** consider this acl.
|
||||||
|
- ** the opposite is true if it is a deny rule, only a deny without
|
||||||
|
- ** any targetattr should deny modrdn
|
||||||
|
- ** default: matches = ACL_TRUE;
|
||||||
|
- */
|
||||||
|
+ * change any attrs but changes the RDN and so (attr=NULL).
|
||||||
|
+ * Here we found an acl which has a targetattr but
|
||||||
|
+ * the resource doesn't need one. In that case, we should
|
||||||
|
+ * consider this acl.
|
||||||
|
+ * the opposite is true if it is a deny rule, only a deny without
|
||||||
|
+ * any targetattr should deny modrdn
|
||||||
|
+ * default: matches = ACL_TRUE;
|
||||||
|
+ */
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
matches = ACL_FALSE;
|
||||||
|
@@ -2821,16 +2786,16 @@ acl__resource_match_aci(Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *a
|
||||||
|
} /* !attr_matched_in_targetattrfilters */
|
||||||
|
|
||||||
|
/*
|
||||||
|
- ** Here we are testing if we find a entry test rule (which should
|
||||||
|
- ** be rare). In that case, just remember it. An entry test rule
|
||||||
|
- ** doesn't have "(targetattr)".
|
||||||
|
- */
|
||||||
|
+ * Here we are testing if we find a entry test rule (which should
|
||||||
|
+ * be rare). In that case, just remember it. An entry test rule
|
||||||
|
+ * doesn't have "(targetattr)".
|
||||||
|
+ */
|
||||||
|
if ((aclpb->aclpb_state & ACLPB_EVALUATING_FIRST_ATTR) &&
|
||||||
|
(!(aci->aci_type & ACI_TARGET_ATTR))) {
|
||||||
|
aclpb->aclpb_state |= ACLPB_FOUND_A_ENTRY_TEST_RULE;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*
|
||||||
|
+ /*
|
||||||
|
* Generic exit point for this routine:
|
||||||
|
* matches is ACL_TRUE if the aci matches the target of the resource,
|
||||||
|
* ACL_FALSE othrewise.
|
||||||
|
@@ -2853,6 +2818,7 @@ acl__resource_match_aci_EXIT:
|
||||||
|
|
||||||
|
return (matches);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
/* Macro to determine if the cached result is valid or not. */
|
||||||
|
#define ACL_CACHED_RESULT_VALID(result) \
|
||||||
|
(((result & ACLPB_CACHE_READ_RES_ALLOW) && \
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/findentry.c b/ldap/servers/slapd/back-ldbm/findentry.c
|
||||||
|
index 6e53a0aea..bff751c88 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/findentry.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/findentry.c
|
||||||
|
@@ -93,7 +93,6 @@ find_entry_internal_dn(
|
||||||
|
size_t tries = 0;
|
||||||
|
int isroot = 0;
|
||||||
|
int op_type;
|
||||||
|
- char *errbuf = NULL;
|
||||||
|
|
||||||
|
/* get the managedsait ldap message control */
|
||||||
|
slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
|
||||||
|
@@ -207,8 +206,8 @@ find_entry_internal_dn(
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (acl_type > 0) {
|
||||||
|
- err = plugin_call_acl_plugin(pb, me->ep_entry, NULL, NULL, acl_type,
|
||||||
|
- ACLPLUGIN_ACCESS_DEFAULT, &errbuf);
|
||||||
|
+ char *dummy_attr = "1.1";
|
||||||
|
+ err = slapi_access_allowed(pb, me->ep_entry, dummy_attr, NULL, acl_type);
|
||||||
|
}
|
||||||
|
if (((acl_type > 0) && err) || (op_type == SLAPI_OPERATION_BIND)) {
|
||||||
|
/*
|
||||||
|
@@ -237,7 +236,6 @@ find_entry_internal_dn(
|
||||||
|
CACHE_RETURN(&inst->inst_cache, &me);
|
||||||
|
}
|
||||||
|
|
||||||
|
- slapi_ch_free_string(&errbuf);
|
||||||
|
slapi_log_err(SLAPI_LOG_TRACE, "find_entry_internal_dn", "<= Not found (%s)\n",
|
||||||
|
slapi_sdn_get_dn(sdn));
|
||||||
|
return (NULL);
|
||||||
|
diff --git a/src/lib389/lib389/_mapped_object.py b/src/lib389/lib389/_mapped_object.py
|
||||||
|
index c60837601..ca6ea6ef8 100644
|
||||||
|
--- a/src/lib389/lib389/_mapped_object.py
|
||||||
|
+++ b/src/lib389/lib389/_mapped_object.py
|
||||||
|
@@ -1190,7 +1190,7 @@ class DSLdapObjects(DSLogging, DSLints):
|
||||||
|
# Now actually commit the creation req
|
||||||
|
return co.ensure_state(rdn, properties, self._basedn)
|
||||||
|
|
||||||
|
- def filter(self, search, scope=None):
|
||||||
|
+ def filter(self, search, scope=None, strict=False):
|
||||||
|
# This will yield and & filter for objectClass with as many terms as needed.
|
||||||
|
if search:
|
||||||
|
search_filter = _gen_and([self._get_objectclass_filter(), search])
|
||||||
|
@@ -1211,5 +1211,7 @@ class DSLdapObjects(DSLogging, DSLints):
|
||||||
|
insts = [self._entry_to_instance(dn=r.dn, entry=r) for r in results]
|
||||||
|
except ldap.NO_SUCH_OBJECT:
|
||||||
|
# There are no objects to select from, se we return an empty array
|
||||||
|
+ if strict:
|
||||||
|
+ raise ldap.NO_SUCH_OBJECT
|
||||||
|
insts = []
|
||||||
|
return insts
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,145 @@
|
|||||||
|
From 4fb3023a55529c9d5332e3425ae8da590a8ebb69 Mon Sep 17 00:00:00 2001
|
||||||
|
From: tbordaz <tbordaz@redhat.com>
|
||||||
|
Date: Mon, 1 Feb 2021 09:28:25 +0100
|
||||||
|
Subject: [PATCH 3/4] Issue 4581 - A failed re-indexing leaves the database in
|
||||||
|
broken state (#4582)
|
||||||
|
|
||||||
|
Bug description:
|
||||||
|
During reindex the numsubordinates attribute is not updated in parent entries.
|
||||||
|
The consequence is that the internal counter job->numsubordinates==0.
|
||||||
|
Later when indexing the ancestorid, the server can show the progression of this
|
||||||
|
indexing with a ratio using job->numsubordinates==0.
|
||||||
|
Division with 0 -> SIGFPE
|
||||||
|
|
||||||
|
Fix description:
|
||||||
|
if the numsubordinates is NULL, log a message without a division.
|
||||||
|
|
||||||
|
relates: https://github.com/389ds/389-ds-base/issues/4581
|
||||||
|
|
||||||
|
Reviewed by: Pierre Rogier, Mark Reynolds, Simon Pichugin, Teko Mihinto (thanks !!)
|
||||||
|
|
||||||
|
Platforms tested: F31
|
||||||
|
---
|
||||||
|
.../slapd/back-ldbm/db-bdb/bdb_import.c | 72 ++++++++++++++-----
|
||||||
|
1 file changed, 54 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c
|
||||||
|
index 15574e60f..9713b52f6 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c
|
||||||
|
@@ -468,18 +468,30 @@ bdb_get_nonleaf_ids(backend *be, DB_TXN *txn, IDList **idl, ImportJob *job)
|
||||||
|
}
|
||||||
|
key_count++;
|
||||||
|
if (!(key_count % PROGRESS_INTERVAL)) {
|
||||||
|
- import_log_notice(job, SLAPI_LOG_INFO, "bdb_get_nonleaf_ids",
|
||||||
|
- "Gathering ancestorid non-leaf IDs: processed %d%% (ID count %d)",
|
||||||
|
- (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ if (job->numsubordinates) {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_get_nonleaf_ids",
|
||||||
|
+ "Gathering ancestorid non-leaf IDs: processed %d%% (ID count %d)",
|
||||||
|
+ (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ } else {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_get_nonleaf_ids",
|
||||||
|
+ "Gathering ancestorid non-leaf IDs: processed %d ancestors...",
|
||||||
|
+ key_count);
|
||||||
|
+ }
|
||||||
|
started_progress_logging = 1;
|
||||||
|
}
|
||||||
|
} while (ret == 0 && !(job->flags & FLAG_ABORT));
|
||||||
|
|
||||||
|
if (started_progress_logging) {
|
||||||
|
/* finish what we started logging */
|
||||||
|
- import_log_notice(job, SLAPI_LOG_INFO, "bdb_get_nonleaf_ids",
|
||||||
|
- "Gathering ancestorid non-leaf IDs: processed %d%% (ID count %d)",
|
||||||
|
- (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ if (job->numsubordinates) {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_get_nonleaf_ids",
|
||||||
|
+ "Gathering ancestorid non-leaf IDs: processed %d%% (ID count %d)",
|
||||||
|
+ (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ } else {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_get_nonleaf_ids",
|
||||||
|
+ "Gathering ancestorid non-leaf IDs: processed %d ancestors",
|
||||||
|
+ key_count);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
import_log_notice(job, SLAPI_LOG_INFO, "bdb_get_nonleaf_ids",
|
||||||
|
"Finished gathering ancestorid non-leaf IDs.");
|
||||||
|
@@ -660,9 +672,15 @@ bdb_ancestorid_default_create_index(backend *be, ImportJob *job)
|
||||||
|
|
||||||
|
key_count++;
|
||||||
|
if (!(key_count % PROGRESS_INTERVAL)) {
|
||||||
|
- import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_default_create_index",
|
||||||
|
- "Creating ancestorid index: processed %d%% (ID count %d)",
|
||||||
|
- (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ if (job->numsubordinates) {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_default_create_index",
|
||||||
|
+ "Creating ancestorid index: processed %d%% (ID count %d)",
|
||||||
|
+ (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ } else {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_default_create_index",
|
||||||
|
+ "Creating ancestorid index: processed %d ancestors...",
|
||||||
|
+ key_count);
|
||||||
|
+ }
|
||||||
|
started_progress_logging = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -743,9 +761,15 @@ out:
|
||||||
|
if (ret == 0) {
|
||||||
|
if (started_progress_logging) {
|
||||||
|
/* finish what we started logging */
|
||||||
|
- import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_default_create_index",
|
||||||
|
- "Creating ancestorid index: processed %d%% (ID count %d)",
|
||||||
|
- (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ if (job->numsubordinates) {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_default_create_index",
|
||||||
|
+ "Creating ancestorid index: processed %d%% (ID count %d)",
|
||||||
|
+ (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ } else {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_default_create_index",
|
||||||
|
+ "Creating ancestorid index: processed %d ancestors",
|
||||||
|
+ key_count);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_default_create_index",
|
||||||
|
"Created ancestorid index (old idl).");
|
||||||
|
@@ -869,9 +893,15 @@ bdb_ancestorid_new_idl_create_index(backend *be, ImportJob *job)
|
||||||
|
|
||||||
|
key_count++;
|
||||||
|
if (!(key_count % PROGRESS_INTERVAL)) {
|
||||||
|
- import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_new_idl_create_index",
|
||||||
|
- "Creating ancestorid index: progress %d%% (ID count %d)",
|
||||||
|
- (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ if (job->numsubordinates) {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_new_idl_create_index",
|
||||||
|
+ "Creating ancestorid index: progress %d%% (ID count %d)",
|
||||||
|
+ (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ } else {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_new_idl_create_index",
|
||||||
|
+ "Creating ancestorid index: progress %d ancestors...",
|
||||||
|
+ key_count);
|
||||||
|
+ }
|
||||||
|
started_progress_logging = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -932,9 +962,15 @@ out:
|
||||||
|
if (ret == 0) {
|
||||||
|
if (started_progress_logging) {
|
||||||
|
/* finish what we started logging */
|
||||||
|
- import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_new_idl_create_index",
|
||||||
|
- "Creating ancestorid index: processed %d%% (ID count %d)",
|
||||||
|
- (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ if (job->numsubordinates) {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_new_idl_create_index",
|
||||||
|
+ "Creating ancestorid index: processed %d%% (ID count %d)",
|
||||||
|
+ (key_count * 100 / job->numsubordinates), key_count);
|
||||||
|
+ } else {
|
||||||
|
+ import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_new_idl_create_index",
|
||||||
|
+ "Creating ancestorid index: processed %d ancestors",
|
||||||
|
+ key_count);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
import_log_notice(job, SLAPI_LOG_INFO, "bdb_ancestorid_new_idl_create_index",
|
||||||
|
"Created ancestorid index (new idl).");
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,163 @@
|
|||||||
|
From 861f17d2cb50fc649feee004be1ce08d2e3873f8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mark Reynolds <mreynolds@redhat.com>
|
||||||
|
Date: Tue, 9 Feb 2021 14:02:59 -0500
|
||||||
|
Subject: [PATCH 4/4] Issue 4609 - CVE - info disclosure when authenticating
|
||||||
|
|
||||||
|
Description: If you bind as a user that does not exist. Error 49 is returned
|
||||||
|
instead of error 32. As error 32 discloses that the entry does
|
||||||
|
not exist. When you bind as an entry that does not have userpassword
|
||||||
|
set then error 48 (inappropriate auth) is returned, but this
|
||||||
|
discloses that the entry does indeed exist. Instead we should
|
||||||
|
always return error 49, even if the password is not set in the
|
||||||
|
entry. This way we do not disclose to an attacker if the Bind
|
||||||
|
DN exists or not.
|
||||||
|
|
||||||
|
Relates: https://github.com/389ds/389-ds-base/issues/4609
|
||||||
|
|
||||||
|
Reviewed by: tbordaz(Thanks!)
|
||||||
|
---
|
||||||
|
dirsrvtests/tests/suites/basic/basic_test.py | 72 +++++++++++++++++++-
|
||||||
|
ldap/servers/slapd/back-ldbm/ldbm_bind.c | 4 +-
|
||||||
|
ldap/servers/slapd/dse.c | 7 +-
|
||||||
|
3 files changed, 78 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/basic/basic_test.py b/dirsrvtests/tests/suites/basic/basic_test.py
|
||||||
|
index e9afa1e7e..6244782fa 100644
|
||||||
|
--- a/dirsrvtests/tests/suites/basic/basic_test.py
|
||||||
|
+++ b/dirsrvtests/tests/suites/basic/basic_test.py
|
||||||
|
@@ -13,7 +13,7 @@
|
||||||
|
|
||||||
|
from subprocess import check_output, PIPE, run
|
||||||
|
from lib389 import DirSrv
|
||||||
|
-from lib389.idm.user import UserAccounts
|
||||||
|
+from lib389.idm.user import UserAccount, UserAccounts
|
||||||
|
import pytest
|
||||||
|
from lib389.tasks import *
|
||||||
|
from lib389.utils import *
|
||||||
|
@@ -1062,6 +1062,76 @@ def test_search_ou(topology_st):
|
||||||
|
assert len(entries) == 0
|
||||||
|
|
||||||
|
|
||||||
|
+def test_bind_invalid_entry(topology_st):
|
||||||
|
+ """Test the failing bind does not return information about the entry
|
||||||
|
+
|
||||||
|
+ :id: 5cd9b083-eea6-426b-84ca-83c26fc49a6f
|
||||||
|
+ :customerscenario: True
|
||||||
|
+ :setup: Standalone instance
|
||||||
|
+ :steps:
|
||||||
|
+ 1: bind as non existing entry
|
||||||
|
+ 2: check that bind info does not report 'No such entry'
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1: pass
|
||||||
|
+ 2: pass
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ topology_st.standalone.restart()
|
||||||
|
+ INVALID_ENTRY="cn=foooo,%s" % DEFAULT_SUFFIX
|
||||||
|
+ try:
|
||||||
|
+ topology_st.standalone.simple_bind_s(INVALID_ENTRY, PASSWORD)
|
||||||
|
+ except ldap.LDAPError as e:
|
||||||
|
+ log.info('test_bind_invalid_entry: Failed to bind as %s (expected)' % INVALID_ENTRY)
|
||||||
|
+ log.info('exception description: ' + e.args[0]['desc'])
|
||||||
|
+ if 'info' in e.args[0]:
|
||||||
|
+ log.info('exception info: ' + e.args[0]['info'])
|
||||||
|
+ assert e.args[0]['desc'] == 'Invalid credentials'
|
||||||
|
+ assert 'info' not in e.args[0]
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ log.info('test_bind_invalid_entry: PASSED')
|
||||||
|
+
|
||||||
|
+ # reset credentials
|
||||||
|
+ topology_st.standalone.simple_bind_s(DN_DM, PW_DM)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def test_bind_entry_missing_passwd(topology_st):
|
||||||
|
+ """
|
||||||
|
+ :id: af209149-8fb8-48cb-93ea-3e82dd7119d2
|
||||||
|
+ :setup: Standalone Instance
|
||||||
|
+ :steps:
|
||||||
|
+ 1. Bind as database entry that does not have userpassword set
|
||||||
|
+ 2. Bind as database entry that does not exist
|
||||||
|
+ 1. Bind as cn=config entry that does not have userpassword set
|
||||||
|
+ 2. Bind as cn=config entry that does not exist
|
||||||
|
+ :expectedresults:
|
||||||
|
+ 1. Fails with error 49
|
||||||
|
+ 2. Fails with error 49
|
||||||
|
+ 3. Fails with error 49
|
||||||
|
+ 4. Fails with error 49
|
||||||
|
+ """
|
||||||
|
+ user = UserAccount(topology_st.standalone, DEFAULT_SUFFIX)
|
||||||
|
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
|
||||||
|
+ # Bind as the suffix root entry which does not have a userpassword
|
||||||
|
+ user.bind("some_password")
|
||||||
|
+
|
||||||
|
+ user = UserAccount(topology_st.standalone, "cn=not here," + DEFAULT_SUFFIX)
|
||||||
|
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
|
||||||
|
+ # Bind as the entry which does not exist
|
||||||
|
+ user.bind("some_password")
|
||||||
|
+
|
||||||
|
+ # Test cn=config since it has its own code path
|
||||||
|
+ user = UserAccount(topology_st.standalone, "cn=config")
|
||||||
|
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
|
||||||
|
+ # Bind as the config entry which does not have a userpassword
|
||||||
|
+ user.bind("some_password")
|
||||||
|
+
|
||||||
|
+ user = UserAccount(topology_st.standalone, "cn=does not exist,cn=config")
|
||||||
|
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
|
||||||
|
+ # Bind as an entry under cn=config that does not exist
|
||||||
|
+ user.bind("some_password")
|
||||||
|
+
|
||||||
|
+
|
||||||
|
@pytest.mark.bz1044135
|
||||||
|
@pytest.mark.ds47319
|
||||||
|
def test_connection_buffer_size(topology_st):
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_bind.c b/ldap/servers/slapd/back-ldbm/ldbm_bind.c
|
||||||
|
index fa450ecd5..38d115a32 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/ldbm_bind.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/ldbm_bind.c
|
||||||
|
@@ -76,8 +76,8 @@ ldbm_back_bind(Slapi_PBlock *pb)
|
||||||
|
case LDAP_AUTH_SIMPLE: {
|
||||||
|
Slapi_Value cv;
|
||||||
|
if (slapi_entry_attr_find(e->ep_entry, "userpassword", &attr) != 0) {
|
||||||
|
- slapi_send_ldap_result(pb, LDAP_INAPPROPRIATE_AUTH, NULL,
|
||||||
|
- NULL, 0, NULL);
|
||||||
|
+ slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Entry does not have userpassword set");
|
||||||
|
+ slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
|
||||||
|
CACHE_RETURN(&inst->inst_cache, &e);
|
||||||
|
rc = SLAPI_BIND_FAIL;
|
||||||
|
goto bail;
|
||||||
|
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
|
||||||
|
index 0e22d3cec..0d3268046 100644
|
||||||
|
--- a/ldap/servers/slapd/dse.c
|
||||||
|
+++ b/ldap/servers/slapd/dse.c
|
||||||
|
@@ -1443,7 +1443,8 @@ dse_bind(Slapi_PBlock *pb) /* JCM There should only be one exit point from this
|
||||||
|
|
||||||
|
ec = dse_get_entry_copy(pdse, sdn, DSE_USE_LOCK);
|
||||||
|
if (ec == NULL) {
|
||||||
|
- slapi_send_ldap_result(pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL);
|
||||||
|
+ slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Entry does not exist");
|
||||||
|
+ slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
|
||||||
|
return (SLAPI_BIND_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1451,7 +1452,8 @@ dse_bind(Slapi_PBlock *pb) /* JCM There should only be one exit point from this
|
||||||
|
case LDAP_AUTH_SIMPLE: {
|
||||||
|
Slapi_Value cv;
|
||||||
|
if (slapi_entry_attr_find(ec, "userpassword", &attr) != 0) {
|
||||||
|
- slapi_send_ldap_result(pb, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, 0, NULL);
|
||||||
|
+ slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Entry does not have userpassword set");
|
||||||
|
+ slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
|
||||||
|
slapi_entry_free(ec);
|
||||||
|
return SLAPI_BIND_FAIL;
|
||||||
|
}
|
||||||
|
@@ -1459,6 +1461,7 @@ dse_bind(Slapi_PBlock *pb) /* JCM There should only be one exit point from this
|
||||||
|
|
||||||
|
slapi_value_init_berval(&cv, cred);
|
||||||
|
if (slapi_pw_find_sv(bvals, &cv) != 0) {
|
||||||
|
+ slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Invalid credentials");
|
||||||
|
slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
|
||||||
|
slapi_entry_free(ec);
|
||||||
|
value_done(&cv);
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,97 @@
|
|||||||
|
From 82db41ae6f76464a6ee3cbfdca8019bc809b3cf3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: William Brown <william@blackhats.net.au>
|
||||||
|
Date: Thu, 26 Nov 2020 09:08:13 +1000
|
||||||
|
Subject: [PATCH] Issue 4460 - BUG - lib389 should use system tls policy
|
||||||
|
|
||||||
|
Bug Description: Due to some changes in dsrc for tlsreqcert
|
||||||
|
and how def open was structured in lib389, the system ldap.conf
|
||||||
|
policy was ignored.
|
||||||
|
|
||||||
|
Fix Description: Default to using the system ldap.conf policy
|
||||||
|
if undefined in lib389 or the tls_reqcert param in dsrc.
|
||||||
|
|
||||||
|
fixes: #4460
|
||||||
|
|
||||||
|
Author: William Brown <william@blackhats.net.au>
|
||||||
|
|
||||||
|
Review by: ???
|
||||||
|
---
|
||||||
|
src/lib389/lib389/__init__.py | 11 +++++++----
|
||||||
|
src/lib389/lib389/cli_base/dsrc.py | 16 +++++++++-------
|
||||||
|
2 files changed, 16 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib389/lib389/__init__.py b/src/lib389/lib389/__init__.py
|
||||||
|
index 63d44b60a..dc18b2bfe 100644
|
||||||
|
--- a/src/lib389/lib389/__init__.py
|
||||||
|
+++ b/src/lib389/lib389/__init__.py
|
||||||
|
@@ -962,7 +962,7 @@ class DirSrv(SimpleLDAPObject, object):
|
||||||
|
# Now, we are still an allocated ds object so we can be re-installed
|
||||||
|
self.state = DIRSRV_STATE_ALLOCATED
|
||||||
|
|
||||||
|
- def open(self, uri=None, saslmethod=None, sasltoken=None, certdir=None, starttls=False, connOnly=False, reqcert=ldap.OPT_X_TLS_HARD,
|
||||||
|
+ def open(self, uri=None, saslmethod=None, sasltoken=None, certdir=None, starttls=False, connOnly=False, reqcert=None,
|
||||||
|
usercert=None, userkey=None):
|
||||||
|
'''
|
||||||
|
It opens a ldap bound connection to dirsrv so that online
|
||||||
|
@@ -1025,9 +1025,12 @@ class DirSrv(SimpleLDAPObject, object):
|
||||||
|
try:
|
||||||
|
# Note this sets LDAP.OPT not SELF. Because once self has opened
|
||||||
|
# it can NOT change opts on reused (ie restart)
|
||||||
|
- self.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, reqcert)
|
||||||
|
- self.log.debug("Using certificate policy %s", reqcert)
|
||||||
|
- self.log.debug("ldap.OPT_X_TLS_REQUIRE_CERT = %s", reqcert)
|
||||||
|
+ if reqcert is not None:
|
||||||
|
+ self.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, reqcert)
|
||||||
|
+ self.log.debug("Using lib389 certificate policy %s", reqcert)
|
||||||
|
+ else:
|
||||||
|
+ self.log.debug("Using /etc/openldap/ldap.conf certificate policy")
|
||||||
|
+ self.log.debug("ldap.OPT_X_TLS_REQUIRE_CERT = %s", self.get_option(ldap.OPT_X_TLS_REQUIRE_CERT))
|
||||||
|
except ldap.LDAPError as e:
|
||||||
|
self.log.fatal('TLS negotiation failed: %s', e)
|
||||||
|
raise e
|
||||||
|
diff --git a/src/lib389/lib389/cli_base/dsrc.py b/src/lib389/lib389/cli_base/dsrc.py
|
||||||
|
index 9cad23437..8a4a2a55d 100644
|
||||||
|
--- a/src/lib389/lib389/cli_base/dsrc.py
|
||||||
|
+++ b/src/lib389/lib389/cli_base/dsrc.py
|
||||||
|
@@ -45,7 +45,7 @@ def dsrc_arg_concat(args, dsrc_inst):
|
||||||
|
'tls_cacertdir': None,
|
||||||
|
'tls_cert': None,
|
||||||
|
'tls_key': None,
|
||||||
|
- 'tls_reqcert': ldap.OPT_X_TLS_HARD,
|
||||||
|
+ 'tls_reqcert': None,
|
||||||
|
'starttls': args.starttls,
|
||||||
|
'prompt': False,
|
||||||
|
'pwdfile': None,
|
||||||
|
@@ -134,21 +134,23 @@ def dsrc_to_ldap(path, instance_name, log):
|
||||||
|
dsrc_inst['binddn'] = config.get(instance_name, 'binddn', fallback=None)
|
||||||
|
dsrc_inst['saslmech'] = config.get(instance_name, 'saslmech', fallback=None)
|
||||||
|
if dsrc_inst['saslmech'] is not None and dsrc_inst['saslmech'] not in ['EXTERNAL', 'PLAIN']:
|
||||||
|
- raise Exception("%s [%s] saslmech must be one of EXTERNAL or PLAIN" % (path, instance_name))
|
||||||
|
+ raise ValueError("%s [%s] saslmech must be one of EXTERNAL or PLAIN" % (path, instance_name))
|
||||||
|
|
||||||
|
dsrc_inst['tls_cacertdir'] = config.get(instance_name, 'tls_cacertdir', fallback=None)
|
||||||
|
dsrc_inst['tls_cert'] = config.get(instance_name, 'tls_cert', fallback=None)
|
||||||
|
dsrc_inst['tls_key'] = config.get(instance_name, 'tls_key', fallback=None)
|
||||||
|
- dsrc_inst['tls_reqcert'] = config.get(instance_name, 'tls_reqcert', fallback='hard')
|
||||||
|
- if dsrc_inst['tls_reqcert'] not in ['never', 'allow', 'hard']:
|
||||||
|
- raise Exception("dsrc tls_reqcert value invalid. %s [%s] tls_reqcert should be one of never, allow or hard" % (instance_name,
|
||||||
|
- path))
|
||||||
|
+ dsrc_inst['tls_reqcert'] = config.get(instance_name, 'tls_reqcert', fallback=None)
|
||||||
|
if dsrc_inst['tls_reqcert'] == 'never':
|
||||||
|
dsrc_inst['tls_reqcert'] = ldap.OPT_X_TLS_NEVER
|
||||||
|
elif dsrc_inst['tls_reqcert'] == 'allow':
|
||||||
|
dsrc_inst['tls_reqcert'] = ldap.OPT_X_TLS_ALLOW
|
||||||
|
- else:
|
||||||
|
+ elif dsrc_inst['tls_reqcert'] == 'hard':
|
||||||
|
dsrc_inst['tls_reqcert'] = ldap.OPT_X_TLS_HARD
|
||||||
|
+ elif dsrc_inst['tls_reqcert'] is None:
|
||||||
|
+ # Use system value
|
||||||
|
+ pass
|
||||||
|
+ else:
|
||||||
|
+ raise ValueError("dsrc tls_reqcert value invalid. %s [%s] tls_reqcert should be one of never, allow or hard" % (instance_name, path))
|
||||||
|
dsrc_inst['starttls'] = config.getboolean(instance_name, 'starttls', fallback=False)
|
||||||
|
dsrc_inst['pwdfile'] = None
|
||||||
|
dsrc_inst['prompt'] = False
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
From 2d6ca042adcf0dc2bbf9b898d698bbf62514c4a5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Firstyear <william@blackhats.net.au>
|
||||||
|
Date: Fri, 4 Dec 2020 10:14:33 +1000
|
||||||
|
Subject: [PATCH] Issue 4460 - BUG - add machine name to subject alt names in
|
||||||
|
SSCA (#4472)
|
||||||
|
|
||||||
|
Bug Description: During SSCA creation, the server cert did not have
|
||||||
|
the machine name, which meant that the cert would not work without
|
||||||
|
reqcert = never.
|
||||||
|
|
||||||
|
Fix Description: Add the machine name as an alt name during SSCA
|
||||||
|
creation. It is not guaranteed this value is correct, but it
|
||||||
|
is better than nothing.
|
||||||
|
|
||||||
|
relates: https://github.com/389ds/389-ds-base/issues/4460
|
||||||
|
|
||||||
|
Author: William Brown <william@blackhats.net.au>
|
||||||
|
|
||||||
|
Review by: mreynolds389, droideck
|
||||||
|
---
|
||||||
|
src/lib389/lib389/instance/setup.py | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib389/lib389/instance/setup.py b/src/lib389/lib389/instance/setup.py
|
||||||
|
index 45c7dfdd4..21260ee20 100644
|
||||||
|
--- a/src/lib389/lib389/instance/setup.py
|
||||||
|
+++ b/src/lib389/lib389/instance/setup.py
|
||||||
|
@@ -870,7 +870,7 @@ class SetupDs(object):
|
||||||
|
tlsdb_inst = NssSsl(dbpath=os.path.join(etc_dirsrv_path, dir))
|
||||||
|
tlsdb_inst.import_rsa_crt(ca)
|
||||||
|
|
||||||
|
- csr = tlsdb.create_rsa_key_and_csr()
|
||||||
|
+ csr = tlsdb.create_rsa_key_and_csr(alt_names=[general['full_machine_name']])
|
||||||
|
(ca, crt) = ssca.rsa_ca_sign_csr(csr)
|
||||||
|
tlsdb.import_rsa_crt(ca, crt)
|
||||||
|
if general['selinux']:
|
||||||
|
--
|
||||||
|
2.26.2
|
||||||
|
|
@ -45,7 +45,7 @@ ExcludeArch: i686
|
|||||||
Summary: 389 Directory Server (base)
|
Summary: 389 Directory Server (base)
|
||||||
Name: 389-ds-base
|
Name: 389-ds-base
|
||||||
Version: 1.4.3.8
|
Version: 1.4.3.8
|
||||||
Release: %{?relprefix}6%{?prerel}%{?dist}
|
Release: %{?relprefix}7%{?prerel}%{?dist}
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
URL: https://www.port389.org
|
URL: https://www.port389.org
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
@ -207,7 +207,12 @@ Patch30: 0030-ticket-2058-Add-keep-alive-entry-after-on-line-initi.patc
|
|||||||
Patch31: 0031-do-not-add-referrals-for-masters-with-different-data.patch
|
Patch31: 0031-do-not-add-referrals-for-masters-with-different-data.patch
|
||||||
Patch32: 0032-Issue-4383-Do-not-normalize-escaped-spaces-in-a-DN.patch
|
Patch32: 0032-Issue-4383-Do-not-normalize-escaped-spaces-in-a-DN.patch
|
||||||
Patch33: 0033-Issue-49300-entryUSN-is-duplicated-after-memberOf-op.patch
|
Patch33: 0033-Issue-49300-entryUSN-is-duplicated-after-memberOf-op.patch
|
||||||
|
Patch34: 0034-Issue-4480-Unexpected-info-returned-to-ldap-request-.patch
|
||||||
|
Patch35: 0035-Issue-5442-Search-results-are-different-between-RHDS.patch
|
||||||
|
Patch36: 0036-Issue-4581-A-failed-re-indexing-leaves-the-database-.patch
|
||||||
|
Patch37: 0037-Issue-4609-CVE-info-disclosure-when-authenticating.patch
|
||||||
|
Patch38: 0038-Issue-4460-BUG-lib389-should-use-system-tls-policy.patch
|
||||||
|
Patch39: 0039-Issue-4460-BUG-add-machine-name-to-subject-alt-names.patch
|
||||||
|
|
||||||
%description
|
%description
|
||||||
389 Directory Server is an LDAPv3 compliant server. The base package includes
|
389 Directory Server is an LDAPv3 compliant server. The base package includes
|
||||||
@ -825,15 +830,21 @@ exit 0
|
|||||||
%doc README.md
|
%doc README.md
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Mar 11 2021 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.8-7
|
||||||
|
- Bump version to 1.4.3.8-7
|
||||||
|
- Resolves: Bug 1908705 - CVE-2020-35518 389-ds:1.4/389-ds-base: information disclosure during the binding of a DN
|
||||||
|
- Resolves: Bug 1936461 - A failed re-indexing leaves the database in broken state.
|
||||||
|
- Resolves: Bug 1912481 - Server-Cert.crt created using dscreate has Subject:CN =localhost instead of hostname.
|
||||||
|
|
||||||
* Thu Dec 3 2020 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.8-6
|
* Thu Dec 3 2020 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.8-6
|
||||||
- Bump version to 1.4.3.8-6
|
- Bump version to 1.4.3.8-6
|
||||||
- Resolves: Bug 1851973 - Duplicate entryUSN numbers for different LDAP entries in the same backend
|
- Resolves: Bug 1904348 - Duplicate entryUSN numbers for different LDAP entries in the same backend
|
||||||
- Resolves: Bug 1888863 - group rdn with leading space char and add fails error 21 invalid syntax and delete fails error 32
|
- Resolves: Bug 1904349 - group rdn with leading space char and add fails error 21 invalid syntax and delete fails error 32
|
||||||
- Resolves: Bug 1859228 - do not add referrals for masters with different data generation
|
- Resolves: Bug 1904350 - do not add referrals for masters with different data generation
|
||||||
- Resolves: Bug 1859227 - create keep alive entry after on line init
|
- Resolves: Bug 1904351 - create keep alive entry after on line init
|
||||||
- Resolves: Bug 1896850 - NULL dereference in revert_cache()
|
- Resolves: Bug 1904352 - NULL dereference in revert_cache()
|
||||||
- Resolves: Bug 1861504 - ds-replcheck crashes in offline mode
|
- Resolves: Bug 1904353 - ds-replcheck crashes in offline mode
|
||||||
- Resolves: Bug 1898850 - Entries conflict not resolved by replication
|
- Resolves: Bug 1904347 - Entries conflict not resolved by replication
|
||||||
|
|
||||||
* Wed Aug 5 2020 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.8-5
|
* Wed Aug 5 2020 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.8-5
|
||||||
- Bump version to 1.4.3.8-5
|
- Bump version to 1.4.3.8-5
|
||||||
|
Loading…
Reference in New Issue
Block a user