From c80eb3488868d2808a5ee29b76b0f38059df2e04 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Thu, 5 May 2005 00:07:17 +0000 Subject: [PATCH] honor T-F filters (ITS#3706) and some cleanup --- servers/slapd/back-ldap/back-ldap.h | 6 ++ servers/slapd/back-ldap/config.c | 115 +++++++++++++++++----------- servers/slapd/back-ldap/init.c | 81 ++++++++++++++++++++ servers/slapd/back-ldap/search.c | 22 +++++- 4 files changed, 178 insertions(+), 46 deletions(-) diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index 0a14779929..beb560c3e6 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -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; diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index 6cd07ba40a..e570e3b0e4 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -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 \" 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 \": 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 \" 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 \" 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; diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index 328e3ceaa8..7286cd222a 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -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; } diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index c391347baa..3ee82956df 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -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 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 ); -- 2.39.5