]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/filter.c
More for prev commit - only set if URL was provided.
[openldap] / libraries / libldap / filter.c
index 7d40d1ceb472588ee886da4c89df09f19c7a18b5..2d05d81c25dc78187d08596ecfd9b5867ff6ef84 100644 (file)
@@ -1,13 +1,20 @@
+/* search.c */
 /* $OpenLDAP$ */
-/*
- * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
- */
-/*  Portions
- *  Copyright (c) 1990 Regents of the University of Michigan.
- *  All rights reserved.
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2009 The OpenLDAP Foundation.
+ * All rights reserved.
  *
- *  search.c
+ * 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>.
+ */
+/* Portions Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
  */
 
 #include "portable.h"
@@ -43,7 +50,8 @@ static int put_simple_filter LDAP_P((
 static int put_substring_filter LDAP_P((
        BerElement *ber,
        char *type,
-       char *str ));
+       char *str,
+       char *nextstar ));
 
 static int put_filter_list LDAP_P((
        BerElement *ber,
@@ -324,44 +332,39 @@ ldap_pvt_put_filter( BerElement *ber, const char *str_in )
        int     parens, balance, escape;
 
        /*
-        * A Filter looks like this:
-        *      Filter ::= CHOICE {
-        *              and             [0]     SET OF Filter,
-        *              or              [1]     SET OF Filter,
-        *              not             [2]     Filter,
-        *              equalityMatch   [3]     AttributeValueAssertion,
-        *              substrings      [4]     SubstringFilter,
-        *              greaterOrEqual  [5]     AttributeValueAssertion,
-        *              lessOrEqual     [6]     AttributeValueAssertion,
-        *              present         [7]     AttributeType,
-        *              approxMatch     [8]     AttributeValueAssertion,
-        *                              extensibleMatch [9]             MatchingRuleAssertion -- LDAPv3
-        *      }
+        * A Filter looks like this (RFC 4511 as extended by RFC 4526):
+        *     Filter ::= CHOICE {
+        *         and             [0]     SET SIZE (0..MAX) OF filter Filter,
+        *         or              [1]     SET SIZE (0..MAX) OF filter Filter,
+        *         not             [2]     Filter,
+        *         equalityMatch   [3]     AttributeValueAssertion,
+        *         substrings      [4]     SubstringFilter,
+        *         greaterOrEqual  [5]     AttributeValueAssertion,
+        *         lessOrEqual     [6]     AttributeValueAssertion,
+        *         present         [7]     AttributeDescription,
+        *         approxMatch     [8]     AttributeValueAssertion,
+        *         extensibleMatch [9]     MatchingRuleAssertion,
+        *         ... }
         *
-        *      SubstringFilter ::= SEQUENCE {
-        *              type               AttributeType,
-        *              SEQUENCE OF CHOICE {
-        *                      initial          [0] IA5String,
-        *                      any              [1] IA5String,
-        *                      final            [2] IA5String
-        *              }
-        *      }
+        *     SubstringFilter ::= SEQUENCE {
+        *         type         AttributeDescription,
+        *         substrings   SEQUENCE SIZE (1..MAX) OF substring CHOICE {
+        *             initial          [0] AssertionValue, -- only once
+        *             any              [1] AssertionValue,
+        *             final            [2] AssertionValue  -- only once
+        *             }
+        *         }
         *
-        *              MatchingRuleAssertion ::= SEQUENCE {    -- LDAPv3
-        *                      matchingRule    [1] MatchingRuleId OPTIONAL,
-        *                      type            [2] AttributeDescription OPTIONAL,
-        *                      matchValue      [3] AssertionValue,
-        *                      dnAttributes    [4] BOOLEAN DEFAULT FALSE }
+        *         MatchingRuleAssertion ::= SEQUENCE {
+        *         matchingRule    [1] MatchingRuleId OPTIONAL,
+        *         type            [2] AttributeDescription OPTIONAL,
+        *         matchValue      [3] AssertionValue,
+        *         dnAttributes    [4] BOOLEAN DEFAULT FALSE }
         *
-        * Note: tags in a choice are always explicit
+        * Note: tags in a CHOICE are always explicit
         */
 
-#ifdef NEW_LOGGING
-       LDAP_LOG (( "filter", LDAP_LEVEL_ARGS, "ldap_pvt_put_filter: \"%s\"\n",
-               str_in ));
-#else
        Debug( LDAP_DEBUG_TRACE, "put_filter: \"%s\"\n", str_in, 0, 0 );
-#endif
 
        freeme = LDAP_STRDUP( str_in );
        if( freeme == NULL ) return LDAP_NO_MEMORY;
@@ -379,13 +382,8 @@ ldap_pvt_put_filter( BerElement *ber, const char *str_in )
 
                        switch ( *str ) {
                        case '&':
-#ifdef NEW_LOGGING
-                               LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                                       "ldap_pvt_put_filter: AND\n" ));
-#else
                                Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n",
                                    0, 0, 0 );
