]> git.sur5r.net Git - openldap/commitdiff
This patch is for a component filter. please refer ITS#3260 for detail
authorSang Seok Lim <slim@openldap.org>
Thu, 26 Aug 2004 00:06:39 +0000 (00:06 +0000)
committerSang Seok Lim <slim@openldap.org>
Thu, 26 Aug 2004 00:06:39 +0000 (00:06 +0000)
and "implementing GSER and Component Matching" in ODD 2004.
All codes are #ifdef'd with LDAP_COMP_MATCH.
test031-component-filter works correctly only when the LDAP_COMP_MATCH macro is set.
To disable it, set AC_WITH_COMP_MATCH "no" in "openldap_src/tests/run.in".

15 files changed:
include/ldap.h
servers/slapd/Makefile.in
servers/slapd/asn.h [new file with mode: 0644]
servers/slapd/component.c [new file with mode: 0644]
servers/slapd/filterentry.c
servers/slapd/mra.c
servers/slapd/proto-slap.h
servers/slapd/schema/core.schema
servers/slapd/schema_init.c
servers/slapd/slap.h
tests/data/compsearch.out [new file with mode: 0644]
tests/data/test-compmatch.ldif [new file with mode: 0644]
tests/run.in
tests/scripts/defines.sh
tests/scripts/test031-component-filter [new file with mode: 0755]

index 08e6abf2de4d4841f722fd7749a46ef061c24a60..f3a0e51dfd2f56f398f70acf48f3a941093a8854 100644 (file)
@@ -1992,5 +1992,9 @@ ldap_passwordpolicy_err2txt LDAP_P(( LDAPPasswordPolicyError ));
 
 #endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */
 
+#ifdef LDAP_DEVEL
+#define LDAP_COMP_MATCH 1
+#endif
+
 LDAP_END_DECL
 #endif /* _LDAP_H */
index e305e7fc313b1aa06b46f9dfaa8815f0fb39de74..9bfbf006af9888d9ad15cf116c445722ed3145e8 100644 (file)
@@ -37,7 +37,7 @@ SRCS  = main.c globals.c config.c daemon.c \
                backglue.c operational.c matchedValues.c cancel.c syncrepl.c \
                backover.c ctxcsn.c ldapsync.c sessionlog.c frontend.c \
                slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
-               slappasswd.c slaptest.c slapauth.c slapacl.c \
+               slappasswd.c slaptest.c slapauth.c slapacl.c component.c\
                $(@PLAT@_SRCS)
 
 OBJS   = main.o globals.o config.o daemon.o \
@@ -54,7 +54,7 @@ OBJS  = main.o globals.o config.o daemon.o \
                backglue.o operational.o matchedValues.o cancel.o syncrepl.o \
                backover.o ctxcsn.o ldapsync.o sessionlog.o frontend.o \
                slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
-               slappasswd.o slaptest.o slapauth.o slapacl.o \
+               slappasswd.o slaptest.o slapauth.o slapacl.o component.o\
                $(@PLAT@_OBJS)
 
 LDAP_INCDIR= ../../include -I$(srcdir)/slapi
