ldap/servers/slapd/filter.h | 6 -
ldap/servers/slapd/str2filter.c | 145 ++++++++++++++++++++++----
3 files changed, 269 insertions(+), 21 deletions(-)
New commits:
commit 59b8b05c39104cd919a3fa872259b45a6def7b83
Author: Noriko Hosoi <nhosoi@redhat.com>
Date: Fri Jun 10 18:33:05 2016 -0700
Ticket #48234 - CI test: test case for ticket 48234
Description: "matching rules" in ACI's "bind rules not fully evaluated
diff --git a/dirsrvtests/tests/tickets/ticket48234_test.py b/dirsrvtests/tests/tickets/ticket48234_test.py
new file mode 100644
index 0000000..27eff1a
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket48234_test.py
@@ -0,0 +1,139 @@
+import os
+import sys
+import time
+import ldap
+import logging
+import pytest
+from lib389 import DirSrv, Entry, tools, tasks
+from lib389.tools import DirSrvTools
+from lib389._constants import *
+from lib389.properties import *
+from lib389.tasks import *
+from lib389.utils import *
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+installation1_prefix = None
+
+
+class TopologyStandalone(object):
+ def __init__(self, standalone):
+ standalone.open()
+ self.standalone = standalone
+
+
+@pytest.fixture(scope="module")
+def topology(request):
+ global installation1_prefix
+ if installation1_prefix:
+ args_instance[SER_DEPLOYED_DIR] = installation1_prefix
+
+ # Creating standalone instance ...
+ standalone = DirSrv(verbose=False)
+ args_instance[SER_HOST] = HOST_STANDALONE
+ args_instance[SER_PORT] = PORT_STANDALONE
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
+ args_standalone = args_instance.copy()
+ standalone.allocate(args_standalone)
+ instance_standalone = standalone.exists()
+ if instance_standalone:
+ standalone.delete()
+ standalone.create()
+ standalone.open()
+
+ # Delete each instance in the end
+ def fin():
+ standalone.delete()
+ request.addfinalizer(fin)
+
+ # Clear out the tmp dir
+ standalone.clearTmpDir(__file__)
+
+ return TopologyStandalone(standalone)
+
+def add_ou_entry(server, name, myparent):
+ dn = 'ou=%s,%s' % (name, myparent)
+ server.add_s(Entry((dn, {'objectclass': ['top', 'organizationalunit'],
+ 'ou': name})))
+
+def add_user_entry(server, name, pw, myparent):
+ dn = 'cn=%s,%s' % (name, myparent)
+ server.add_s(Entry((dn, {'objectclass': ['top', 'person'],
+ 'sn': name,
+ 'cn': name,
+ 'telephonenumber': '+1 222 333-4444',
+ 'userpassword': pw})))
+
+def test_ticket48234(topology):
+ """
+ Test aci which contains an extensible filter.
+ shutdown
+ """
+
+ log.info('Bind as root DN')
+ try:
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
+ except ldap.LDAPError as e:
+ topology.standalone.log.error('Root DN failed to authenticate: ' + e.message['desc'])
+ assert False
+
+ ouname = 'outest'
+ username = 'admin'
+ passwd = 'Password'
+ deniedattr = 'telephonenumber'
+ log.info('Add aci which contains extensible filter.')
+ aci_text = ('(targetattr = "%s")' % (deniedattr) +
+ '(target = "ldap:///%s")' % (DEFAULT_SUFFIX) +
+ '(version 3.0;acl "admin-tel-matching-rule-outest";deny (all)' +
+ '(userdn = "ldap:///%s??sub?(&(cn=%s)(ou:dn:=%s))");)' % (DEFAULT_SUFFIX, username, ouname))
+
+ try:
+ topology.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci', aci_text)])
+ except ldap.LDAPError as e:
+ log.error('Failed to add aci: (%s) error %s' % (aci_text, e.message['desc']))
+ assert False
+
+ log.info('Add entries ...')
+ for idx in range(0, 2):
+ ou0 = 'OU%d' % idx
+ log.info('adding %s under %s...' % (ou0, DEFAULT_SUFFIX))
+ add_ou_entry(topology.standalone, ou0, DEFAULT_SUFFIX)
+ parent = 'ou=%s,%s' % (ou0, DEFAULT_SUFFIX)
+ log.info('adding %s under %s...' % (ouname, parent))
+ add_ou_entry(topology.standalone, ouname, parent)
+
+ for idx in range(0, 2):
+ parent = 'ou=%s,ou=OU%d,%s' % (ouname, idx, DEFAULT_SUFFIX)
+ log.info('adding %s under %s...' % (username, parent))
+ add_user_entry(topology.standalone, username, passwd, parent)
+
+ binddn = 'cn=%s,%s' % (username, parent)
+ log.info('Bind as user %s' % binddn)
+ try:
+ topology.standalone.simple_bind_s(binddn, passwd)
+ except ldap.LDAPError as e:
+ topology.standalone.log.error(bindn + ' failed to authenticate: ' + e.message['desc'])
+ assert False
+
+ filter = '(cn=%s)' % username
+ try:
+ entries = topology.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, filter, [deniedattr, 'dn'])
+ assert 2 == len(entries)
+ for idx in range(0, 1):
+ if entries[idx].hasAttr(deniedattr):
+ log.fatal('aci with extensible filter failed -- %s')
+ assert False
+ except ldap.LDAPError as e:
+ topology.standalone.log.error('Search (%s, %s) failed: ' % (DEFAULT_SUFFIX, filter) + e.message['desc'])
+ assert False
+
+ log.info('Test complete')
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
commit 32edbde0c2895ca31b3717cbb4abbd28b66b545b
Author: Noriko Hosoi <nhosoi@redhat.com>
Date: Fri Jun 10 17:27:50 2016 -0700
Ticket #48234 - "matching rules" in ACI's "bind rules not fully evaluated
Description: Extensible filter was added to slapi_str2filter. Thus, aci
containing such a filter was ignored.
aci: (targetattr = "telephoneNumber") (target = "ldap:///dc=example,dc=com")
(version 3.0;acl "admin-tel-matching-rule-outest";deny (all)(userdn = "ldap
:///dc=example,dc=com??sub?(&(cn=admin)(ou:dn:=outest))");)
https://fedorahosted.org/389/ticket/48234
Reviewed by wibrown@redhat.com (Thank you, William!!)
diff --git a/ldap/servers/slapd/filter.h b/ldap/servers/slapd/filter.h
index 83e9bcc..e5a7e44 100644
--- a/ldap/servers/slapd/filter.h
+++ b/ldap/servers/slapd/filter.h
@@ -24,10 +24,14 @@ typedef int (*mrf_plugin_fn) (Slapi_PBlock*);
#define MRF_ANY_TYPE 1
#define MRF_ANY_VALUE 2
+/*
+ * To adjust the other structures in struct slapi_filter,
+ * the first field must be type and the second must be value.
+ */
typedef struct mr_filter_t {
- char* mrf_oid;
char* mrf_type;
struct berval mrf_value;
+ char* mrf_oid;
char mrf_dnAttrs;
mrFilterMatchFn mrf_match;
mrf_plugin_fn mrf_index;
diff --git a/ldap/servers/slapd/str2filter.c b/ldap/servers/slapd/str2filter.c
index ad696db..1a4a6ec 100644
--- a/ldap/servers/slapd/str2filter.c
+++ b/ldap/servers/slapd/str2filter.c
@@ -45,32 +45,28 @@ slapi_str2filter( char *str )
str++;
switch ( *str ) {
case '&':
- LDAPDebug( LDAP_DEBUG_FILTER, "slapi_str2filter: AND\n",
- 0, 0, 0 );
+ LDAPDebug0Args(LDAP_DEBUG_FILTER, "slapi_str2filter: AND\n");
str++;
f = str2list( str, LDAP_FILTER_AND );
break;
case '|':
- LDAPDebug( LDAP_DEBUG_FILTER, "put_filter: OR\n",
- 0, 0, 0 );
+ LDAPDebug0Args(LDAP_DEBUG_FILTER, "put_filter: OR\n");
str++;
f = str2list( str, LDAP_FILTER_OR );
break;
case '!':
- LDAPDebug( LDAP_DEBUG_FILTER, "put_filter: NOT\n",
- 0, 0, 0 );
+ LDAPDebug0Args(LDAP_DEBUG_FILTER, "put_filter: NOT\n");
str++;
f = str2list( str, LDAP_FILTER_NOT );
break;
default:
- LDAPDebug( LDAP_DEBUG_FILTER, "slapi_str2filter: simple\n",
- 0, 0, 0 );
+ LDAPDebug0Args(LDAP_DEBUG_FILTER, "slapi_str2filter: simple\n");
f = str2simple( str , 1 /* unescape_filter */);
break;
@@ -79,8 +75,7 @@ slapi_str2filter( char *str )
break;
default: /* assume it's a simple type=value filter */
- LDAPDebug( LDAP_DEBUG_FILTER, "slapi_str2filter: default\n", 0, 0,
- 0 );
+ LDAPDebug0Args(LDAP_DEBUG_FILTER, "slapi_str2filter: default\n");
f = str2simple( str , 1 /* unescape_filter */);
break;
@@ -209,7 +204,102 @@ filt_unescape_str(const char *instr, char *outstr, size_t outsize, size_t* outle
return 1; /* ok */
}
-
+/*
+ * Return value: 0 -- success
+ * : 1 -- failure
+ */
+static int
+_parse_ext_filter(char *str, char *p0, char **type, char **oid, char *dnAttrs)
+{
+ char *p1 = NULL;
+ char *p2 = NULL;
+
+ if (!type || !oid || !dnAttrs) {
+ return 1;
+ }
+ *type = NULL;
+ *oid = NULL;
+ *dnAttrs = '\0';
+ /*
+ * RFC 4515 examples
+ * 1 - (cn:caseExactMatch:=Fred Flintstone)
+ * 2 - (cn:=Betty Rubble)
+ * 3 - (sn:dn:2.4.6.8.10:=Barney Rubble)
+ * 4 - (o:dn:=Ace Industry)
+ * 5 - (:1.2.3:=Wilma Flintstone)
+ * 6 - (:DN:2.4.6.8.10:=Dino)
+ */
+ p1 = strchr(p0+1, ':');
+ if (p1) {
+ p2 = strchr(p1+1, ':');
+ }
+ if (p0 == str) {
+ *type = slapi_ch_strdup(""); /* no type */
+ if (p2) {
+ /* example 6 */
+ *p1 = *p2 = '\0';
+ if (strcasecmp(p0+1, "dn") == 0) {
+ *dnAttrs = -1;
+ *oid = slapi_ch_strdup(p1+1);
+ } else {
+ goto error;
+ }
+ } else if (p1) {
+ /* example 5 */
+ *p1 = '\0';
+ if (strcasecmp(p0+1, "dn") == 0) {
+ *dnAttrs = -1;
+ } else {
+ *oid = slapi_ch_strdup(p0+1);
+ }
+ } else {
+ goto error;
+ }
+ } else if (p2) {
+ /* example 3 */
+ *p0 = *p1 = *p2 = '\0';
+ *type = slapi_ch_strdup(str);
+ if (strcasecmp(p0+1, "dn") == 0) {
+ *dnAttrs = -1;
+ *oid = slapi_ch_strdup(p1+1);
+ } else {
+ goto error;
+ }
+ } else if (p1) {
+ *p0 = *p1 = '\0';
+ *type = slapi_ch_strdup(str);
+ if (strcasecmp(p0+1, "dn") == 0) {
+ /* example 4 */
+ *dnAttrs = -1;
+ } else {
+ /* example 1 */
+ *oid = slapi_ch_strdup(p0+1);
+ }
+ } else {
+ /* example 2 */
+ *type = slapi_ch_strdup(str);
+ *p0 = '\0';
+ }
+ if (p1) {
+ *p1 = ':';
+ }
+ if (p2) {
+ *p2 = ':';
+ }
+ return 0;
+
+error:
+ slapi_ch_free_string(type);
+ slapi_ch_free_string(oid);
+ if (p1) {
+ *p1 = ':';
+ }
+ if (p2) {
+ *p2 = ':';
+ }
+ return 1;
+}
+
/*
* The caller unescapes it if unescape_filter == 0.
*/
@@ -234,6 +324,7 @@ str2simple( char *str , int unescape_filter)
f = (struct slapi_filter *) slapi_ch_calloc( 1, sizeof(struct slapi_filter) );
switch ( *s ) {
+ char *extp = NULL;
case '<':
f->f_choice = LDAP_FILTER_LE;
break;
@@ -245,7 +336,17 @@ str2simple( char *str , int unescape_filter)
break;
default:
LDAP_UTF8INC(s);
- if ( str_find_star( value ) == NULL ) {
+ if ((extp = strchr(str, ':')) && (extp < value)) {
+ int rc;
+ char *endp = s; /* '=' */
+ *endp = '\0';
+ rc = _parse_ext_filter(str, extp, &f->f_mr_type, &f->f_mr_oid, &f->f_mr_dnAttrs);
+ if (rc) {
+ return NULL; /* error */
+ } else {
+ f->f_choice = LDAP_FILTER_EXTENDED;
+ }
+ } else if ( str_find_star( value ) == NULL ) {
f->f_choice = LDAP_FILTER_EQUALITY;
} else if ( strcmp( value, "*" ) == 0 ) {
f->f_choice = LDAP_FILTER_PRESENT;
@@ -271,21 +372,23 @@ str2simple( char *str , int unescape_filter)
f->f_type = slapi_ch_strdup( str );
*s = savechar;
} else if ( unescape_filter ) {
- int r;
+ int r;
char *unqstr;
size_t len = strlen(value), len2;
/* dup attr */
savechar = *s;
*s = 0;
- f->f_avtype = slapi_ch_strdup( str );
+ if (f->f_choice != LDAP_FILTER_EXTENDED) {
+ f->f_avtype = slapi_ch_strdup( str );
+ }
*s = savechar;
/* dup value */
savechar = value[len];
value[len] = 0;
unqstr = slapi_ch_calloc( 1, len+1);
- r= filt_unescape_str(value, unqstr, len, &len2, 1);
+ r = filt_unescape_str(value, unqstr, len, &len2, 1);
value[len] = savechar;
if (!r) {
slapi_filter_free(f, 1);
@@ -310,7 +413,9 @@ str2simple( char *str , int unescape_filter)
}
} else if ( !unescape_filter ) {
- f->f_avtype = slapi_ch_strdup( str );
+ if (f->f_choice != LDAP_FILTER_EXTENDED) {
+ f->f_avtype = slapi_ch_strdup( str );
+ }
f->f_avvalue.bv_val = slapi_ch_strdup ( value );
f->f_avvalue.bv_len = strlen ( f->f_avvalue.bv_val );
}
@@ -337,12 +442,12 @@ str2subvals( char *val, struct slapi_filter *f, int unescape_filter )
len = strlen(val);
unqval = slapi_ch_malloc(len+1);
if (!filt_unescape_str(val, unqval, len, &outlen, 0)) {
- slapi_ch_free((void **)&unqval);
- return -1;
+ slapi_ch_free((void **)&unqval);
+ return -1;
}
- unqval[outlen]= '\0';
+ unqval[outlen]= '\0';
} else {
- unqval = slapi_ch_strdup ( val );
+ unqval = slapi_ch_strdup ( val );
}
if (unqval && unqval[0]) {
if (gotstar == 0) {
--
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