-#endif
 
                                str = put_complex_filter( ber, str,
                                    LDAP_FILTER_AND, 0 );
@@ -398,13 +396,8 @@ ldap_pvt_put_filter( BerElement *ber, const char *str_in )
                                break;
 
                        case '|':
-#ifdef NEW_LOGGING
-                               LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                                       "ldap_pvt_put_filter: OR\n" ));
-#else
                                Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n",
                                    0, 0, 0 );
-#endif
 
                                str = put_complex_filter( ber, str,
                                    LDAP_FILTER_OR, 0 );
@@ -417,13 +410,8 @@ ldap_pvt_put_filter( BerElement *ber, const char *str_in )
                                break;
 
                        case '!':
-#ifdef NEW_LOGGING
-                               LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                                       "ldap_pvt_put_filter: NOT\n" ));
-#else
                                Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n",
                                    0, 0, 0 );
-#endif
 
                                str = put_complex_filter( ber, str,
                                    LDAP_FILTER_NOT, 0 );
@@ -435,14 +423,13 @@ ldap_pvt_put_filter( BerElement *ber, const char *str_in )
                                parens--;
                                break;
 
+                       case '(':
+                               rc = -1;
+                               goto done;
+
                        default:
-#ifdef NEW_LOGGING
-                               LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                                       "ldap_pvt_put_filter: simple\n" ));
-#else
                                Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n",
                                    0, 0, 0 );
-#endif
 
                                balance = 1;
                                escape = 0;
@@ -487,13 +474,8 @@ ldap_pvt_put_filter( BerElement *ber, const char *str_in )
                        break;
 
                case /*'('*/ ')':
-#ifdef NEW_LOGGING
-                       LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                               "ldap_pvt_put_filter: end\n" ));
-#else
                        Debug( LDAP_DEBUG_TRACE, "put_filter: end\n",
                                0, 0, 0 );
-#endif
                        if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) {
                                rc = -1;
                                goto done;
@@ -507,13 +489,8 @@ ldap_pvt_put_filter( BerElement *ber, const char *str_in )
                        break;
 
                default:        /* assume it's a simple type=value filter */
-#ifdef NEW_LOGGING
-                       LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                               "ldap_pvt_put_filter: default\n" ));
-#else
                        Debug( LDAP_DEBUG_TRACE, "put_filter: default\n",
                                0, 0, 0 );
-#endif
                        next = strchr( str, '\0' );
                        if ( put_simple_filter( ber, str ) == -1 ) {
                                rc = -1;
@@ -522,9 +499,11 @@ ldap_pvt_put_filter( BerElement *ber, const char *str_in )
                        str = next;
                        break;
                }
+               if ( !parens )
+                       break;
        }
 
-       rc = parens ? -1 : 0;
+       rc = ( parens || *str ) ? -1 : 0;
 
 done:
        LDAP_FREE( freeme );
@@ -541,13 +520,8 @@ put_filter_list( BerElement *ber, char *str, ber_tag_t tag )
        char    *next = NULL;
        char    save;
 
-#ifdef NEW_LOGGING
-       LDAP_LOG (( "filter", LDAP_LEVEL_ARGS, 
-                               "put_filter_list \"%s\"\n", str ));
-#else
        Debug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n",
                str, 0, 0 );