diff --git a/servers/slapd/asn.h b/servers/slapd/asn.h
new file mode 100644 (file)
index 0000000..44439d0
--- /dev/null
@@ -0,0 +1,67 @@
+/* asn.h -- Component Filter Match Routines */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2003-2004 The OpenLDAP Foundation.
+ * Portions Copyright 2004 by IBM Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+#ifdef LDAP_COMP_MATCH
+#include <asn-incl.h>
+
+#define AsnId AsnOcts
+#define NUM_ENCODING_TYPE 2
+
+typedef enum { BER, GSER } EncRulesType;
+typedef enum { ASN_BASIC, ASN_COMPOSITE } AsnType;
+static EncRulesType rulesListG[NUM_ENCODING_TYPE] = { BER, GSER };
+
+typedef enum AsnTypeId {
+       BASICTYPE_BOOLEAN,      /* 1 */
+       BASICTYPE_INTEGER, 
+       BASICTYPE_BITSTRING,
+       BASICTYPE_OCTETSTRING,
+       BASICTYPE_NULL,
+       BASICTYPE_OID,
+       BASICTYPE_REAL,
+       BASICTYPE_ENUMERATED,
+       BASICTYPE_NUMERIC_STR,
+       BASICTYPE_PRINTABLE_STR,
+       BASICTYPE_UNIVERSAL_STR,
+       BASICTYPE_IA5_STR,
+       BASICTYPE_BMP_STR,
+       BASICTYPE_UTF8_STR,
+       BASICTYPE_UTCTIME,
+       BASICTYPE_GENERALIZEDTIME,
+       BASICTYPE_GRAPHIC_STR,
+       BASICTYPE_VISIBLE_STR,
+       BASICTYPE_GENERAL_STR,
+       BASICTYPE_OBJECTDESCRIPTOR,
+       BASICTYPE_VIDEOTEX_STR,
+       BASICTYPE_T61_STR,
+       BASICTYPE_OCTETCONTAINING,
+       BASICTYPE_BITCONTAINING,
+       BASICTYPE_RELATIVE_OID, /* 25 */
+       /* Embedded Composite Types*/
+       COMPOSITE_ASN1_TYPE,
+       /* A New ASN.1 types including type reference */
+       RDNSequence,
+       RelativeDistinguishedName,
+       TelephoneNumber,
+       FacsimileTelephoneNumber_telephoneNumber,
+       DirectoryString,
+       /* Newly Defined ASN.1 Type, Manually registered */
+       ASN_T1,
+       /* ASN.1 Type End */
+       ASNTYPE_END
+} AsnTypeId;
+#endif
diff --git a/servers/slapd/component.c b/servers/slapd/component.c
new file mode 100644 (file)
index 0000000..f2e73f3
--- /dev/null
@@ -0,0 +1,923 @@
+/* component.c -- Component Filter Match Routines */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2003-2004 The OpenLDAP Foundation.
+ * Portions Copyright 2004 by IBM Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+#include "portable.h"
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "ldap_pvt.h"
+#include "lutil.h"
+#include <ldap.h>
+#include "slap.h"
+
+#ifdef LDAP_COMP_MATCH
+
+#include "asn.h"
+
+static int
+peek_componentId_type( ComponentAssertionValue* cav );
+
+static int
+strip_cav_str( ComponentAssertionValue* cav, char* str);
+
+static int
+peek_cav_str( ComponentAssertionValue* cav, char* str );
+
+static int
+parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
+                               ComponentFilter** filt, const char** text );
+
+static int
+test_comp_filter_attr( Operation *op, Attribute        *a, struct berval *bv,
+                       ComponentFilter *f );
+
+int
+componentFilterValidate(
+       Syntax *syntax,
+       struct berval *val )
+{
+       return LDAP_SUCCESS;
+}
+
+int
+componentFilterMatch ( 
+       int *matchp, 
+       slap_mask_t flags, 
+       Syntax *syntax, 
+       MatchingRule *mr,
+       struct berval *value, 
+       void *assertedValue )
+{
+       /* FIXME: to be implemented */
+       *matchp = 0;
+       return LDAP_SUCCESS;
+}
+
+
+static int
+slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav)
+{
+       int len;
+
+       len = ldap_pvt_filter_value_unescape( bv->bv_val );
+       cav->cav_ptr = cav->cav_buf = bv->bv_val;
+       cav->cav_end = bv->bv_val + len;
+}
+
+int
+get_comp_filter ( Operation* op, struct berval* bv, ComponentFilter** filt,
+                                const char **text )
+{
+       ComponentAssertionValue cav;
+       int len, rc;
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY, "get_comp_filter\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
+#endif
+       slapd_ber2cav(bv, &cav);
+       rc = parse_comp_filter( op, &cav, filt, text );
+       bv->bv_val = cav.cav_ptr;
+       return rc;
+}
+
+static void
+eat_whsp( ComponentAssertionValue* cav )
+{
+       int count = 0;
+       for ( ; ; ) {
+               if ( cav->cav_ptr[count++] == ' ' ) cav->cav_ptr++;
+               else break;
+       }
+}
+
+static int
+cav_cur_len( ComponentAssertionValue* cav )
+{
+       return cav->cav_end - cav->cav_ptr;
+}
+
+static ber_tag_t
+comp_first_element( ComponentAssertionValue* cav )
+{
+       eat_whsp( cav );
+       if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
+               return LDAP_COMP_FILTER_ITEM;
+       }
+       else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
+               return LDAP_COMP_FILTER_AND;
+       }
+       else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
+               return LDAP_COMP_FILTER_OR;
+       }
+       else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
+               return LDAP_COMP_FILTER_NOT;
+       }
+       else
+               return LDAP_COMP_FILTER_UNDEFINED;
+}
+
+static ber_tag_t
+comp_next_element( ComponentAssertionValue* cav )
+{
+
+       eat_whsp( cav );
+       if ( *(cav->cav_ptr) == ',' ) {
+               /* move pointer to the next CA */
+               cav->cav_ptr++;
+               return comp_first_element( cav );
+       }
+       else return LDAP_COMP_FILTER_UNDEFINED;
+}
+
+static int
+get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
+                       ComponentFilter** f, const char** text )
+{
+       ComponentFilter **new;
+       int             err;
+       ber_tag_t       tag;
+       ber_len_t       len;
+       char            *last;
+
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY, "get_comp_filter_list\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
+#endif
+       new = f;
+       for ( tag = comp_first_element( cav ); tag != LDAP_COMP_FILTER_UNDEFINED;
+               tag = comp_next_element( cav ) )
+       {
+               err = parse_comp_filter( op, cav, new, text );
+               if ( err != LDAP_SUCCESS )
+                       return ( err );
+               new = &(*new)->cf_next;
+       }
+       *new = NULL;
+
+
+       return( LDAP_SUCCESS );
+}
+
+static int
+get_componentId( Operation *op, ComponentAssertionValue* cav,
+                       ComponentId ** cid, const char** text )
+{
+       ber_tag_t type;
+       ComponentId _cid;
+       int len;
+
+       type = peek_componentId_type( cav );
+
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY, "get_compId [%d]\n", type, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "get_compId [%d]\n", type, 0, 0 );
+#endif
+       len = 0;
+       _cid.ci_type = type;
+       _cid.ci_next = NULL;
+       switch ( type ) {
+       case LDAP_COMPREF_IDENTIFIER :
+               _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
+               for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
+                       cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
+               _cid.ci_val.ci_identifier.bv_len = len;
+               cav->cav_ptr += len;
+               break;
+       case LDAP_COMPREF_FROM_BEGINNING :
+               for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
+                       cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
+               _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
+               cav->cav_ptr += len;
+               break;
+       case LDAP_COMPREF_FROM_END :
+               for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
+                       cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
+               _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
+               cav->cav_ptr += len;
+               break;
+       case LDAP_COMPREF_COUNT :
+               _cid.ci_val.ci_count = 0;
+               cav->cav_ptr++;
+               break;
+       case LDAP_COMPREF_CONTENT :
+               /* FIXEME: yet to be implemented */
+               break;
+       case LDAP_COMPREF_SELECT :
+               /* FIXEME: yet to be implemented */
+               break;
+       case LDAP_COMPREF_ALL :
+               _cid.ci_val.ci_all = '*';
+               cav->cav_ptr++;
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY, "get_compId : ALL\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "get_compId : ALL\n", 0, 0, 0 );
+#endif
+               break;
+       default :
+               return LDAP_COMPREF_UNDEFINED;
+       }
+
+       *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
+       **cid = _cid;
+       return LDAP_SUCCESS;
+}
+
+static int
+peek_componentId_type( ComponentAssertionValue* cav )
+{
+       eat_whsp( cav );
+       if ( cav->cav_ptr[0] == '-' )
+               return LDAP_COMPREF_FROM_END;
+       else if ( cav->cav_ptr[0] == '(' )
+               return LDAP_COMPREF_SELECT;
+       else if ( cav->cav_ptr[0] == '*' )
+               return LDAP_COMPREF_ALL;
+       else if ( cav->cav_ptr[0] == '0' )
+               return LDAP_COMPREF_COUNT;
+       else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' )
+               return LDAP_COMPREF_FROM_BEGINNING;
+       else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
+               strncmp(cav->cav_ptr,"content",7) == 0 )
+               return LDAP_COMPREF_CONTENT;
+       else if ( cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z' )
+               return LDAP_COMPREF_IDENTIFIER;
+       else
+               return LDAP_COMPREF_UNDEFINED;
+}
+
+static ber_tag_t
+comp_next_id( ComponentAssertionValue* cav )
+{
+
+       if ( *(cav->cav_ptr) == '.' ) {
+               cav->cav_ptr++;
+               return LDAP_COMPREF_DEFINED;
+       }
+       else return LDAP_COMPREF_UNDEFINED;
+}
+
+static int
+get_component_reference( Operation *op, ComponentAssertionValue* cav,
+                       ComponentReference** cr, const char** text )
+{
+       int rc,count=0;
+       ber_int_t type;
+       ComponentReference* ca_comp_ref;
+       ComponentId** cr_list;
+
+       eat_whsp( cav );
+       ca_comp_ref =
+               op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
+
+       cr_list = &ca_comp_ref->cr_list;
+       strip_cav_str( cav, "\"");
+       for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
+               ; type = comp_next_id( cav ), count++ ) {
+               rc = get_componentId( op, cav, cr_list, text );
+               if ( rc == LDAP_SUCCESS ) {
+                       if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
+                       cr_list = &(*cr_list)->ci_next;
+               }
+       }
+       ca_comp_ref->cr_len = count;
+       strip_cav_str( cav, "\"");
+
+       if ( rc == LDAP_SUCCESS ) {     
+               *cr = ca_comp_ref;
+               **cr = *ca_comp_ref;    
+       }
+       else op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
+
+       return rc;
+}
+
+static int
+get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
+               int* ca_use_def, const char**  text )
+{
+       int rc;
+       if ( peek_cav_str( cav, "useDefaultValues" ) == LDAP_SUCCESS ) {
+               strip_cav_str( cav, "useDefaultValues" );
+               if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
+                       strip_cav_str( cav, "TRUE" );
+                       *ca_use_def = 1;
+               }
+               else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
+                       strip_cav_str( cav, "FALSE" );
+                       *ca_use_def = 0;
+               }
+               else
+                       return LDAP_INVALID_SYNTAX;
+       }
+       else /* If not defined, default value is TRUE */
+               *ca_use_def = 1;
+       return LDAP_SUCCESS;
+}
+
+static int
+get_matching_rule( Operation *op, ComponentAssertionValue* cav,
+               MatchingRule** mr, const char**  text )
+{
+       int count = 0;
+       char temp;
+       struct berval rule_text = { 0L, NULL };
+
+       eat_whsp( cav );
+
+       for ( ; ; count++ ) {
+               if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
+                       cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
+                       cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
+                       break;
+       }
+
+       if ( count == 0 ) {
+               *text = "component matching rule not recognized";
+               return LDAP_INAPPROPRIATE_MATCHING;
+       }
+       
+       rule_text.bv_len = count;
+       rule_text.bv_val = cav->cav_ptr;
+       *mr = mr_bvfind( &rule_text );
+       cav->cav_ptr += count;
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY,  "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
+#endif
+       if ( *mr == NULL ) {
+               *text = "component matching rule not recognized";
+               return LDAP_INAPPROPRIATE_MATCHING;
+       }
+       return LDAP_SUCCESS;
+}
+
+static void
+get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
+{
+       int count;
+
+       eat_whsp( cav );
+       /*
+        * Four cases of GSER <Values>
+        * 1) "..." :
+        *      StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
+        * 2) '...'B or '...'H :
+        *      BitStringVal, OctetStringVal
+        * 3) {...} :
+        *      SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
+        * 4) Between two white spaces
+        *      INTEGER, BOOLEAN, NULL,ENUMERATE, etc
+        */
+
+       if ( cav->cav_ptr[0] == '"' ) {
+               for( count = 0 ; ; count++ ) {
+                       if ( cav->cav_ptr[count] == '\0' ||
+                       ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') )
+                               break;
+               }
+       }
+       else if ( cav->cav_ptr[0] == '\'' ) {
+               for( count = 0 ; ; count++ ) {
+                       if ( cav->cav_ptr[count] == '\0' ||
+                       (cav->cav_ptr[count] == '\'' && cav->cav_ptr[count] == 'B')||
+                       (cav->cav_ptr[count] == '\'' && cav->cav_ptr[count] == 'H') )
+                               break;
+               }
+                               
+       }
+       else if ( cav->cav_ptr[0] == '{' ) {
+               for( count = 0 ; ; count++ ) {
+                       if ( cav->cav_ptr[count] == '\0' ||
+                       (cav->cav_ptr[count] == '}' && cav->cav_ptr[count] == ' ') )
+                               break;
+               }
+       }
+       else {
+               for( count = 0 ; ; count++ ) {
+                       if ( cav->cav_ptr[count] == ' ')
+                               break;
+               }
+       }
+
+       bv->bv_val = cav->cav_ptr;
+       bv->bv_len = count;
+       cav->cav_ptr += count;
+}
+
+static int
+get_matching_value( Operation *op, ComponentAssertion* ca,
+                       ComponentAssertionValue* cav, struct berval* bv,
+                       const char**  text )
+{
+       int count;
+       ber_tag_t tag;
+
+       if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
+               get_GSER_value( cav, bv );
+       }
+       else {
+               /* embeded componentFilterMatch Description */
+               bv->bv_val = cav->cav_ptr;
+               bv->bv_len = cav_cur_len( cav );
+       }
+
+       return LDAP_SUCCESS;
+}
+
+/* Don't move the position pointer, just peek given string */
+static int
+peek_cav_str( ComponentAssertionValue* cav, char* str )
+{
+       eat_whsp( cav );
+       if ( cav_cur_len( cav ) >= strlen( str ) &&
+               strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
+               return LDAP_SUCCESS;
+       else 
+               return LDAP_INVALID_SYNTAX;
+}
+
+static int
+strip_cav_str( ComponentAssertionValue* cav, char* str)
+{
+       eat_whsp( cav );
+       if ( cav_cur_len( cav ) >= strlen( str ) &&
+               strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) {
+               cav->cav_ptr += strlen( str );
+               return LDAP_SUCCESS;
+       }
+       else 
+               return LDAP_INVALID_SYNTAX;
+}
+
+/*
+ * TAG : "item", "and", "or", "not"
+ */
+static int
+strip_cav_tag( ComponentAssertionValue* cav )
+{
+
+       eat_whsp( cav );
+       if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
+               strip_cav_str( cav , "item:" );
+               return LDAP_COMP_FILTER_ITEM;
+       }
+       else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
+               strip_cav_str( cav , "and:" );
+               return LDAP_COMP_FILTER_AND;
+       }
+       else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
+               strip_cav_str( cav , "or:" );
+               return LDAP_COMP_FILTER_OR;
+       }
+       else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
+               strip_cav_str( cav , "not:" );
+               return LDAP_COMP_FILTER_NOT;
+       }
+       else
+               return LBER_ERROR;
+}
+
+/*
+ * when encoding, "item" is denotation of ComponentAssertion
+ * ComponentAssertion :: SEQUENCE {
+ *     component               ComponentReference (SIZE(1..MAX)) OPTIONAL,
+ *     useDefaultValues        BOOLEAN DEFAULT TRUE,
+ *     rule                    MATCHING-RULE.&id,
+ *     value                   MATCHING-RULE.&AssertionType }
+ */
+static int
+get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
+               const char** text )
+{
+       int rc;
+       ComponentAssertion* _ca;
+
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY,  "get_item: %s\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "get_item: %s\n", 0, 0, 0 );
+#endif
+       _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
+
+       rc = peek_cav_str( cav, "component" );
+       if ( rc == LDAP_SUCCESS ) {
+               strip_cav_str( cav, "component" );
+               rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
+               if ( rc != LDAP_SUCCESS ) {
+                       rc = LDAP_INVALID_SYNTAX;
+                       op->o_tmpfree( _ca, op->o_tmpmemctx );
+                       return rc;
+               }
+       }
+
+       strip_cav_str( cav,",");
+       rc = peek_cav_str( cav, "useDefaultValues");
+       if ( rc == LDAP_SUCCESS ) {
+               rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
+               if ( rc != LDAP_SUCCESS ) {
+                       rc = LDAP_INVALID_SYNTAX;
+                       op->o_tmpfree( _ca, op->o_tmpmemctx );
+                       return rc;
+               }
+       }
+
+       if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
+               get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
+               rc = LDAP_INAPPROPRIATE_MATCHING;
+               op->o_tmpfree( _ca, op->o_tmpmemctx );
+               return rc;
+       }
+       
+       strip_cav_str( cav,",");
+       if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
+               get_matching_value( op, _ca, cav, &_ca->ca_ma_value,text ) == LDAP_SUCCESS )) {
+               rc = LDAP_INVALID_SYNTAX;
+               op->o_tmpfree( _ca, op->o_tmpmemctx );
+               return rc;
+       }
+
+       /* componentFilterMatch contains componentFilterMatch in it */
+       if ( _ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT) ) {
+               struct berval bv;
+               bv.bv_val = cav->cav_ptr;
+               bv.bv_len = cav_cur_len( cav );
+               rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
+               if ( rc != LDAP_SUCCESS ) {
+                       op->o_tmpfree( _ca, op->o_tmpmemctx );
+                       return rc;
+               }
+               cav->cav_ptr = bv.bv_val;
+               assert( cav->cav_end >= bv.bv_val );
+       }
+
+       *ca = _ca;
+       return LDAP_SUCCESS;
+}
+
+static int
+parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
+                               ComponentFilter** filt, const char** text )
+{
+       /*
+        * A component filter looks like this coming in:
+        *      Filter ::= CHOICE {
+        *              item    [0]     ComponentAssertion,
+        *              and     [1]     SEQUENCE OF ComponentFilter,
+        *              or      [2]     SEQUENCE OF ComponentFilter,
+        *              not     [3]     ComponentFilter,
+        *      }
+        */
+
+       ber_tag_t       tag;
+       ber_len_t       len;
+       int             err;
+       ComponentFilter f;
+       /* TAG : item, and, or, not in RFC 2254 */
+       tag = strip_cav_tag( cav );
+
+       if ( tag == LBER_ERROR ) {
+               *text = "error decoding comp filter";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( tag != LDAP_COMP_FILTER_NOT )
+               strip_cav_str( cav, "{");
+
+       err = LDAP_SUCCESS;
+
+       f.cf_next = NULL;
+       f.cf_choice = tag; 
+
+       switch ( f.cf_choice ) {
+       case LDAP_COMP_FILTER_AND:
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY,  "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
+#endif
+               err = get_comp_filter_list( op, cav, &f.cf_and, text );
+               if ( err != LDAP_SUCCESS ) {
+                       break;
+               }
+               if ( f.cf_and == NULL ) {
+                       f.cf_choice = SLAPD_FILTER_COMPUTED;
+                       f.cf_result = LDAP_COMPARE_TRUE;
+               }
+               break;
+
+       case LDAP_COMP_FILTER_OR:
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY,  "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
+#endif
+               err = get_comp_filter_list( op, cav, &f.cf_or, text );
+               if ( err != LDAP_SUCCESS ) {
+                       break;
+               }
+               if ( f.cf_or == NULL ) {
+                       f.cf_choice = SLAPD_FILTER_COMPUTED;
+                       f.cf_result = LDAP_COMPARE_FALSE;
+               }
+               /* no assert - list could be empty */
+               break;
+
+       case LDAP_COMP_FILTER_NOT:
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY,  "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
+#endif
+               err = parse_comp_filter( op, cav, &f.cf_not, text );
+               if ( err != LDAP_SUCCESS ) {
+                       break;
+               }
+
+               assert( f.cf_not != NULL );
+               if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
+                       int fresult = f.cf_not->cf_result;
+                       f.cf_choice = SLAPD_FILTER_COMPUTED;
+                       op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
+                       f.cf_not = NULL;
+
+                       switch ( fresult ) {
+                       case LDAP_COMPARE_TRUE:
+                               f.cf_result = LDAP_COMPARE_FALSE;
+                               break;
+                       case LDAP_COMPARE_FALSE:
+                               f.cf_result = LDAP_COMPARE_TRUE;
+                               break;
+                       default: ;
+                               /* (!Undefined) is Undefined */
+                       }
+               }
+               break;
+
+       case LDAP_COMP_FILTER_ITEM:
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY,  "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
+#endif
+               err = get_item( op, cav, &f.cf_ca, text );
+               if ( err != LDAP_SUCCESS ) {
+                       break;
+               }
+
+               assert( f.cf_ca != NULL );
+               break;
+
+       default:
+               f.cf_choice = SLAPD_FILTER_COMPUTED;
+               f.cf_result = SLAPD_COMPARE_UNDEFINED;
+               break;
+       }
+
+       if ( tag != LDAP_COMP_FILTER_NOT )
+               strip_cav_str( cav, "}");
+
+       if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
+               *text = NULL;
+               f.cf_choice = SLAPD_FILTER_COMPUTED;
+               f.cf_result = SLAPD_COMPARE_UNDEFINED;
+               err = LDAP_SUCCESS;
+       }
+
+       if ( err == LDAP_SUCCESS ) {
+               *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
+               **filt = f;
+       }
+
+       return( err );
+}
+
+static int
+test_comp_filter_and(
+       Operation *op,
+       Attribute *a,
+       struct berval  *bv,
+       ComponentFilter *flist )
+{
+       ComponentFilter *f;
+       int rtn = LDAP_COMPARE_TRUE;
+
+       for ( f = flist ; f != NULL; f = f->cf_next ) {
+               int rc = test_comp_filter_attr( op, a, bv, f );
+               if ( rc == LDAP_COMPARE_FALSE ) {
+                       rtn = rc;
+                       break;
+               }
+       
+               if ( rc != LDAP_COMPARE_TRUE ) {
+                       rtn = rc;
+               }
+       }
+
+       return rtn;
+}
+
+static int
+test_comp_filter_or(
+       Operation *op,
+       Attribute *a,
+       struct berval     *bv,
+       ComponentFilter *flist )
+{
+       ComponentFilter *f;
+       int rtn = LDAP_COMPARE_TRUE;
+
+       for ( f = flist ; f != NULL; f = f->cf_next ) {
+               int rc = test_comp_filter_attr( op, a, bv, f );
+               if ( rc == LDAP_COMPARE_TRUE ) {
+                       rtn = rc;
+                       break;
+               }
+       
+               if ( rc != LDAP_COMPARE_FALSE ) {
+                       rtn = rc;
+               }
+       }
+
+       return rtn;
+}
+
+/*
+ * Convert attribute value to C internal data structure
+ * This function has an associated ASN.1 type
+ * bv must contain the value for the type( type name is T1 )
+ * This function is linked to ssyn_attr2comp
+ */
+
+/*
+ * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
+ */
+static int
+test_comp_filter_item(
+       Operation       *op,
+       Attribute       *a,
+       struct berval   *bv,
+       ComponentAssertion *ca )
+{
+       int rc = LDAP_COMPARE_TRUE;
+       int len;
+       ComponentSyntaxInfo* csi_attr, *csi_assert;
+       GenBuf* genBuf;
+       ExpBuf* buf;
+
+       if ( (ca->ca_ma_rule->smr_usage & SLAP_MR_COMPONENT) && ca->ca_cf ) {
+               /* componentFilterMatch inside of componentFilterMatch */
+               rc = test_comp_filter_attr( op, a, bv, ca->ca_cf );
+               return rc;
+       }
+
+       assert( !(ca->ca_ma_rule->smr_usage & SLAP_MR_COMPONENT) );
+       /* FIXME : Return ALWAYS true */
+       return LDAP_COMPARE_TRUE;
+}
+
+/*
+ * If matched, LDAP_COMPARE_TRUE is returned
+ */
+int
+test_comp_filter_entry(
+    Operation  *op,
+    Entry      *e,
+    MatchingRuleAssertion *mra )
+{
+       Attribute *a;
+       void    *memctx;
+
+       mra->cf->cf_ca->ca_mra = mra;
+
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY,  "test_comp_filter_entry\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "test_comp_filter_entry\n", 0, 0, 0 );
+#endif
+       if ( mra->ma_desc ) {
+               /*
+                * ma_desc is available, so filtering for one attribute
+                * SEARCH permissionc can be checked directly
+                */
+               if ( !access_allowed( op, e, mra->ma_desc,
+                       &mra->ma_value, ACL_SEARCH, NULL ) )
+               {
+                       return LDAP_INSUFFICIENT_ACCESS;
+               }
+               /* Find attributes that componentFilter Match can be applied to */
+               for( a=attrs_find( e->e_attrs, mra->ma_desc );
+                       a != NULL ;
+                       a = attrs_find( a->a_next, mra->ma_desc ) )
+               {
+                       struct berval *bv = a->a_vals;
+
+                       for ( ; bv->bv_val != NULL ; bv++ ) {
+                               int ret, rc;
+                               const char *text;
+                               rc = test_comp_filter_attr( op, a, bv, mra->cf );
+                               if ( rc == LDAP_COMPARE_TRUE ) return rc;
+                       }
+               }
+
+       } else {
+               /*
+                * No attribute description : test all
+                */
+                for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
+                        struct berval   *bv, value;
+                        const char      *text = NULL;
+                        int             rc;
+                                                                                  
+                        /* check if matching is appropriate */
+                        if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type
+)) {
+                                continue;
+                        }
+                                                                                  
+                        /* check search access */
+                        if ( !access_allowed( op, e,
+                                a->a_desc, &value, ACL_SEARCH, NULL ) ) {
+                                continue;
+                        }
+                                                                                  
+                       bv = a->a_vals;
+
+                       for ( ; bv->bv_val != NULL ; bv++ ) {
+                               int ret, rc;
+                               const char *text;
+                               rc = test_comp_filter_attr( op, a, bv, mra->cf );
+                               if ( rc == LDAP_COMPARE_TRUE ) break;
+                       }
+                        if ( rc != LDAP_SUCCESS ) return rc;
+                }
+       }
+
+       return LDAP_COMPARE_FALSE;
+}
+
+static int
+test_comp_filter_attr(
+    Operation  *op,
+    Attribute  *a,
+    struct berval *bv,
+    ComponentFilter *f )
+{
+       int     rc;
+
+#ifdef NEW_LOGGING
+       LDAP_LOG( FILTER, ENTRY,  "test_comp_filter_attr\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_FILTER, "test_comp_filter_attr\n", 0, 0, 0 );
+#endif
+       switch ( f->cf_choice ) {
+       case SLAPD_FILTER_COMPUTED:
+               rc = f->cf_result;
+               break;
+       case LDAP_COMP_FILTER_AND:
+               rc = test_comp_filter_and( op, a, bv, f->cf_and );
+               break;
+       case LDAP_COMP_FILTER_OR:
+               rc = test_comp_filter_or( op, a, bv, f->cf_or );
+               break;
+       case LDAP_COMP_FILTER_NOT:
+               rc = test_comp_filter_attr( op, a, bv, f->cf_not );
+
+               switch ( rc ) {
+               case LDAP_COMPARE_TRUE:
+                       rc = LDAP_COMPARE_FALSE;
+                       break;
+               case LDAP_COMPARE_FALSE:
+                       rc = LDAP_COMPARE_TRUE;
+                       break;
+               }
+               break;
+       case LDAP_COMP_FILTER_ITEM:
+               rc = test_comp_filter_item( op, a, bv, f->cf_ca );
+               break;
+       default:
+               rc = LDAP_PROTOCOL_ERROR;
+       }
+
+       return( rc );
+}
+#endif
index ceba658ced0deb0379df1214f636862f8370100d..8f9c34539d06d692c48909c9d271a017fa4bbcf2 100644 (file)
@@ -214,6 +214,13 @@ static int test_mra_filter(
                memfree = op->o_tmpfree;
        }
 
+#ifdef LDAP_COMP_MATCH
+       /* Component Matching */
+       if( mra->cf &&
+               mra->ma_rule->smr_usage & (SLAP_MR_COMPONENT) ){
+               return test_comp_filter_entry( op, e, mra );
+       }
+#endif
        if ( mra->ma_desc ) {
                /*
                 * if ma_desc is available, then we're filtering for
index 1e7a7e63782af0f8d48e586741c2a0938147aa81..1cb4e69f3fd046e63dba38ec2d6ef0a61fcbe3f4 100644 (file)
@@ -223,6 +223,13 @@ get_mra(
                return rc;
        }
 
+#ifdef LDAP_COMP_MATCH
+       /* Matching Rule for Component Matching */
+       Debug( LDAP_DEBUG_FILTER, "matchingrule %s\n",ma.ma_rule->smr_mrule.mr_oid,0,0);
+       if( ma.ma_rule && ma.ma_rule->smr_usage & SLAP_MR_COMPONENT )
+               rc = get_comp_filter( op, &ma.ma_value, &ma.cf, text );
+               if ( rc != LDAP_SUCCESS ) return rc;
+#endif
        length = sizeof(ma);
        /* Append rule_text to end of struct */
        if (rule_text.bv_val) length += rule_text.bv_len + 1;
index 7e1c79d99ccff5fcd80f5c301cc003aef813be5e..d9684e4d15e1468fdf31c8f0e9f2576401cabcf3 100644 (file)
@@ -313,6 +313,34 @@ LDAP_SLAPD_F (void) ch_free LDAP_P(( void * ));
 #define free ch_free
 #endif
 
+/*
+ * component.c
+ */
+#ifdef LDAP_COMP_MATCH
+LDAP_SLAPD_F (int) test_comp_filter_entry LDAP_P((
+       Operation* op,
+       Entry* e,
+       MatchingRuleAssertion* mr));
+
+LDAP_SLAPD_F (int) get_comp_filter LDAP_P((
+       Operation* op,
+       BerValue* bv,
+       ComponentFilter** filt,
+       const char **text ));
+
+LDAP_SLAPD_F (int) componentFilterMatch LDAP_P(( 
+       int *matchp, 
+       slap_mask_t flags, 
+       Syntax *syntax, 
+       MatchingRule *mr,
+       struct berval *value, 
+       void *assertedValue ));
+
+LDAP_SLAPD_F (int) componentFilterValidate LDAP_P(( 
+       Syntax *syntax,
+       struct berval* bv ));
+#endif
+
 /*
  * controls.c
  */
@@ -486,6 +514,7 @@ LDAP_SLAPD_F (int) rdnMatch LDAP_P((
        struct berval *value, 
        void *assertedValue ));
 
+
 LDAP_SLAPD_F (int) dnIsSuffix LDAP_P((
        const struct berval *dn, const struct berval *suffix ));
 
index 9bd1d72df15dadbf1559c861f3eb7ac44b6882ab..b336dc51f9577185779712116ff9b8b9dd343411 100644 (file)
@@ -255,6 +255,12 @@ attributetype ( 2.5.4.37 NAME 'cACertificate'
        EQUALITY certificateExactMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
 
+# Component Filter Testing
+attributetype ( 1.3.6.1.4.1.4203.666.1.33 NAME 'componentTest'
+       DESC 'RFC3687 Component Matching , use ;gser'
+       EQUALITY componentFilterMatch 
+       SYNTAX 1.2.36.79672281.1.5.2 )
+
 # Must be transferred using ;binary
 attributetype ( 2.5.4.38 NAME 'authorityRevocationList'
        DESC 'RFC2256: X.509 authority revocation list, use ;binary'
@@ -366,7 +372,7 @@ objectclass ( 2.5.6.4 NAME 'organization'
        MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
                x121Address $ registeredAddress $ destinationIndicator $
                preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
-               telephoneNumber $ internationaliSDNNumber $
+               telephoneNumber $ internationaliSDNNumber $ 
                facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
                postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
 
@@ -385,7 +391,7 @@ objectclass ( 2.5.6.6 NAME 'person'
        DESC 'RFC2256: a person'
        SUP top STRUCTURAL
        MUST ( sn $ cn )
-       MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
+       MAY ( userPassword $ telephoneNumber $ seeAlso $ description $componentTest ) )
 
 objectclass ( 2.5.6.7 NAME 'organizationalPerson'
        DESC 'RFC2256: an organizational person'
index 1e01e72413677452e4b2893285d4815a91b6ef0d..b91d0cfdf9d89799ad6ab9f1f32f2db14aed2762 100644 (file)
@@ -3031,10 +3031,12 @@ static slap_syntax_defs_rec syntax_defs[] = {
                0, countryStringValidate, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
                0, dnValidate, dnPretty},
-
        {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
                0, rdnValidate, rdnPretty},
-
+#ifdef LDAP_COMP_MATCH
+       {"( 1.2.36.79672281.1.5.2 DESC 'ComponentFilter' )",
+               0, componentFilterValidate, NULL},
+#endif
        {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
                0, NULL, NULL},
        {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
@@ -3240,6 +3242,7 @@ static slap_mrule_defs_rec mrule_defs[] = {
                NULL, dnNormalize, dnMatch,
                octetStringIndexer, octetStringFilter,
                NULL },
+
        {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
                "SYNTAX 1.2.36.79672281.1.5.0 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
@@ -3247,6 +3250,15 @@ static slap_mrule_defs_rec mrule_defs[] = {
                octetStringIndexer, octetStringFilter,
                NULL },
 
+#ifdef LDAP_COMP_MATCH
+       {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
+               "SYNTAX 1.2.36.79672281.1.5.2 )",
+               SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
+               NULL, NULL , componentFilterMatch,
+               octetStringIndexer, octetStringFilter,
+               NULL },
+#endif
+
        {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
                "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
                SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
index 138622e14d3d32a4d94b8a12f03a75ee05a835a6..a309bf324bea25dfa43dbfe938282ddb60e9b052 100644 (file)
@@ -56,6 +56,7 @@
 #include "ldap_queue.h"
 
 LDAP_BEGIN_DECL
+
 /*
  * SLAPD Memory allocation macros
  *
@@ -330,6 +331,11 @@ typedef int slap_syntax_transform_func LDAP_P((
        struct berval * out,
        void *memctx));
 
+#ifdef LDAP_COMP_MATCH
+typedef void* slap_component_transform_func LDAP_P((
+       struct berval * in ));
+struct ComponentDesc;
+#endif
 typedef struct slap_syntax {
        LDAPSyntax                      ssyn_syn;
 #define ssyn_oid               ssyn_syn.syn_oid
@@ -366,6 +372,10 @@ typedef struct slap_syntax {
        slap_syntax_transform_func      *ssyn_ber2str;
        slap_syntax_transform_func      *ssyn_str2ber;
 #endif
+#ifdef LDAP_COMP_MATCH
+       slap_component_transform_func *ssyn_attr2comp;
+       struct ComponentDesc* comp_syntax;
+#endif
 
        LDAP_SLIST_ENTRY(slap_syntax) ssyn_next;
 } Syntax;
@@ -468,6 +478,9 @@ typedef struct slap_matching_rule {
 #define SLAP_MR_ORDERING               0x0200U
 #define SLAP_MR_SUBSTR                 0x0400U
 #define SLAP_MR_EXT                            0x0800U /* implicitly extensible */
+#ifdef LDAP_COMP_MATCH
+#define SLAP_MR_COMPONENT              0x1000U
+#endif
 
 #define SLAP_MR_EQUALITY_APPROX        ( SLAP_MR_EQUALITY | 0x0010U )
 
@@ -886,12 +899,19 @@ typedef struct slap_ss_assertion {
        struct berval           sa_final;
 } SubstringsAssertion;
 
+#ifdef LDAP_COMP_MATCH
+struct slap_component_filter;
+#endif
+
 typedef struct slap_mr_assertion {
        MatchingRule            *ma_rule;       /* optional */
        struct berval           ma_rule_text;  /* optional */
        AttributeDescription    *ma_desc;       /* optional */
        int                                             ma_dnattrs; /* boolean */
        struct berval           ma_value;       /* required */
+#ifdef LDAP_COMP_MATCH
+       struct slap_component_filter* cf;
+#endif
 } MatchingRuleAssertion;
 
 /*
@@ -1016,6 +1036,9 @@ typedef struct slap_attr {
        unsigned a_flags;
 #define SLAP_ATTR_IXADD                0x1U
 #define SLAP_ATTR_IXDEL                0x2U
+#ifdef LDAP_COMP_MATCH
+       void* component_values;
+#endif
 } Attribute;
 
 
@@ -2436,6 +2459,156 @@ typedef int (SLAP_CTRL_PARSE_FN) LDAP_P((
 #define SLAP_AUTH_REWRITE      1
 #endif /* LDAP_DEVEL && ENABLE_REWRITE */
 
+#ifdef LDAP_COMP_MATCH
+/*
+ * Extensible Filter Definition
+ *
+ * MatchingRuleAssertion := SEQUENCE {
+ *     matchingRule    [1] MatchingRuleId OPTIONAL,
+ *     type            [2] AttributeDescription OPTIONAL,
+ *     matchValue      [3] AssertionValue,
+ *     dnAttributes    [4] BOOLEAN DEFAULT FALSE }
+ *
+ * Following ComponentFilter is contained in matchValue
+ *
+ * ComponentAssertion ::= SEQUENCE {
+ *     component               ComponentReference (SIZE(1..MAX)) OPTIONAL
+ *     useDefaultValues        BOOLEAN DEFAULT TRUE,
+ *     rule                    MATCHING-RULE.&id,
+ *     value                   MATCHING-RULE.&AssertionType }
+ *
+ * ComponentFilter ::= CHOICE {
+ *     item    [0] ComponentAssertion,
+ *     and     [1] SEQUENCE OF ComponentFilter,
+ *     or      [2] SEQUENCE OF ComponentFilter,
+ *     not     [3] ComponentFilter }
+ */
+
+#define LDAP_COMPREF_IDENTIFIER                ((ber_tag_t) 0x80U)
+#define LDAP_COMPREF_FROM_BEGINNING    ((ber_tag_t) 0x81U)
+#define LDAP_COMPREF_COUNT             ((ber_tag_t) 0x82U)
+#define LDAP_COMPREF_FROM_END          ((ber_tag_t) 0x83U)
+#define LDAP_COMPREF_CONTENT           ((ber_tag_t) 0x84U)
+#define LDAP_COMPREF_SELECT            ((ber_tag_t) 0x85U)
+#define LDAP_COMPREF_ALL               ((ber_tag_t) 0x86U)
+#define LDAP_COMPREF_DEFINED           ((ber_tag_t) 0x87U)
+#define LDAP_COMPREF_UNDEFINED         ((ber_tag_t) 0x88U)
+
+#define LDAP_COMP_FILTER_AND           ((ber_tag_t) 0xa0U)
+#define LDAP_COMP_FILTER_OR            ((ber_tag_t) 0xa1U)
+#define LDAP_COMP_FILTER_NOT           ((ber_tag_t) 0xa2U)
+#define LDAP_COMP_FILTER_ITEM          ((ber_tag_t) 0xa3U)
+#define LDAP_COMP_FILTER_UNDEFINED     ((ber_tag_t) 0xa4U)
+
+typedef struct slap_component_id{
+       int     ci_type;
+       struct slap_component_id *ci_next;
+
+       union comp_id_value{
+               BerValue        ci_identifier;
+               ber_int_t       ci_from_beginning;
+               ber_int_t       ci_count;
+               ber_int_t       ci_from_end;
+               BerValue        ci_select_value;
+               char            ci_all;
+       } ci_val;
+} ComponentId;
+
+typedef struct slap_component_reference {
+       ComponentId     *cr_list;
+       ComponentId     *cr_curr;
+       struct berval   cr_string;
+       int cr_len;
+} ComponentReference;
+
+typedef struct slap_component_assertion {
+       ComponentReference      *ca_comp_ref;
+       ber_int_t               ca_use_def;
+       MatchingRule            *ca_ma_rule;
+       struct berval           ca_ma_value;
+       struct slap_component_filter    *ca_cf;
+       MatchingRuleAssertion   *ca_mra;
+} ComponentAssertion;
+
+typedef struct slap_component_filter {
+       ber_tag_t cf_choice;
+       union cf_un_u {
+               ber_int_t cf_un_result;
+               ComponentAssertion *cf_un_ca;
+               struct slap_component_filter *cf_un_complex;
+       } cf_un;
+
+#define cf_ca          cf_un.cf_un_ca
+#define cf_result      cf_un.cf_un_result
+#define cf_and         cf_un.cf_un_complex
+#define cf_or          cf_un.cf_un_complex
+#define cf_not         cf_un.cf_un_complex
+       
+       struct slap_component_filter *cf_next;
+} ComponentFilter;
+
+typedef struct slap_component_assertion_value {
+       char* cav_buf;
+       char* cav_ptr;
+       char* cav_end;
+} ComponentAssertionValue;
+
+#include "asn.h"
+
+typedef int encoder_func LDAP_P((
+       GenBuf* b,
+       void* comp));
+
+struct slap_component_syntax_info;
+
+typedef int decoder_func LDAP_P((
+       GenBuf* b,
+       struct slap_component_syntax_info** comp_syn_info,
+       unsigned int* len,
+       int mode));
+
+typedef void* extract_component_from_tag_func LDAP_P((
+       int *tag));
+
+typedef void* extract_component_from_id_func LDAP_P((
+       ComponentReference* cr,
+       void* comp ));
+
+typedef int allcomponent_matching_func LDAP_P((
+       char* oid,
+       void* component1,
+       void* component2 ));
+
+typedef struct slap_component_desc{
+       int             cd_tag;
+       ComponentId*    cd_identifier;
+       encoder_func    *cd_encoder;
+       decoder_func    *cd_decoder;
+       extract_component_from_tag_func* cd_extract_t;
+       extract_component_from_id_func*  cd_extract_i;
+       AsnType         cd_type;
+       AsnTypeId       cd_type_id;
+       allcomponent_matching_func*     cd_all_match;
+} ComponentDesc;
+
+typedef struct slap_component_syntax_info {
+       Syntax* csi_syntax;
+       ComponentDesc* csi_comp_desc;
+} ComponentSyntaxInfo;
+
+typedef struct asntype_to_matchingrule {
+       AsnTypeId       atmr_typeId;
+       char*           atmr_mr_name;
+       MatchingRule    *atmr_mr;
+} AsnTypetoMatchingRule;
+
+typedef struct asntype_to_matchingrule_table {
+       char* atmr_oid;
+       struct asntype_to_matchingrule atmr_table[ASNTYPE_END];
+       struct asntype_to_matchingrule_table* atmr_table_next;
+} AsnTypetoMatchingRuleTable;
+
+#endif
 LDAP_END_DECL
 
 #include "proto-slap.h"
diff --git a/tests/data/compsearch.out b/tests/data/compsearch.out
new file mode 100644 (file)
index 0000000..4e1cf2e
--- /dev/null
@@ -0,0 +1,128 @@
+dn: cn=sangseoklim,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: sangseoklim
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+componentTest: component1
+
+dn: cn=seotaejee,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: seotaejee
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+componentTest: component2
+
+dn: cn=sangseoklim,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: sangseoklim
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+componentTest: component1
+
+dn: cn=seotaejee,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: seotaejee
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+componentTest: component2
+
+dn: cn=sangseoklim,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: sangseoklim
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+componentTest: component1
+
+dn: cn=seotaejee,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: seotaejee
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+componentTest: component2
+
+dn: cn=sangseoklim,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: sangseoklim
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+componentTest: component1
+
+dn: cn=seotaejee,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: seotaejee
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homePhone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimileTelephoneNumber: +1 313 555 9700
+telephoneNumber: +1 313 555 5331
+componentTest: component2
+
diff --git a/tests/data/test-compmatch.ldif b/tests/data/test-compmatch.ldif
new file mode 100644 (file)
index 0000000..2ee54db
--- /dev/null
@@ -0,0 +1,428 @@
+#LEAD COMMENT
+dn: dc=example,dc=com
+#EMBEDDED COMMENT
+objectclass: top
+objectclass: organization
+objectclass: domainRelatedObject
+objectclass: dcobject
+dc: example
+l: Anytown, Michigan
+st: Michigan
+o: Example, Inc.
+o: EX
+o: Ex.
+description: The Example, Inc. at Anytown
+postaladdress: Example, Inc. $ 535 W. William St. $ Anytown, MI 48109 $ US
+telephonenumber: +1 313 764-1817
+associateddomain: example.com
+
+dn: ou=People,dc=example,dc=com
+objectclass: organizationalUnit
+objectclass: extensibleObject
+ou: People
+uidNumber: 0
+gidNumber: 0
+
+dn: ou=Groups,dc=example,dc=com
+objectclass: organizationalUnit
+ou: Groups
+
+dn: ou=Alumni Association,ou=People,dc=example,dc=com
+objectclass: organizationalUnit
+ou: Alumni Association
+
+dn: ou=Information Technology Division,ou=People,dc=example,dc=com
+objectclass: organizationalUnit
+ou: Information Technology Division
+description:: aMODwoPDgsKCw4PCgsOCwotFVlZQw4PCg8OCwoPDg8KCw4LCv0zDg8KDw4LCgsOD
+ woLDgsKKT8ODwoPDgsKDw4PCgsOCwqs6w4PCg8OCwoLDg8KCw4LCjUQkw4PCg8OCwoLDg8KCw4LCi
+ 01QUcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoLDg8KCw4LCik/Dg8KDw4
+ LCgsODwoLDgsKLRCQoZitEJMODwoPDgsKCw4PCgsOCwrfDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoP
+ Dg8KCw4LCgcODwoPDgsKDw4PCgsOCwqHDg8KDw4LCgsODwoLDgsKLRCQkZitEJMODwoPDgsKCw4PC
+ gsOCwrfDg8KDw4LCg8ODwoLDgsKQw4PCg8OCwoPDg8KCw4LCisODwoPDgsKCw4PCgsOCwotFUVZqU
+ MODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKAw4PCg8OCwoLDg8KCw4LCik85dCTDg8KDw4
+ LCgsODwoLDgsKFQ8ODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4L
+ Cvzl0JMODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoPD
+ gsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKLRCTDg8KDw4LCgsODwoLDgsKDw4PCg8OCwoLDg8KCw
+ 4LCuMODwoPDgsKDw4PCgsOCwoR0Q8ODwoPDgsKCw4PCgsOCwoM9w4PCg8OCwoPDg8KCw4LChMODwo
+ PDgsKDw4PCgsOCwoFOdTrDg8KDw4LCg8ODwoLDgsKHw4PCg8OCwoPDg8KCw4LChMODwoPDgsKDw4P
+ CgsOCwoFOw4PCg8OCwoPDg8KCw4LCqMODwoPDgsKDw4PCgsOCwrtHw4PCg8OCwoLDg8KCw4LChcOD
+ woPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsK4dMODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODw
+ oLDgsKtR8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCiMODwo
+ PDgsKDw4PCgsOCwr9SfGrDg8KDw4LCgsODwoLDgsKLQGgxw4PCg8OCwoPDg8KCw4LCoWhQw4PCg8O
+ CwoPDg8KCw4LCv8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKKT8ODwoPDgsKCw4PCgsOC
+ wotEJDDDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHTDg8KDw4LCgsODwoLDgsKDw4PCg
+ 8OCwoPDg8KCw4LCuHXDg8KDw4LCgsODwoLDgsKLRCRqw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4
+ PCgsOCwojDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpPDg8K
+ Dw4LCg8ODwoLDgsKQXV9eW8ODwoPDgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsKEw4PCg8OCwoPD
+ g8KCw4LCgsODwoPDgsKDw4PCgsOCwozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODw
+ oPDgsKDw4PCgsOCwozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgs
+ OCwoxWV8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKxw4PCg8OCwoLDg8KCw4LCi3wkw4P
+ Cg8OCwoLDg8KCw4LCjcODwoPDgsKCw4PCgsOCwofDg8KDw4LCg8ODwoLDgsKof8ODwoPDgsKDw4PC
+ gsOCwr/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoLDg8KCw4LCg8ODwoPDgsKDw4PCgsOCwrh5w4PCg
+ 8OCwoLDg8KCw4LChzQzw4PCg8OCwoPDg8KCw4LCicODwoPDgsKCw4PCgsOCworDg8KDw4LCgsODwo
+ LDgsKIw4PCg8OCwoLDg8KCw4LCuDFBw4PCg8OCwoPDg8KCw4LCvyTDg8KDw4LCgsODwoLDgsKNdDF
+ Bw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODwoPD
+ gsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwoLDg8KCw
+ 4LCi8ODwoPDgsKDw4PCgsOCwo7Dg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw4LCv8ODwoPDgs
+ KCw4PCgsOCwoTDg8KDw4LCgsODwoLDgsKAdcODwoPDgsKDw4PCgsOCwqhtw4PCg8OCwoLDg8KCw4L
+ ChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKEw4PCg8OCwoPDg8KCw4LCsMODwoPDgsKC
+ w4PCgsOCwrhfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCg8ODwoLDgsKow4PCg8OCwoLDg8KCw4LCt
+ sODwoPDgsKDw4PCgsOCwq7Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4
+ PCgsOCwoPDg8KDw4LCg8ODwoLDgsKoZsODwoPDgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsK4w4P
+ Cg8OCwoLDg8KCw4LCh8ODwoPDgsKDw4PCgsOCwpUzw4PCg8OCwoPDg8KCw4LCicODwoPDgsKCw4PC
+ gsOCworDg8KDw4LCgsODwoLDgsKISDJBw4PCg8OCwoPDg8KCw4LCvyTDg8KDw4LCgsODwoLDgsKNN
+ DJBw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKOw4PCg8OCwo
+ PDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpDDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8O
+ DwoPDgsKDw4PCgsOCwojDg8KDw4LCg8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCnEzDg8KDw4LCgsOD
+ woLDgsKLSEBmw4PCg8OCwoLDg8KCw4LCg3lwdSTDg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw
+ 4LCv8ODwoPDgsKCw4PCgsOCwobDg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODwoPDgs
+ KCw4PCgsOCwp/Dg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwoj
+ Dg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODwoPDgsKCw4PCgsOCwpPDg8KDw4LCgsOD
+ woLDgsKBw4PCg8OCwoPDg8KCw4LCv1rDg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODw
+ oPDgsKCw4PCgsOCwodqw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwoBqaMODwoPDgsKCw4
+ PCgsOCwpBQw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKDIMODwoPDgsKCw4PCgsOCwopPw4PCg8OCwoL
+ Dg8KCw4LChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKOacODwoPDgsKCw4PCgsOCwrhf
+ XsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCw
+ oLDg8KCw4LCgcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKGw4PCg8OCwoLDg8KCw4LCgM
+ ODwoPDgsKCw4PCgsOCwoRJw4PCg8OCwoLDg8KCw4LCgcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsO
+ DwoLDgsKIw4PCg8OCwoLDg8KCw4LCgMODwoPDgsKCw4PCgsOCwoQ9w4PCg8OCwoLDg8KCw4LCgcOD
+ woPDgsKDw4PCgsOCwr9aw4PCg8OCwoLDg8KCw4LCgMODwoPDgsKCw4PCgsOCwoQxw4PCg8OCwoLDg
+ 8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwoM9w4PCg8OCwoPDg8KCw4LCm0
+ 7Dg8KDw4LCgsODwoLDgsKEw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsK
+ Cw4PCgsOCwrhfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLD
+ gsKCw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODw
+ oPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgs
+ OCwo7Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoLDg8KCw4LCkMODwoPDgsKDw4PCgsOCwojDg8KDw4L
+ CgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCiMODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODwoLDgsK+
+ S8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKww4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKDw
+ 4PCgsOCwoTDg8KDw4LCgsODwoLDgsKKT1DDg8KDw4LCg8ODwoLDgsKoRsODwoPDgsKCw4PCgsOCwo
+ vDg8KDw4LCg8ODwoLDgsK4w4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwrZ0Y8ODwoPDgsK
+ Cw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK/dF/Dg8KDw4LCgsODwoLDgsKhdHpPw4PCg8OCwoLDg8KC
+ w4LCi8ODwoPDgsKDw4PCgsOCwo5Qw4PCg8OCwoPDg8KCw4LCqC1Jw4PCg8OCwoLDg8KCw4LChcODw
+ oPDgsKDw4PCgsOCwoB1RMODwoPDgsKCw4PCgsOCwqFwek/Dg8KDw4LCgsODwoLDgsKLw4PCg8OCwo
+ PDg8KCw4LCj1DDg8KDw4LCg8ODwoLDgsKoScODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK
+ AdTPDg8KDw4LCgsODwoLDgsKhbHpPw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo5Qw4PC
+ g8OCwoPDg8KCw4LCqEnDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHXDg8KDw4LCgsODw
+ oLDgsKhaHpPw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo9Qw4PCg8OCwoPDg8KCw4LCqM
+ ODwoPDgsKDw4PCgsOCwrpIw4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwoB1M8ODwoPDgsK
+ Dw4PCgsOCwoBfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLD
+ gsKCw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgjPDg8KDw4LCg8ODwoLDgsKAX17Dg
+ 8KDw4LCg8ODwoLDgsKCw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo7Dg8KDw4LCg8ODwo
+ LDgsKoJ8ODwoPDgsKDw4PCgsOCwq3Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoP
+ DgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsK4aHU5w4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PC
+ gsOCwovDg8KDw4LCg8ODwoLDgsKOw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpDDg8KDw
+ 4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgs
+ KIw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpLDg8KDw4LCg8ODwoLDgsKEw4PCg8OCwoL
+ Dg8KCw4LChcODwoPDgsKDw4PCgsOCwoB0IcODwoPDgsKCw4PCgsOCwovDg8KDw4LCgsODwoLDgsKA
+ w4PCg8OCwoPDg8KCw4LCtMODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsKAdGbDg8KDw4LCg
+ sODwoLDgsKLQGY9dGY9dTPDg8KDw4LCg8ODwoLDgsKAX17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwo
+ LDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODwoPDgsKDw4PCgsO
+ CwoIzw4PCg8OCwoPDg8KCw4LCgF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwovDg8KD
+ w4LCg8ODwoLDgsK/Ri9BUC9BRi9BWi9BZC9BWzBBZC9BZTBBZC9BZC9BbzBBZC9BeTBBw4PCg8OCw
+ oLDg8KCw4LCgzBBMUFhMUFrMUE=
+description:: UF7Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOC
+ wozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOCwozDg8KDw4LCg
+ 8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCqFDDg8KDw4LCg8ODwoLDgsKpRsODwoPDgsKDw4PCgsOCwo
+ zDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOCwozDg8KDw4LCg8O
+ DwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKCw4PCgsOCwotEJCDDg8KDw4LCgsODwoLDgsKD
+ w4PCg8OCwoPDg8KCw4LCrMODwoPDgsKCw4PCgsOCwotUJCRTw4PCg8OCwoLDg8KCw4LCi1wkJFbDg
+ 8KDw4LCgsODwoLDgsKJTCRXVVBSU8ODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODwoLDgsKdT8ODwo
+ PDgsKCw4PCgsOCwoN8JDB1w4PCg8OCwoPDg8KCw4LCh8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCg8O
+ DwoLDgsKBTsODwoPDgsKDw4PCgsOCwqktw4PCg8OCwoLDg8KCw4LCg3wkMHTDg8KDw4LCgsODwoLD
+ gsKDfCQww4PCg8OCwoLDg8KCw4LChTPDg8KDw4LCg8ODwoLDgsK2OTXDg8KDw4LCg8ODwoLDgsKAw
+ 4PCg8OCwoPDg8KCw4LCgU7Dg8KDw4LCgsODwoLDgsKEIMODwoPDgsKCw4PCgsOCwqFIw4PCg8OCwo
+ PDg8KCw4LChU7Dg8KDw4LCgsODwoLDgsKJNcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCg8ODwoLDgsK
+ BTsODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKD
+ w4PCgsOCwr9TXMODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGw4PCg8OCwoLDg8KCw
+ 4LChMODwoPDgsKCw4PCgsOCwpHDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLIEjDg8
+ KDw4LCg8ODwoLDgsKFTlDDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv1Ngw4PCg8OCwoL
+ Dg8KCw4LCi8ODwoPDgsKDw4PCgsOCwpjDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCm3Rx
+ w4PCg8OCwoLDg8KCw4LCizvDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCi8ODwoPDgsKDw
+ 4PCgsOCwr9XaMODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGdGLDg8KDw4LCgsODwo
+ LDgsKLf2zDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCi1D
+ Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCl8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8OD
+ woLDgsKow4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwq10SmgoT03Dg8KDw4LCgsODwoLDg
+ sKLw4PCg8OCwoPDg8KCw4LCjcODwoPDgsKDw4PCgsOCwqggTMODwoPDgsKCw4PCgsOCwoXDg8KDw4
+ LCg8ODwoLDgsKAdDrDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLTSBQUcODwoPDgsK
+ Dw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoLDg8KCw4LCik/Dg8KDw4LCgsODwoLDgsKL
+ RCQoZitEJCDDg8KDw4LCgsODwoLDgsK3w4PCg8OCwoPDg8KCw4LCiMODwoPDgsKDw4PCgsOCwoHDg
+ 8KDw4LCg8ODwoLDgsKhw4PCg8OCwoLDg8KCw4LCi0QkJGYrRCTDg8KDw4LCgsODwoLDgsK3w4PCg8
+ OCwoPDg8KCw4LCkMODwoPDgsKDw4PCgsOCworDg8KDw4LCgsODwoLDgsKLRSBRVmpQw4PCg8OCwoP
+ Dg8KCw4LCv8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKKTzl0JHXDg8KDw4LCgsODwoLD
+ gsKhOXQkw4PCg8OCwoLDg8KCw4LChW/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODw
+ oPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKhRMODwoPDgsKDw4PCgsOCwoVOw4PCg8OCwoLDg8
+ KCw4LCi8ODwoPDgsKDw4PCgsOCwojDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv1Ncw4P
+ Cg8OCwoLDg8KCw4LCiUQkw4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsOD
+ woLDgsKEw4PCg8OCwoPDg8KCw4LCtjPDg8KDw4LCg8ODwoLDgsK2w4PCg8OCwoLDg8KCw4LCjUQkw
+ 4PCg8OCwoLDg8KCw4LCiyBEw4PCg8OCwoPDg8KCw4LChU5Qw4PCg8OCwoLDg8KCw4LCi8ODwoPDgs
+ KDw4PCgsOCwr9TYMODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsK4w4PCg8OCwoLDg8KCw4L
+ ChcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKEw4PCg8OCwoPDg8KCw4LCkMODwoPDgsKC
+ w4PCgsOCwovDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCj8ODwoPDgsKDw4PCgsOCwr9Ta
+ MODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGw4PCg8OCwoLDg8KCw4LChMODwoPDgs
+ KCw4PCgsOCwr3Dg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4L
+ Cj1DDg8KDw4LCg8ODwoLDgsK/U2zDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCqMODwoPD
+ gsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsKtw4PCg8OCwoLDg8KCw4LChMODwoPDgsKCw4PCgsOCw
+ p9oMMODwoPDgsKDw4PCgsOCwolMw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo3Dg8KDw4
+ LCg8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCq0vDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4L
+ CgMODwoPDgsKCw4PCgsOCwoTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoLDg8KCw4LCi0QkOcODwoPD
+ gsKCw4PCgsOCwrDDg8KDw4LCg8ODwoLDgsKEdEU5w4PCg8OCwoLDg8KCw4LCtTR0PcODwoPDgsKCw
+ 4PCgsOCwovDg8KDw4LCg8ODwoLDgsKNw4PCg8OCwoPDg8KCw4LCqMODwoPDgsKDw4PCgsOCwo5Lw4
+ PCg8OCwoLDg8KCw4LCi0AgUMODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKsw4PCg8OCwoL
+ Dg8KCw4LCik/Dg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHUow4PCg8OCwoLDg8KCw4LC
+ i8ODwoPDgsKDw4PCgsOCwo3Dg8KDw4LCgsODwoLDgsKJw4PCg8OCwoLDg8KCw4LCtTTDg8KDw4LCg
+ 8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCl8ODwoPDgsKDw4PCgsOCwrtWw4PCg8OCwoLDg8KCw4LCi8
+ ODwoPDgsKDw4PCgsOCwo3Dg8KDw4LCg8ODwoLDgsKow4PCg8OCwoLDg8KCw4LCnw==
+
+dn: cn=All Staff,ou=Groups,dc=example,dc=com
+member: cn=Manager,dc=example,dc=com
+member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
+ ple,dc=com
+member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
+ mple,dc=com
+member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
+ e,dc=com
+owner: cn=Manager,dc=example,dc=com
+cn: All Staff
+description: Everyone in the sample data
+objectclass: groupofnames
+
+dn: cn=Alumni Assoc Staff,ou=Groups,dc=example,dc=com
+member: cn=Manager,dc=example,dc=com
+member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+owner: cn=Manager,dc=example,dc=com
+description: All Alumni Assoc Staff
+cn: Alumni Assoc Staff
+objectclass: groupofnames
+
+dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,
+ dc=com
+objectclass: OpenLDAPperson
+cn: Barbara Jensen
+cn: Babs Jensen
+sn:: IEplbnNlbiA=
+uid: bjensen
+title: Mythical Manager, Research Systems
+postaladdress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Anyt
+ own, MI 48103-4943
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+userpassword:: YmplbnNlbg==
+mail: bjensen@mailgw.example.com
+homepostaladdress: 123 Wesley $ Anytown, MI 48103
+description: Mythical manager of the rsdd unix project
+drink: water
+homephone: +1 313 555 2333
+pager: +1 313 555 3233
+facsimiletelephonenumber: +1 313 555 2274
+telephonenumber: +1 313 555 9022
+
+dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+objectclass: OpenLDAPperson
+cn: Bjorn Jensen
+cn: Biiff Jensen
+sn: Jensen
+uid: bjorn
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+userpassword:: Ympvcm4=
+homepostaladdress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
+drink: Iced Tea
+description: Hiker, biker
+title: Director, Embedded Systems
+postaladdress: Info Tech Division $ 535 W. William St. $ Anytown, MI 48103
+mail: bjorn@mailgw.example.com
+homephone: +1 313 555 5444
+pager: +1 313 555 4474
+facsimiletelephonenumber: +1 313 555 2177
+telephonenumber: +1 313 555 0355
+
+dn: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+objectclass: OpenLDAPperson
+cn: Dorothy Stevens
+cn: Dot Stevens
+sn: Stevens
+uid: dots
+title: Secretary, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+drink: Lemonade
+homepostaladdress: 377 White St. Apt. 3 $ Anytown, MI 48104
+description: Very tall
+facsimiletelephonenumber: +1 313 555 3223
+telephonenumber: +1 313 555 3664
+mail: dots@mail.alumni.example.com
+homephone: +1 313 555 0454
+
+dn: cn=ITD Staff,ou=Groups,dc=example,dc=com
+owner: cn=Manager,dc=example,dc=com
+description: All ITD Staff
+cn: ITD Staff
+objectclass: groupofuniquenames
+uniquemember: cn=Manager,dc=example,dc=com
+uniquemember: cn=Bjorn Jensen,OU=Information Technology Division,ou=People,dc=
+ example,dc=com
+uniquemember: cn=James A Jones 2,ou=Information Technology Division,ou=People,
+ dc=example,dc=com
+uniquemember: cn=John Doe,ou=Information Technology Division,ou=People,dc=exam
+ ple,dc=com
+
+dn: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+objectclass: OpenLDAPperson
+cn: James A Jones 1
+cn: James Jones
+cn: Jim Jones
+sn: Jones
+uid: jaj
+postaladdress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+userpassword:: amFq
+homepostaladdress: 3882 Beverly Rd. $ Anytown, MI 48105
+homephone: +1 313 555 4772
+description: Outstanding
+title: Mad Cow Researcher, UM Alumni Association
+pager: +1 313 555 3923
+mail: jaj@mail.alumni.example.com
+facsimiletelephonenumber: +1 313 555 4332
+telephonenumber: +1 313 555 0895
+
+dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=example
+ ,dc=com
+objectclass: OpenLDAPperson
+cn: James A Jones 2
+cn: James Jones
+cn: Jim Jones
+sn: Doe
+uid: jjones
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+homepostaladdress: 933 Brooks $ Anytown, MI 48104
+homephone: +1 313 555 8838
+title: Senior Manager, Information Technology Division
+description: Not around very much
+mail: jjones@mailgw.example.com
+postaladdress: Info Tech Division $ 535 W William $ Anytown, MI 48103
+pager: +1 313 555 2833
+facsimiletelephonenumber: +1 313 555 8688
+telephonenumber: +1 313 555 7334
+
+dn: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+objectclass: OpenLDAPperson
+cn: Jane Doe
+cn: Jane Alverson
+sn: Doe
+uid: jdoe
+title: Programmer Analyst, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+homepostaladdress: 123 Anystreet $ Anytown, MI 48104
+drink: diet coke
+description: Enthusiastic
+mail: jdoe@woof.net
+homephone: +1 313 555 5445
+pager: +1 313 555 1220
+facsimiletelephonenumber: +1 313 555 2311
+telephonenumber: +1 313 555 4774
+
+dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+objectclass: OpenLDAPperson
+cn: Jennifer Smith
+cn: Jen Smith
+sn: Smith
+uid: jen
+postaladdress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+drink: Sam Adams
+homepostaladdress: 1000 Maple #44 $ Anytown, MI 48103
+title: Telemarketer, UM Alumni Association
+mail: jen@mail.alumni.example.com
+homephone: +1 313 555 2333
+pager: +1 313 555 6442
+facsimiletelephonenumber: +1 313 555 2756
+telephonenumber: +1 313 555 8232
+
+dn: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc=com
+objectclass: OpenLDAPperson
+cn: John Doe
+cn: Jonathon Doe
+sn: Doe
+uid: johnd
+postaladdress: ITD $ 535 W. William $ Anytown, MI 48109
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+homepostaladdress: 912 East Bllvd $ Anytown, MI 48104
+title: System Administrator, Information Technology Division
+description: overworked!
+mail: johnd@mailgw.example.com
+homephone: +1 313 555 3774
+pager: +1 313 555 6573
+facsimiletelephonenumber: +1 313 555 4544
+telephonenumber: +1 313 555 9394
+
+dn: cn=Manager,dc=example,dc=com
+objectclass: person
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userpassword:: c2VjcmV0
+
+dn: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+objectclass: OpenLDAPperson
+cn: Mark Elliot
+cn: Mark A Elliot
+sn: Elliot
+uid: melliot
+postaladdress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+homepostaladdress: 199 Outer Drive $ Ypsilanti, MI 48198
+homephone: +1 313 555 0388
+drink: Gasoline
+title: Director, UM Alumni Association
+mail: melliot@mail.alumni.example.com
+pager: +1 313 555 7671
+facsimiletelephonenumber: +1 313 555 7762
+telephonenumber: +1 313 555 4177
+
+dn: cn=sangseoklim,ou=Alumni Association,ou=People,dc=example,dc=com
+objectclass: OpenLDAPperson
+cn: sangseoklim
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+homepostaladdress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homephone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimiletelephonenumber: +1 313 555 9700
+telephonenumber: +1 313 555 5331
+componentTest: component1
+
+dn: cn=seotaejee,ou=Alumni Association,ou=People,dc=example,dc=com
+objectclass: OpenLDAPperson
+cn: seotaejee
+sn: Hampster
+uid: uham
+title: Secretary, UM Alumni Association
+postaladdress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+homepostaladdress: 123 Anystreet $ Anytown, MI 48104
+mail: uham@mail.alumni.example.com
+homephone: +1 313 555 8421
+pager: +1 313 555 2844
+facsimiletelephonenumber: +1 313 555 9700
+telephonenumber: +1 313 555 5331
+componentTest: component2
index 5d00a0261e1f9779c4d802de8d37cdeff7d0b739..3f9043ad6effba2b70ac7dd5612b96551e987cc8 100644 (file)
@@ -41,10 +41,11 @@ AC_rwm=rwm@BUILD_RWM@
 # misc
 AC_WITH_SASL=@WITH_SASL@
 AC_WITH_TLS=@WITH_TLS@
+AC_WITH_COMP_MATCH=yes
 
 export AC_bdb AC_hdb AC_ldap AC_ldbm AC_monitor AC_relay AC_sql 
 export AC_pcache AC_ppolicy AC_refint AC_unique AC_rwm
-export AC_WITH_SASL AC_WITH_TLS
+export AC_WITH_SASL AC_WITH_TLS AC_WITH_COMP_MATCH
 
 if test ! -x ../servers/slapd/slapd ; then
        echo "Could not locate slapd(8)"
index 2a4aca3887cb29b5c5474df2f72df1e061709ca6..6b3a6603afbfdb3fc1258d9738d67e9aeff6fd45 100755 (executable)
@@ -154,6 +154,7 @@ LDIFIDASSERT2=$DATADIR/test-idassert2.ldif
 LDIFLDAPGLUE1=$DATADIR/test-ldapglue.ldif
 LDIFLDAPGLUE2=$DATADIR/test-ldapgluepeople.ldif
 LDIFLDAPGLUE3=$DATADIR/test-ldapgluegroups.ldif
+LDIFCOMPMATCH=$DATADIR/test-compmatch.ldif
 MONITOR=""
 REFDN="c=US"
 BASEDN="dc=example,dc=com"
@@ -204,6 +205,7 @@ PROXYCACHEOUT=$DATADIR/proxycache.out
 REFERRALOUT=$DATADIR/referrals.out
 SEARCHOUTMASTER=$DATADIR/search.out.master
 SEARCHOUTX=$DATADIR/search.out.xsearch
+COMPSEARCHOUT=$DATADIR/compsearch.out
 MODIFYOUTMASTER=$DATADIR/modify.out.master
 ADDDELOUTMASTER=$DATADIR/adddel.out.master
 MODRDNOUTMASTER0=$DATADIR/modrdn.out.master.0
diff --git a/tests/scripts/test031-component-filter b/tests/scripts/test031-component-filter
new file mode 100755 (executable)
index 0000000..42d7747
--- /dev/null
@@ -0,0 +1,169 @@
+#! /bin/sh
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2004 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+## If you use this script then
+## Make sure that you turn on LDAP_COMP_MATCH in slapd source codes
+## To disable, set "WITH_COMP_MATHC=no" in source_root/openldap/tests/run.in
+if test "$AC_WITH_COMP_MATCH" != "yes" ; then
+        echo "test disabled "
+        exit
+fi
+
+mkdir -p $TESTDIR $DBDIR1
+
+echo "Running slapadd to build slapd database..."
+. $CONFFILTER $BACKEND $MONITORDB < $MCONF > $ADDCONF
+$SLAPADD -f $ADDCONF -l $LDIFCOMPMATCH
+RC=$?
+if test $RC != 0 ; then
+       echo "slapadd failed ($RC)!"
+       exit $RC
+fi
+
+echo "Running slapindex to index slapd database..."
+. $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
+$SLAPINDEX -f $CONF1
+RC=$?
+if test $RC != 0 ; then
+       echo "warning: slapindex failed ($RC)"
+       echo "  assuming no indexing support"
+fi
+
+echo "Starting slapd on TCP/IP port $PORT1..."
+$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+    echo PID $PID
+    read foo
+fi
+KILLPIDS="$PID"
+
+echo "Testing slapd searching..."
+for i in 0 1 2 3 4 5; do
+       $LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \
+               'objectclass=*' > /dev/null 2>&1
+       RC=$?
+       if test $RC = 0 ; then
+               break
+       fi
+       echo "Waiting 5 seconds for slapd to start..."
+       sleep 5
+done
+
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+cat /dev/null > $SEARCHOUT
+
+echo "Testing Component Filter Match RFC3687 searching:"
+echo "# Testing Component Filter Match RFC3687 searching:" >> $SEARCHOUT
+
+FILTER="(componentTest:componentFilterMatch:=item:{ component \"id\", rule caseExactMatch, value \"worldcup\" )"
+echo "        f=$FILTER ..."
+echo "#         f=$FILTER ..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
+       "$FILTER" >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+FILTER="(componentTest:componentFilterMatch:=not:item:{ component \"id2\", rule caseExactMatch, value \"worldcup\" )"
+echo "        f=$FILTER ..."
+echo "#         f=$FILTER ..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
+       "$FILTER" >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+FILTER="(componentTest:componentFilterMatch:=not:item:{ component \"id2\", rule componentFilterMatch, value not:item:{ component \"id.0\", rule integerMatch, value 5 }})"
+echo "        f=$FILTER ..."
+echo "#         f=$FILTER ..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
+       "$FILTER" >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+FILTER="(componentTest:componentFilterMatch:=and:{item:{ component \"100\", rule caseIgnoreMatch, value "foobar" },item:{ component \"id2.rr.kk\", rule componentFilterMatch, value item:{ component \"id3\", rule integerMatch, value 1 }}})"
+echo "        f=$FILTER ..."
+echo "#         f=$FILTER ..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
+       "$FILTER" >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+FILTER="(componentTest:componentFilterMatch:=and:{not:item:{ component \"100\", rule caseIgnoreMatch, value "foobar" },not:item:{ component \"id2.rr.kk\", rule componentFilterMatch, value item:{ component \"id3\", rule integerMatch, value 1 }}})"
+echo "        f=$FILTER ..."
+echo "#         f=$FILTER ..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
+       "$FILTER" >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+FILTER="(componentTest:componentFilterMatch:=or:{not:item:{ component \"100\", rule caseIgnoreMatch, value "foobar" },not:item:{ component \"id2.rr.kk\", rule componentFilterMatch, value item:{ component \"id3\", rule integerMatch, value 1 }}})"
+echo "        f=$FILTER ..."
+echo "#         f=$FILTER ..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
+       "$FILTER" >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+echo "Filtering ldapsearch results..."
+. $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $COMPSEARCHOUT > $CMPOUT
+
+if test $? != 0 ; then
+       echo "Comparison failed"
+       exit 1
+fi
+
+echo ">>>>> Test succeeded"
+exit 0