Backend *be,
Connection *conn,
Operation *op,
- const char *dn,
- const char *ndn,
+ struct berval *dn,
+ struct berval *ndn,
int method,
struct berval *cred,
- char **edn
+ struct berval *edn
)
{
struct metainfo *li = ( struct metainfo * )be->be_private;
struct metaconn *lc;
- int rc = -1, i, gotit = 0, ndnlen, err = LDAP_SUCCESS;
+ int rc = -1, i, gotit = 0, ndnlen, isroot = 0;
+ int op_type = META_OP_ALLOW_MULTIPLE;
+ int err = LDAP_SUCCESS;
+
+ struct berval *realdn = dn;
+ struct berval *realndn = ndn;
+ struct berval *realcred = cred;
+ int realmethod = method;
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
- "meta_back_bind: dn: %s.\n", dn ));
+ "meta_back_bind: dn: %s.\n", dn->bv_val ));
#else /* !NEW_LOGGING */
- Debug( LDAP_DEBUG_ARGS, "meta_back_bind: dn: %s.\n%s%s", dn, "", "" );
+ Debug( LDAP_DEBUG_ARGS, "meta_back_bind: dn: %s.\n%s%s", dn->bv_val, "", "" );
#endif /* !NEW_LOGGING */
- *edn = NULL;
-
- lc = meta_back_getconn( li, conn, op, META_OP_ALLOW_MULTIPLE,
- ndn, NULL );
+ if ( method == LDAP_AUTH_SIMPLE
+ && be_isroot_pw( be, conn, ndn, cred ) ) {
+ isroot = 1;
+ ber_dupbv( edn, be_root_dn( be ) );
+ op_type = META_OP_REQUIRE_ALL;
+ }
+ lc = meta_back_getconn( li, conn, op, op_type, ndn, NULL );
if ( !lc ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_NOTICE,
"meta_back_bind: no target for dn %s.\n",
- dn ));
+ dn->bv_val ));
#else /* !NEW_LOGGING */
Debug( LDAP_DEBUG_ANY,
"meta_back_bind: no target for dn %s.\n%s%s",
- dn, "", "");
+ dn->bv_val, "", "");
#endif /* !NEW_LOGGING */
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return -1;
}
/*
* Each target is scanned ...
*/
- ndnlen = strlen( ndn );
+ lc->bound_target = META_BOUND_NONE;
+ ndnlen = ndn->bv_len;
for ( i = 0; i < li->ntargets; i++ ) {
int lerr;
#endif /* !NEW_LOGGING */
}
-
- lerr = meta_back_do_single_bind( li, lc, dn, ndn, cred,
- method, i );
+ if ( isroot && li->targets[ i ]->pseudorootdn != NULL ) {
+ realdn = li->targets[ i ]->pseudorootdn;
+ realndn = li->targets[ i ]->pseudorootdn;
+ realcred = li->targets[ i ]->pseudorootpw;
+ realmethod = LDAP_AUTH_SIMPLE;
+ }
+
+ lerr = meta_back_do_single_bind( li, lc,
+ realdn, realndn, realcred, realmethod, i );
if ( lerr != LDAP_SUCCESS ) {
err = lerr;
( void )meta_clear_one_candidate( lc->conns[ i ], 1 );
}
}
- if ( rc != LDAP_SUCCESS && err != LDAP_SUCCESS ) {
+ if ( isroot ) {
+ lc->bound_target = META_BOUND_ALL;
+ }
+
+ /*
+ * rc is LDAP_SUCCESS if at least one bind succeeded,
+ * err is the last error that occurred during a bind;
+ * if at least (and at most?) one bind succeedes, fine.
+ */
+ if ( rc != LDAP_SUCCESS /* && err != LDAP_SUCCESS */ ) {
/*
* deal with bind failure ...
*/
err = ldap_back_map_result( err );
- send_ldap_result( conn, op, err, NULL, "", NULL, NULL );
+ send_ldap_result( conn, op, err, NULL, NULL, NULL, NULL );
+ return -1;
}
- return LDAP_SUCCESS;
+ return 0;
}
/*
meta_back_do_single_bind(
struct metainfo *li,
struct metaconn *lc,
- const char *dn,
- const char *ndn,
+ struct berval *dn,
+ struct berval *ndn,
struct berval *cred,
int method,
int candidate
* Rewrite the bind dn if needed
*/
switch ( rewrite_session( li->targets[ candidate ]->rwinfo,
- "bindDn", dn, lc->conn, &mdn ) ) {
+ "bindDn", dn->bv_val, lc->conn, &mdn ) ) {
case REWRITE_REGEXEC_OK:
if ( mdn == NULL ) {
- mdn = ( char * )dn;
+ mdn = ( char * )dn->bv_val;
}
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
- "[rw] bindDn: \"%s\" -> \"%s\"\n", dn, mdn ));
+ "[rw] bindDn: \"%s\" -> \"%s\"\n", dn->bv_val, mdn ));
#else /* !NEW_LOGGING */
Debug( LDAP_DEBUG_ARGS,
"rw> bindDn: \"%s\" -> \"%s\"\n%s",
- dn, mdn, "" );
+ dn->bv_val, mdn, "" );
#endif /* !NEW_LOGGING */
break;
return LDAP_OPERATIONS_ERROR;
}
- rc = ldap_bind_s( lc->conns[ candidate ]->ld, mdn,
- cred->bv_val, method );
+ rc = ldap_bind_s( lc->conns[ candidate ]->ld, mdn, cred->bv_val, method );
if ( rc != LDAP_SUCCESS ) {
rc = ldap_back_map_result( rc );
} else {
- lc->conns[ candidate ]->bound_dn = ch_strdup( dn );
+ lc->conns[ candidate ]->bound_dn = ber_bvdup( dn );
lc->conns[ candidate ]->bound = META_BOUND;
lc->bound_target = candidate;
if ( li->cache.ttl != META_DNCACHE_DISABLED
- && ndn[ 0 ] != '\0' ) {
+ && ndn->bv_len != 0 ) {
( void )meta_dncache_update_entry( &li->cache,
- ch_strdup( ndn ), candidate );
+ ber_bvdup( ndn ), candidate );
}
}
- if ( mdn != dn ) {
+ if ( mdn != dn->bv_val ) {
free( mdn );
}
struct metasingleconn **lsc;
int bound = 0, i;
+ /*
+ * all the targets are bound as pseudoroot
+ */
+ if ( lc->bound_target == META_BOUND_ALL ) {
+ return 1;
+ }
+
for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
int rc;
* (note: if the target was already bound, the anonymous
* bind clears the previous bind).
*/
- rc = ldap_bind_s( lsc[ 0 ]->ld, lsc[ 0 ]->bound_dn,
+ rc = ldap_bind_s( lsc[ 0 ]->ld, lsc[ 0 ]->bound_dn->bv_val,
NULL, LDAP_AUTH_SIMPLE );
if ( rc != LDAP_SUCCESS ) {
"meta_back_dobind: (anonymous)"
" bind as \"%s\" failed"
" with error \"%s\"\n",
- lsc[ 0 ]->bound_dn,
+ lsc[ 0 ]->bound_dn->bv_val,
ldap_err2string( rc ) ));
#else /* !NEW_LOGGING */
Debug( LDAP_DEBUG_ANY,
- "==>meta_back_dobind: (anonymous) bind as \"%s\" failed"
- " with error \"%s\"\n%s",
- lsc[ 0 ]->bound_dn,
- ldap_err2string( rc ), "" );
+ "==>meta_back_dobind: (anonymous)"
+ " bind as \"%s\" failed"
+ " with error \"%s\"\n%s",
+ lsc[ 0 ]->bound_dn->bv_val,
+ ldap_err2string( rc ), "" );
#endif /* !NEW_LOGGING */
/*
* as anonymous, so a failure means
* the target is no longer candidate possibly
* due to technical reasons (remote host down?)
- *
* so better clear the handle
*/
( void )meta_clear_one_candidate( lsc[ 0 ], 1 );
return( bound > 0 );
}
+/*
+ *
+ */
+int
+meta_back_is_valid( struct metaconn *lc, int candidate )
+{
+ struct metasingleconn **lsc;
+ int i;
+
+ assert( lc );
+
+ if ( candidate < 0 ) {
+ return 0;
+ }
+
+ for ( i = 0, lsc = lc->conns;
+ lsc[ 0 ] != NULL && i < candidate;
+ ++i, ++lsc );
+
+ if ( lsc[ 0 ] ) {
+ return( lsc[ 0 ]->ld != NULL );
+ }
+
+ return 0;
+}
+
/*
* FIXME: error return must be handled in a cleaner way ...
*/
int
meta_back_op_result( struct metaconn *lc, Operation *op )
{
- int i, err = LDAP_SUCCESS;
- char *msg = NULL;
- char *match = NULL;
+ int i, rerr = LDAP_SUCCESS;
struct metasingleconn **lsc;
+ char *rmsg = NULL;
+ char *rmatch = NULL;
for ( i = 0, lsc = lc->conns; lsc[ 0 ] != NULL; ++i, ++lsc ) {
+ int err = LDAP_SUCCESS;
+ char *msg = NULL;
+ char *match = NULL;
+
ldap_get_option( lsc[ 0 ]->ld, LDAP_OPT_ERROR_NUMBER, &err );
if ( err != LDAP_SUCCESS ) {
/*
LDAP_OPT_MATCHED_DN, &match );
err = ldap_back_map_result( err );
- /*
- * FIXME: need to rewrite "match"
- */
- send_ldap_result( lc->conn, op, err, match, msg,
- NULL, NULL );
-
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_DEBUG_NOTICE,
- "meta_back_op_result: target"
- " <%d> sending msg \"%s\""
- " (matched \"%s\")\n",
- i, ( msg ? msg : "" ),
- ( match ? match : "" ) ));
+ "meta_back_op_result: target"
+ " <%d> sending msg \"%s\""
+ " (matched \"%s\")\n",
+ i, ( msg ? msg : "" ),
+ ( match ? match : "" ) ));
#else /* !NEW_LOGGING */
Debug(LDAP_DEBUG_ANY,
-"==> meta_back_op_result: target <%d> sending msg \"%s\" (matched \"%s\")\n",
- i,
- ( msg ? msg : "" ),
- ( match ? match : "" ) );
+ "==> meta_back_op_result: target"
+ " <%d> sending msg \"%s\""
+ " (matched \"%s\")\n",
+ i, ( msg ? msg : "" ),
+ ( match ? match : "" ) );
#endif /* !NEW_LOGGING */
+ /*
+ * FIXME: need to rewrite "match" (need rwinfo)
+ */
+ switch ( err ) {
+ default:
+ rerr = err;
+ rmsg = msg;
+ msg = NULL;
+ rmatch = match;
+ match = NULL;
+ break;
+ }
+
/* better test the pointers before freeing? */
if ( match ) {
free( match );
if ( msg ) {
free( msg );
}
- return -1;
}
}
- return ( err == LDAP_SUCCESS ) ? 0 : -1;
+ send_ldap_result( lc->conn, op, rerr, rmatch, rmsg, NULL, NULL );
+
+ return ( ( rerr == LDAP_SUCCESS ) ? 0 : -1 );
}