-#endif
 
        while ( *str ) {
                while ( *str && LDAP_SPACE( (unsigned char) *str ) ) {
@@ -586,13 +560,8 @@ put_simple_filter(
        ber_tag_t       ftype;
        int             rc = -1;
 
-#ifdef NEW_LOGGING
-       LDAP_LOG (( "filter", LDAP_LEVEL_ARGS, 
-                               "put_simple_filter: \"%s\"\n", str ));
-#else
        Debug( LDAP_DEBUG_TRACE, "put_simple_filter: \"%s\"\n",
                str, 0, 0 );
-#endif
 
        str = LDAP_STRDUP( str );
        if( str == NULL ) return -1;
@@ -621,7 +590,7 @@ put_simple_filter(
                break;
 
        case ':':
-               /* RFC2254 extensible filters are off the form:
+               /* RFC 4515 extensible filters are off the form:
                 *              type [:dn] [:rule] := value
                 * or   [:dn]:rule := value             
                 */
@@ -638,7 +607,7 @@ put_simple_filter(
 
                                if( rule == NULL ) {
                                        /* one colon */
-                                       if ( strcmp(dn, "dn") == 0 ) {
+                                       if ( strcasecmp(dn, "dn") == 0 ) {
                                                /* must have attribute */
                                                if( !ldap_is_desc( str ) ) {
                                                        goto done;
@@ -655,7 +624,7 @@ put_simple_filter(
                                        /* two colons */
                                        *rule++ = '\0';
 
-                                       if ( strcmp(dn, "dn") != 0 ) {
+                                       if ( strcasecmp(dn, "dn") != 0 ) {
                                                /* must have "dn" */
                                                goto done;
                                        }
@@ -725,7 +694,7 @@ put_simple_filter(
                                ftype = LDAP_FILTER_PRESENT;
 
                        } else {
-                               rc = put_substring_filter( ber, str, value );
+                               rc = put_substring_filter( ber, str, value, nextstar );
                                goto done;
                        }
                } break;
@@ -752,31 +721,26 @@ done:
 }
 
 static int
-put_substring_filter( BerElement *ber, char *type, char *val )
+put_substring_filter( BerElement *ber, char *type, char *val, char *nextstar )
 {
-       char *nextstar;
        int gotstar = 0;
        ber_tag_t       ftype = LDAP_FILTER_SUBSTRINGS;
 
-#ifdef NEW_LOGGING
-       LDAP_LOG (( "filter", LDAP_LEVEL_ARGS, 
-                               "put_substring_filter \"%s=%s\"\n", type, val ));
-#else
        Debug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n",
                type, val, 0 );
-#endif
 
        if ( ber_printf( ber, "t{s{" /*"}}"*/, ftype, type ) == -1 ) {
                return -1;
        }
 
        for( ; *val; val=nextstar ) {
-               nextstar = ldap_pvt_find_wildcard( val );
+               if ( gotstar )
+                       nextstar = ldap_pvt_find_wildcard( val );
 
                if ( nextstar == NULL ) {
                        return -1;
                }
-               
+
                if ( *nextstar == '\0' ) {
                        ftype = LDAP_SUBSTRING_FINAL;
                } else {
@@ -791,7 +755,7 @@ put_substring_filter( BerElement *ber, char *type, char *val )
                if ( *val != '\0' || ftype == LDAP_SUBSTRING_ANY ) {
                        ber_slen_t len = ldap_pvt_filter_value_unescape( val );
 
-                       if ( len < 0  ) {
+                       if ( len <= 0  ) {
                                return -1;
                        }
 
@@ -808,8 +772,8 @@ put_substring_filter( BerElement *ber, char *type, char *val )
        return 0;
 }
 
-int
-ldap_pvt_put_vrFilter( BerElement *ber, const char *str_in )
+static int
+put_vrFilter( BerElement *ber, const char *str_in )
 {
        int rc;
        char    *freeme;
@@ -844,14 +808,11 @@ ldap_pvt_put_vrFilter( BerElement *ber, const char *str_in )
         *              matchingRule    [1] MatchingRuleId OPTIONAL,
         *              type            [2] AttributeDescription OPTIONAL,
         *              matchValue      [3] AssertionValue }
+        *
+        * (Source: RFC 3876)
         */
 
-#ifdef NEW_LOGGING
-       LDAP_LOG (( "filter", LDAP_LEVEL_ARGS, "ldap_pvt_put_vrFilter: \"%s\"\n",
-               str_in ));
-#else
        Debug( LDAP_DEBUG_TRACE, "put_vrFilter: \"%s\"\n", str_in, 0, 0 );
-#endif
 
        freeme = LDAP_STRDUP( str_in );
        if( freeme == NULL ) return LDAP_NO_MEMORY;
@@ -891,13 +852,8 @@ ldap_pvt_put_vrFilter( BerElement *ber, const char *str_in )
 
 
                        default:
-#ifdef NEW_LOGGING
-                               LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                                       "ldap_pvt_put_vrFilter: simple\n" ));
-#else
                                Debug( LDAP_DEBUG_TRACE, "put_vrFilter: simple\n",
                                    0, 0, 0 );
-#endif
 
                                balance = 1;
                                escape = 0;
@@ -942,13 +898,8 @@ ldap_pvt_put_vrFilter( BerElement *ber, const char *str_in )
                        break;
 
                case /*'('*/ ')':
-#ifdef NEW_LOGGING
-                       LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                               "ldap_pvt_put_filter: end\n" ));
-#else
-                       Debug( LDAP_DEBUG_TRACE, "put_filter: end\n",
+                       Debug( LDAP_DEBUG_TRACE, "put_vrFilter: end\n",
                                0, 0, 0 );
-#endif
                        if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) {
                                rc = -1;
                                goto done;
@@ -962,15 +913,10 @@ ldap_pvt_put_vrFilter( BerElement *ber, const char *str_in )
                        break;
 
                default:        /* assume it's a simple type=value filter */
-#ifdef NEW_LOGGING
-                       LDAP_LOG (( "filter", LDAP_LEVEL_DETAIL1, 
-                               "ldap_pvt_put_filter: default\n" ));
-#else
-                       Debug( LDAP_DEBUG_TRACE, "put_filter: default\n",
+                       Debug( LDAP_DEBUG_TRACE, "put_vrFilter: default\n",
                                0, 0, 0 );
-#endif
                        next = strchr( str, '\0' );
-                       if ( put_simple_filter( ber, str ) == -1 ) {
+                       if ( put_simple_vrFilter( ber, str ) == -1 ) {
                                rc = -1;
                                goto done;
                        }
@@ -987,7 +933,7 @@ done:
 }
 
 int
-put_vrFilter( BerElement *ber, const char *str_in )
+ldap_put_vrFilter( BerElement *ber, const char *str_in )
 {
        int rc =0;
        
@@ -995,7 +941,7 @@ put_vrFilter( BerElement *ber, const char *str_in )
                rc = -1;
        }
        
-       rc = ldap_pvt_put_vrFilter( ber, str_in );
+       rc = put_vrFilter( ber, str_in );
 
        if ( ber_printf( ber, /*"{"*/ "N}" ) == -1 ) {
                rc = -1;
@@ -1010,13 +956,8 @@ put_vrFilter_list( BerElement *ber, char *str )
        char    *next = NULL;
        char    save;
 
-#ifdef NEW_LOGGING
-       LDAP_LOG (( "filter", LDAP_LEVEL_ARGS, 
-               "put_vrFilter_list \"%s\"\n", str ));
-#else
        Debug( LDAP_DEBUG_TRACE, "put_vrFilter_list \"%s\"\n",
                str, 0, 0 );
-#endif
 
        while ( *str ) {
                while ( *str && LDAP_SPACE( (unsigned char) *str ) ) {
@@ -1031,7 +972,7 @@ put_vrFilter_list( BerElement *ber, char *str )
 
                /* now we have "(filter)" with str pointing to it */
                *next = '\0';
-               if ( ldap_pvt_put_vrFilter( ber, str ) == -1 ) return -1;
+               if ( put_vrFilter( ber, str ) == -1 ) return -1;
                *next = save;
                str = next;
        }
@@ -1049,13 +990,8 @@ put_simple_vrFilter(
        ber_tag_t       ftype;
        int             rc = -1;
 
-#ifdef NEW_LOGGING
-       LDAP_LOG (( "filter", LDAP_LEVEL_ARGS, 
-               "put_simple_vrFilter: \"%s\"\n", str ));
-#else
        Debug( LDAP_DEBUG_TRACE, "put_simple_vrFilter: \"%s\"\n",
                str, 0, 0 );
-#endif
 
        str = LDAP_STRDUP( str );
        if( str == NULL ) return -1;
@@ -1094,7 +1030,6 @@ put_simple_vrFilter(
 
                {
                        char *rule = strchr( str, ':' );
-                       *rule++ = '\0';
 
                        if( rule == NULL ) {
                                /* must have attribute */
@@ -1102,12 +1037,10 @@ put_simple_vrFilter(
                                        goto done;
                                }
                                rule = "";
-                       
                        } else {
                                *rule++ = '\0';
                        }
 
-
                        if ( *str == '\0' && ( !rule || *rule == '\0' ) ) {
                                /* must have either type or rule */
                                goto done;
@@ -1165,7 +1098,7 @@ put_simple_vrFilter(
                                ftype = LDAP_FILTER_PRESENT;
 
                        } else {
-                               rc = put_substring_filter( ber, str, value );
+                               rc = put_substring_filter( ber, str, value, nextstar );
                                goto done;
                        }
                } break;