]> git.sur5r.net Git - openldap/commitdiff
honor T-F filters (ITS#3706) and some cleanup
authorPierangelo Masarati <ando@openldap.org>
Thu, 5 May 2005 00:07:17 +0000 (00:07 +0000)
committerPierangelo Masarati <ando@openldap.org>
Thu, 5 May 2005 00:07:17 +0000 (00:07 +0000)
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/search.c

index 0a147799298913f501063bb227001c5611dbfe76..beb560c3e610a77760e7a72b8a52929c132c31f2 100644 (file)
@@ -93,14 +93,20 @@ struct ldapinfo {
 #define LDAP_BACK_F_USE_TLS            0x02U
 #define LDAP_BACK_F_PROPAGATE_TLS      0x04U
 #define LDAP_BACK_F_TLS_CRITICAL       0x08U
+#define LDAP_BACK_F_TLS_MASK           (LDAP_BACK_F_USE_TLS|LDAP_BACK_F_PROPAGATE_TLS|LDAP_BACK_F_TLS_CRITICAL)
 #define LDAP_BACK_F_CHASE_REFERRALS    0x10U
 
+#define        LDAP_BACK_F_SUPPORT_T_F                 0x80U
+#define        LDAP_BACK_F_SUPPORT_T_F_DISCOVER        0x40U
+
 #define LDAP_BACK_SAVECRED(li)         ( (li)->flags & LDAP_BACK_F_SAVECRED )
 #define LDAP_BACK_USE_TLS(li)          ( (li)->flags & LDAP_BACK_F_USE_TLS )
 #define LDAP_BACK_PROPAGATE_TLS(li)    ( (li)->flags & LDAP_BACK_F_PROPAGATE_TLS )
 #define LDAP_BACK_TLS_CRITICAL(li)     ( (li)->flags & LDAP_BACK_F_TLS_CRITICAL )
 #define LDAP_BACK_CHASE_REFERRALS(li)  ( (li)->flags & LDAP_BACK_F_CHASE_REFERRALS )
 
+       int             version;
+
        Avlnode         *conntree;
 
        int             rwm_started;
index 6cd07ba40a502df64e5b3463706e8a6282b44774..e570e3b0e4f922588c1d4277a10d12576e9c4652 100644 (file)
@@ -217,49 +217,37 @@ ldap_back_db_config(
                li->url = ch_strdup( argv[ 1 ] );
 #endif
 
-       } else if ( strncasecmp( argv[0], "tls-", STRLENOF( "tls-" ) ) == 0 ) {
+       } else if ( strcasecmp( argv[0], "tls" ) == 0 ) {
+               if ( argc != 2 ) {
+                       fprintf( stderr,
+               "%s: line %d: \"tls <what>\" needs 1 argument.\n",
+                                       fname, lineno );
+                       return( 1 );
+               }
 
-               /* start tls */
-               if ( strcasecmp( argv[0], "tls-start" ) == 0 ) {
-                       if ( argc != 1 ) {
-                               fprintf( stderr,
-               "%s: line %d: tls-start takes no arguments\n",
-                                               fname, lineno );
-                               return( 1 );
-                       }
+               /* start */
+               if ( strcasecmp( argv[1], "start" ) == 0 ) {
                        li->flags |= ( LDAP_BACK_F_USE_TLS | LDAP_BACK_F_TLS_CRITICAL );
        
                /* try start tls */
-               } else if ( strcasecmp( argv[0], "tls-try-start" ) == 0 ) {
-                       if ( argc != 1 ) {
-                               fprintf( stderr,
-               "%s: line %d: tls-try-start takes no arguments\n",
-                                               fname, lineno );
-                               return( 1 );
-                       }
+               } else if ( strcasecmp( argv[1], "try-start" ) == 0 ) {
                        li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
                        li->flags |= LDAP_BACK_F_USE_TLS;
        
                /* propagate start tls */
-               } else if ( strcasecmp( argv[0], "tls-propagate" ) == 0 ) {
-                       if ( argc != 1 ) {
-                               fprintf( stderr,
-               "%s: line %d: tls-propagate takes no arguments\n",
-                                               fname, lineno );
-                               return( 1 );
-                       }
+               } else if ( strcasecmp( argv[1], "propagate" ) == 0 ) {
                        li->flags |= ( LDAP_BACK_F_PROPAGATE_TLS | LDAP_BACK_F_TLS_CRITICAL );
                
                /* try start tls */
-               } else if ( strcasecmp( argv[0], "tls-try-propagate" ) == 0 ) {
-                       if ( argc != 1 ) {
-                               fprintf( stderr,
-               "%s: line %d: tls-try-propagate takes no arguments\n",
-                                               fname, lineno );
-                               return( 1 );
-                       }
+               } else if ( strcasecmp( argv[1], "try-propagate" ) == 0 ) {
                        li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
                        li->flags |= LDAP_BACK_F_PROPAGATE_TLS;
+
+               } else {
+                       fprintf( stderr,
+               "%s: line %d: \"tls <what>\": unknown argument \"%s\".\n",
+                                       fname, lineno, argv[1] );
+                       return( 1 );
                }
        
        /* remote ACL stuff... */
@@ -291,24 +279,50 @@ ldap_back_db_config(
                li->flags |= LDAP_BACK_F_SAVECRED;
 
        } else if ( strcasecmp( argv[0], "chase-referrals" ) == 0 ) {
-               if ( argc != 1 ) {
+               if ( argc != 2 ) {
                        fprintf( stderr,
-       "%s: line %d: \"chase-referrals\" takes no arguments\n",
+       "%s: line %d: \"chase-referrals\" needs 1 argument.\n",
                                        fname, lineno );
                        return( 1 );
                }
 
-               li->flags |= LDAP_BACK_F_CHASE_REFERRALS;
+               /* this is the default; we add it because the default might change... */
+               if ( strcasecmp( argv[1], "yes" ) == 0 ) {
+                       li->flags |= LDAP_BACK_F_CHASE_REFERRALS;
 
-       } else if ( strcasecmp( argv[0], "dont-chase-referrals" ) == 0 ) {
-               if ( argc != 1 ) {
+               } else if ( strcasecmp( argv[1], "no" ) == 0 ) {
+                       li->flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
+
+               } else {
+                       fprintf( stderr,
+               "%s: line %d: \"chase-referrals {yes|no}\": unknown argument \"%s\".\n",
+                                       fname, lineno, argv[1] );
+                       return( 1 );
+               }
+       
+       } else if ( strcasecmp( argv[ 0 ], "t-f-support" ) == 0 ) {
+               if ( argc != 2 ) {
                        fprintf( stderr,
-       "%s: line %d: \"dont-chase-referrals\" takes no arguments\n",
+               "%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
                                        fname, lineno );
                        return( 1 );
                }
 
-               li->flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
+               if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+                       li->flags &= ~(LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER);
+
+               } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+                       li->flags |= LDAP_BACK_F_SUPPORT_T_F;
+
+               } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
+                       li->flags |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+
+               } else {
+                       fprintf( stderr,
+       "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
+                               fname, lineno, argv[ 1 ] );
+                       return 1;
+               }
 
        /* intercept exop_who_am_i? */
        } else if ( strcasecmp( argv[0], "proxy-whoami" ) == 0 ) {
@@ -352,6 +366,7 @@ ldap_back_db_config(
                                "triggered by \"%s\" directive.\n",
                                fname, lineno, argv[ 0 ] );
 
+               /* this is the default; we add it because the default might change... */
                        li->rwm_started = 1;
 
                        return ( *be->bd_info->bi_db_config )( be, fname, lineno, argc, argv );
@@ -606,6 +621,8 @@ parse_idassert(
                ber_bvarray_add( &li->idassert_authz, &rule );
 
        } else if ( strcasecmp( argv[0], "idassert-method" ) == 0 ) {
+               char    *argv1;
+
                if ( argc < 2 ) {
                        fprintf( stderr,
        "%s: line %d: missing method in \"%s <method>\" line\n",
@@ -613,7 +630,12 @@ parse_idassert(
                        return( 1 );
                }
 
-               if ( strcasecmp( argv[1], "none" ) == 0 ) {
+               argv1 = argv[1];
+               if ( strncasecmp( argv1, "bindmethod=", STRLENOF( "bindmethod=" ) ) == 0 ) {
+                       argv1 += STRLENOF( "bindmethod=" );
+               }
+
+               if ( strcasecmp( argv1, "none" ) == 0 ) {
                        /* FIXME: is this at all useful? */
                        li->idassert_authmethod = LDAP_AUTH_NONE;
 
@@ -623,7 +645,7 @@ parse_idassert(
                                        fname, lineno, argv[0], argv[1] );
                        }
 
-               } else if ( strcasecmp( argv[1], "simple" ) == 0 ) {
+               } else if ( strcasecmp( argv1, "simple" ) == 0 ) {
                        li->idassert_authmethod = LDAP_AUTH_SIMPLE;
 
                        if ( argc != 2 ) {
@@ -632,7 +654,7 @@ parse_idassert(
                                        fname, lineno, argv[0], argv[1] );
                        }
 
-               } else if ( strcasecmp( argv[1], "sasl" ) == 0 ) {
+               } else if ( strcasecmp( argv1, "sasl" ) == 0 ) {
 #ifdef HAVE_CYRUS_SASL
                        int     arg;
 
@@ -823,6 +845,8 @@ parse_acl_auth(
                ber_str2bv( argv[1], 0, 1, &li->acl_passwd );
 
        } else if ( strcasecmp( argv[0], "acl-method" ) == 0 ) {
+               char    *argv1;
+
                if ( argc < 2 ) {
                        fprintf( stderr,
        "%s: line %d: missing method in \"%s <method>\" line\n",
@@ -830,7 +854,12 @@ parse_acl_auth(
                        return( 1 );
                }
 
-               if ( strcasecmp( argv[1], "none" ) == 0 ) {
+               argv1 = argv[1];
+               if ( strncasecmp( argv1, "bindmethod=", STRLENOF( "bindmethod=" ) ) == 0 ) {
+                       argv1 += STRLENOF( "bindmethod=" );
+               }
+
+               if ( strcasecmp( argv1, "none" ) == 0 ) {
                        /* FIXME: is this at all useful? */
                        li->acl_authmethod = LDAP_AUTH_NONE;
 
@@ -840,7 +869,7 @@ parse_acl_auth(
                                        fname, lineno, argv[0], argv[1] );
                        }
 
-               } else if ( strcasecmp( argv[1], "simple" ) == 0 ) {
+               } else if ( strcasecmp( argv1, "simple" ) == 0 ) {
                        li->acl_authmethod = LDAP_AUTH_SIMPLE;
 
                        if ( argc != 2 ) {
@@ -849,7 +878,7 @@ parse_acl_auth(
                                        fname, lineno, argv[0], argv[1] );
                        }
 
-               } else if ( strcasecmp( argv[1], "sasl" ) == 0 ) {
+               } else if ( strcasecmp( argv1, "sasl" ) == 0 ) {
 #ifdef HAVE_CYRUS_SASL
                        int     arg;
 
index 328e3ceaa8ecb1506205e4dd0d5df7ff77bcb19f..7286cd222a76d0e2c334e7f69f9cdc74ba1388f3 100644 (file)
@@ -113,6 +113,9 @@ ldap_back_db_init( Backend *be )
        /* initialize flags */
        li->flags = LDAP_BACK_F_CHASE_REFERRALS;
 
+       /* initialize version */
+       li->version = LDAP_VERSION3;
+
        ldap_pvt_thread_mutex_init( &li->conn_mutex );
 
        be->be_private = li;
@@ -121,6 +124,73 @@ ldap_back_db_init( Backend *be )
        return 0;
 }
 
+int
+ldap_back_discover_t_f_support( const char *uri, int version )
+{
+       LDAP            *ld;
+       LDAPMessage     *res = NULL, *entry;
+       int             rc, i;
+       struct berval   cred = BER_BVC( "" ),
+                       absoluteFilters = BER_BVC( LDAP_FEATURE_ABSOLUTE_FILTERS ),
+                       **values = NULL;
+       char            *attrs[ 2 ] = { "supportedFeatures", NULL };
+
+       rc = ldap_initialize( &ld, uri );
+       if ( rc != LDAP_SUCCESS ) {
+               return rc;
+       }
+
+       rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
+       if ( rc != LDAP_SUCCESS ) {
+               goto done;
+       }
+
+       rc = ldap_sasl_bind_s( ld, "", LDAP_SASL_SIMPLE,
+                       &cred, NULL, NULL, NULL );
+       if ( rc != LDAP_SUCCESS ) {
+               goto done;
+       }
+
+       rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, "(objectClass=*)",
+                       attrs, 0, NULL, NULL, NULL, 0, &res );
+       if ( rc != LDAP_SUCCESS ) {
+               goto done;
+       }
+
+       entry = ldap_first_entry( ld, res );
+       if ( entry == NULL ) {
+               goto done;
+       }
+
+       values = ldap_get_values_len( ld, entry, attrs[ 0 ] );
+       if ( values == NULL ) {
+               rc = LDAP_NO_SUCH_ATTRIBUTE;
+               goto done;
+       }
+
+       for ( i = 0; values[ i ] != NULL; i++ ) {
+               if ( bvmatch( &absoluteFilters, values[ i ] ) ) {
+                       rc = LDAP_COMPARE_TRUE;
+                       goto done;
+               }
+       }
+
+       rc = LDAP_COMPARE_FALSE;
+
+done:;
+       if ( values != NULL ) {
+               ldap_value_free_len( values );
+       }
+
+       if ( res != NULL ) {
+               ldap_msgfree( res );
+       }
+
+       ldap_unbind_ext( ld, NULL, NULL );
+
+       return rc;
+}
+
 int
 ldap_back_db_open( BackendDB *be )
 {
@@ -175,6 +245,17 @@ ldap_back_db_open( BackendDB *be )
        }
 #endif /* SLAPD_MONITOR */
 
+       if ( li->flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER ) {
+               int             rc;
+
+               li->flags &= ~LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+
+               rc = ldap_back_discover_t_f_support( li->url, li->version );
+               if ( rc == LDAP_COMPARE_TRUE ) {
+                       li->flags |= LDAP_BACK_F_SUPPORT_T_F;
+               }
+       }
+
        return 0;
 }
 
index c391347baa2f55ce726d71cf13f0503350b3d7fe..3ee82956df15a42ee545a399c0faf8eabdc1dba8 100644 (file)
@@ -46,6 +46,8 @@ ldap_back_search(
                Operation       *op,
                SlapReply       *rs )
 {
+       struct ldapinfo *li = (struct ldapinfo *) op->o_bd->be_private;
+
        struct ldapconn *lc;
        struct timeval  tv;
        LDAPMessage     *res,
@@ -54,7 +56,11 @@ ldap_back_search(
                        msgid; 
        struct berval   match = BER_BVNULL;
        int             i;
-       char            **attrs = NULL;
+       char            **attrs = NULL,
+                       *filter = NULL;
+       static struct berval
+                       bv_true = BER_BVC( "(?=true)" ),
+                       bv_false = BER_BVC( "(?=false)" );
        int             dontfreetext = 0;
        int             do_retry = 1;
        LDAPControl     **ctrls = NULL;
@@ -109,10 +115,20 @@ ldap_back_search(
                dontfreetext = 1;
                goto finish;
        }
-       
+
+       /* deal with <draft-zeilenga-ldap-t-f> filters */
+       filter = op->ors_filterstr.bv_val;
+       if ( li->flags & LDAP_BACK_F_SUPPORT_T_F ) {
+               if ( bvmatch( &op->ors_filterstr, &bv_true ) ) {
+                       filter = "(&)";
+               } else if ( bvmatch( &op->ors_filterstr, &bv_false ) ) {
+                       filter = "(|)";
+               }
+       }
+
 retry:
        rs->sr_err = ldap_search_ext( lc->lc_ld, op->o_req_ndn.bv_val,
-                       op->ors_scope, op->ors_filterstr.bv_val,
+                       op->ors_scope, filter,
                        attrs, op->ors_attrsonly, ctrls, NULL,
                        tv.tv_sec ? &tv : NULL,
                        op->ors_slimit, &msgid );