Monday, June 20, 2016

[389-commits] 2 commits - dirsrvtests/tests ldap/servers

dirsrvtests/tests/tickets/ticket48366_test.py | 214 ++++++++++++++++++++++++++
ldap/servers/plugins/acl/acl.c | 13 -
ldap/servers/plugins/acl/acl.h | 2
ldap/servers/plugins/acl/acllist.c | 2
ldap/servers/plugins/acl/aclplugin.c | 10 +
5 files changed, 233 insertions(+), 8 deletions(-)

New commits:
commit 4d154353b014576b9630d63d3ed7b5e5676f13bf
Author: Ludwig Krispenz <lkrispen@redhat.com>
Date: Tue Feb 16 10:52:57 2016 +0100

Ticket #48366 - proxyauth does not work bound as directory manager

Description: when binding as directory manager always full access is granted, even if a proxyauthzid is presnt

Fix: when evaluating if access control can be skipped check for proxy auth

Ticket: https://fedorahosted.org/389/ticket/48366

Reviewed by: Noriko, Thanks

diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c
index be2b805..ba6b774 100644
--- a/ldap/servers/plugins/acl/acl.c
+++ b/ldap/servers/plugins/acl/acl.c
@@ -287,7 +287,7 @@ acl_access_allowed(

/* Check for things we need to skip */
TNF_PROBE_0_DEBUG(acl_skipaccess_start,"ACL","");
- if ( acl_skip_access_check ( pb, e )) {
+ if ( acl_skip_access_check ( pb, e, access )) {
slapi_log_error (loglevel, plugin_name,
"conn=%" NSPRIu64 " op=%d (main): Allow %s on entry(%s)"
": root user\n",
@@ -921,7 +921,7 @@ acl_read_access_allowed_on_entry (
** If it's the root, or acl is off or the entry is a rootdse,
** Then you have the privilege to read it.
*/
- if ( acl_skip_access_check ( pb, e ) ) {
+ if ( acl_skip_access_check ( pb, e, access ) ) {
char *n_edn = slapi_entry_get_ndn ( e );
slapi_log_error (SLAPI_LOG_ACL, plugin_name,
"Root access (%s) allowed on entry(%s)\n",
@@ -1227,7 +1227,7 @@ acl_read_access_allowed_on_attr (
n_edn = slapi_entry_get_ndn ( e );

/* If it's the root or acl is off or rootdse, he has all the priv */
- if ( acl_skip_access_check ( pb, e ) ) {
+ if ( acl_skip_access_check ( pb, e, access ) ) {
slapi_log_error (SLAPI_LOG_ACL, plugin_name,
"Root access (%s) allowed on entry(%s)\n",
acl_access2str(access),
@@ -4053,14 +4053,17 @@ acl__get_attrEval ( struct acl_pblock *aclpb, char *attr )
*
*/
int
-acl_skip_access_check ( Slapi_PBlock *pb, Slapi_Entry *e )
+acl_skip_access_check ( Slapi_PBlock *pb, Slapi_Entry *e, int access )
{
int rv, isRoot, accessCheckDisabled;
void *conn = NULL;
Slapi_Backend *be;
+ struct acl_pblock *aclpb = NULL;

slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot );
- if ( isRoot ) return ACL_TRUE;
+ /* need to check if root is proying another user */
+ aclpb = acl_get_aclpb ( pb, ACLPB_PROXYDN_PBLOCK );
+ if ( isRoot && ((access &SLAPI_ACL_PROXY) || !aclpb)) return ACL_TRUE;

/* See if this is local request */
slapi_pblock_get ( pb, SLAPI_CONNECTION, &conn);
diff --git a/ldap/servers/plugins/acl/acl.h b/ldap/servers/plugins/acl/acl.h
index da39cbc..6e3198f 100644
--- a/ldap/servers/plugins/acl/acl.h
+++ b/ldap/servers/plugins/acl/acl.h
@@ -822,7 +822,7 @@ void acl_init_aclpb ( Slapi_PBlock *pb , Acl_PBlock *aclpb,
const char *dn, int copy_from_aclcb);
int acl_create_aclpb_pool ();
void acl_destroy_aclpb_pool ();
-int acl_skip_access_check ( Slapi_PBlock *pb, Slapi_Entry *e );
+int acl_skip_access_check ( Slapi_PBlock *pb, Slapi_Entry *e, int access );

int aclext_alloc_lockarray ();
void aclext_free_lockarray();
diff --git a/ldap/servers/plugins/acl/acllist.c b/ldap/servers/plugins/acl/acllist.c
index d604e37..cc0e9b3 100644
--- a/ldap/servers/plugins/acl/acllist.c
+++ b/ldap/servers/plugins/acl/acllist.c
@@ -611,7 +611,7 @@ acllist_init_scan (Slapi_PBlock *pb, int scope, const char *base)
char *basedn = NULL;
int index;

- if ( acl_skip_access_check ( pb, NULL ) ) {
+ if ( acl_skip_access_check ( pb, NULL, 0 ) ) {
return;
}

diff --git a/ldap/servers/plugins/acl/aclplugin.c b/ldap/servers/plugins/acl/aclplugin.c
index d90996e..50de2cc 100644
--- a/ldap/servers/plugins/acl/aclplugin.c
+++ b/ldap/servers/plugins/acl/aclplugin.c
@@ -110,14 +110,22 @@ aclplugin_preop_search ( Slapi_PBlock *pb )
Slapi_DN *sdn = NULL;
int optype;
int isRoot;
+ int isProxy = 0;
int rc = 0;
+ char *errtxt = NULL;
+ char *proxy_dn = NULL;

TNF_PROBE_0_DEBUG(aclplugin_preop_search_start ,"ACL","");

slapi_pblock_get ( pb, SLAPI_OPERATION_TYPE, &optype );
slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot );

- if ( isRoot ) {
+ if (LDAP_SUCCESS == proxyauth_get_dn(pb, &proxy_dn, &errtxt) && proxy_dn) {
+ isProxy = 1;
+ slapi_ch_free_string(&proxy_dn);
+ }
+
+ if ( isRoot && !isProxy) {
TNF_PROBE_1_DEBUG(aclplugin_preop_search_end ,"ACL","",
tnf_string,isroot,"");
return rc;


commit 59e45a75a8ba2995b5ddb33a42fc017ecf3d17a3
Author: Ludwig Krispenz <lkrispen@redhat.com>
Date: Fri Jun 17 13:49:05 2016 +0200

add testcase for ticket 48366 - proxyauth for root

diff --git a/dirsrvtests/tests/tickets/ticket48366_test.py b/dirsrvtests/tests/tickets/ticket48366_test.py
new file mode 100644
index 0000000..fb2dd97
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket48366_test.py
@@ -0,0 +1,214 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2015 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import os
+import sys
+import time
+import ldap
+import logging
+import pytest
+from lib389 import DirSrv, Entry, tools
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from ldap.controls.simple import ProxyAuthzControl
+
+log = logging.getLogger(__name__)
+
+installation_prefix = None
+
+PROXY_USER_DN = 'cn=proxy,ou=people,%s' % SUFFIX
+TEST_USER_DN = 'cn=test,ou=people,%s' % SUFFIX
+USER_PW = 'password'
+
+
+# subtrees used in test
+SUBTREE_GREEN = "ou=green,%s" % SUFFIX
+SUBTREE_RED = "ou=red,%s" % SUFFIX
+SUBTREES = (SUBTREE_GREEN, SUBTREE_RED)
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+@pytest.fixture(scope="module")
+def topology(request):
+ global installation_prefix
+
+ if installation_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation_prefix
+
+ standalone = DirSrv(verbose=False)
+
+ # Args for the standalone instance
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+
+ # Get the status of the instance and restart it if it exists
+ instance_standalone = standalone.exists()
+
+ # Remove the instance
+ if instance_standalone:
+ standalone.delete()
+
+ # Create the instance
+ standalone.create()
+
+ # Used to retrieve configuration information (dbdir, confdir...)
+ standalone.open()
+
+ # clear the tmp directory
+ standalone.clearTmpDir(__file__)
+
+ # Here we have standalone instance up and running
+ return TopologyStandalone(standalone)
+
+
+def test_ticket48366_init(topology):
+ """
+ It creates identical entries in 3 subtrees
+ It creates aci which allow access to a set of attrs
+ in two of these subtrees for bound users
+ It creates a user to be used for test
+
+ """
+
+
+ topology.standalone.log.info("Add subtree: %s" % SUBTREE_GREEN)
+ topology.standalone.add_s(Entry((SUBTREE_GREEN, {
+ 'objectclass': "top organizationalunit".split(),
+ 'ou': "green_one"})))
+ topology.standalone.log.info("Add subtree: %s" % SUBTREE_RED)
+ topology.standalone.add_s(Entry((SUBTREE_RED, {
+ 'objectclass': "top organizationalunit".split(),
+ 'ou': "red"})))
+
+ # add proxy user and test user
+ topology.standalone.log.info("Add %s" % TEST_USER_DN)
+ topology.standalone.add_s(Entry((TEST_USER_DN, {
+ 'objectclass': "top person".split(),
+ 'sn': 'test',
+ 'cn': 'test',
+ 'userpassword': USER_PW})))
+ topology.standalone.log.info("Add %s" % PROXY_USER_DN)
+ topology.standalone.add_s(Entry((PROXY_USER_DN, {
+ 'objectclass': "top person".split(),
+ 'sn': 'proxy',
+ 'cn': 'proxy',
+ 'userpassword': USER_PW})))
+
+ # enable acl error logging
+ # mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '128')]
+ # topology.standalone.modify_s(DN_CONFIG, mod)
+
+ # get rid of default ACIs
+ mod = [(ldap.MOD_DELETE, 'aci', None)]
+ topology.standalone.modify_s(SUFFIX, mod)
+
+ # Ok Now add the proper ACIs
+ ACI_TARGET = "(target = \"ldap:///%s\")" % SUBTREE_GREEN
+ ACI_TARGETATTR = "(targetattr = \"objectclass || cn || sn || uid || givenname \")"
+ ACI_ALLOW = "(version 3.0; acl \"Allow search-read to green subtree\"; allow (read, search, compare)"
+ ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % TEST_USER_DN
+ ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_ALLOW + ACI_SUBJECT
+ mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+ topology.standalone.modify_s(SUFFIX, mod)
+
+ ACI_ALLOW = "(version 3.0; acl \"Allow use pf proxy auth to green subtree\"; allow (proxy)"
+ ACI_SUBJECT = " userdn = \"ldap:///%s\";)" % PROXY_USER_DN
+ ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_ALLOW + ACI_SUBJECT
+ mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
+ topology.standalone.modify_s(SUFFIX, mod)
+
+ log.info("Adding %d test entries...")
+ for id in range(2):
+ name = "%s%d" % ('test', id)
+ mail = "%s@example.com" % name
+ for subtree in SUBTREES:
+ topology.standalone.add_s(Entry(("cn=%s,%s" % (name, subtree), {
+ 'objectclass': "top person organizationalPerson inetOrgPerson".split(),
+ 'sn': name,
+ 'cn': name,
+ 'uid': name,
+ 'givenname': 'test',
+ 'mail': mail,
+ 'description': 'description',
+ 'employeenumber': "%d" % id,
+ 'telephonenumber': "%d%d%d" % (id,id,id),
+ 'mobile': "%d%d%d" % (id,id,id),
+ 'l': 'MV',
+ 'title': 'Engineer'})))
+
+
+
+def test_ticket48366_search_user(topology):
+
+ proxy_ctrl = ProxyAuthzControl(criticality=True, authzId="dn: "+TEST_USER_DN)
+ # searching as test user should return one entry from the green subtree
+ topology.standalone.simple_bind_s(TEST_USER_DN, PASSWORD)
+ ents = topology.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid=test1')
+ assert (len(ents) == 1)
+
+ # searching as proxy user should return no entry
+ topology.standalone.simple_bind_s(PROXY_USER_DN, PASSWORD)
+ ents = topology.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid=test1')
+ assert (len(ents) == 0)
+
+ # serching as proxy user, authorizing as test user should return 1 entry
+ ents = topology.standalone.search_ext_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid=test1', serverctrls=[proxy_ctrl])
+ assert (len(ents) == 1)
+
+def test_ticket48366_search_dm(topology):
+
+ # searching as directory manager should return one entries from both subtrees
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ ents = topology.standalone.search_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid=test1')
+ assert (len(ents) == 2)
+
+ # searching as directory manager proxying test user should return one entry
+ proxy_ctrl = ProxyAuthzControl(criticality=True, authzId="dn: "+TEST_USER_DN)
+ ents = topology.standalone.search_ext_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid=test1', serverctrls=[proxy_ctrl])
+ assert (len(ents) == 1)
+
+ # searching as directory manager proxying proxy user should return no entry
+ proxy_ctrl = ProxyAuthzControl(criticality=True, authzId="dn: "+PROXY_USER_DN)
+ ents = topology.standalone.search_ext_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid=test1', serverctrls=[proxy_ctrl])
+ assert (len(ents) == 0)
+
+def test_ticket48366_final(topology):
+ topology.standalone.delete()
+ log.info('Testcase PASSED')
+
+
+def run_isolated():
+ '''
+ run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
+ To run isolated without py.test, you need to
+ - edit this file and comment '@pytest.fixture' line before 'topology' function.
+ - set the installation prefix
+ - run this program
+ '''
+ global installation_prefix
+ installation_prefix = None
+
+ topo = topology(True)
+ test_ticket48366_init(topo)
+
+ test_ticket48366_search_dm(topo)
+
+ test_ticket48366_final(topo)
+
+
+if __name__ == '__main__':
+ run_isolated()
+

--
389-commits mailing list
389-commits@lists.fedoraproject.org
https://lists.fedoraproject.org/admin/lists/389-commits@lists.fedoraproject.org

No comments:

Post a Comment