X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-meta%2Fbind.c;h=4551173ddde1dc1c4c891951df4a28fa5f238b99;hb=02153708a01b580c69e57e41da6243d165bd43c1;hp=219e8b96d766db25e8f24ba05af58fab5133f9ea;hpb=74fa239a201cd2d785fe34bdbaf6804161bdb231;p=openldap diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index 219e8b96d7..4551173ddd 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -82,45 +82,59 @@ meta_back_bind( 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 )); + "meta_back_bind: no target for dn %s.\n", + 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; @@ -140,17 +154,27 @@ meta_back_bind( */ #ifdef NEW_LOGGING LDAP_LOG(( "backend", LDAP_LEVEL_WARNING, -"==>meta_back_bind: more that one candidate is attempting to bind ...%s%s%s\n" )); + "==>meta_back_bind: more than one" + " candidate is attempting to bind" + " ...\n" )); #else /* !NEW_LOGGING */ Debug( LDAP_DEBUG_ANY, -"==>meta_back_bind: more that one candidate is attempting to bind ...%s%s%s\n", - "", "", "" ); + "==>meta_back_bind: more than one" + " candidate is attempting to bind" + " ...\n%s%s%s", + "", "", "" ); #endif /* !NEW_LOGGING */ } - - lerr = meta_back_do_single_bind( op, 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 ); @@ -159,16 +183,26 @@ meta_back_bind( } } - 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; } /* @@ -178,11 +212,10 @@ meta_back_bind( */ int meta_back_do_single_bind( - Operation *op, 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 @@ -195,43 +228,44 @@ meta_back_do_single_bind( * 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->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; case REWRITE_REGEXEC_UNWILLING: - send_ldap_result( lc->conn, op, LDAP_UNWILLING_TO_PERFORM, - NULL, "Unwilling to perform", - NULL, NULL ); - /* continues to next case */ + return LDAP_UNWILLING_TO_PERFORM; case REWRITE_REGEXEC_ERR: - return -1; + 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 ); } @@ -247,6 +281,13 @@ meta_back_dobind( struct metaconn *lc, Operation *op ) 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; @@ -270,25 +311,31 @@ meta_back_dobind( struct metaconn *lc, Operation *op ) * (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 ) { - /* - * This way, the first bind error would be fatal ... - */ +#ifdef NEW_LOGGING + LDAP_LOG(( "backend", LDAP_LEVEL_WARNING, + "meta_back_dobind: (anonymous)" + " bind as \"%s\" failed" + " with error \"%s\"\n", + 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 */ /* * null cred bind should always succeed * 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 ); @@ -302,18 +349,48 @@ meta_back_dobind( struct metaconn *lc, Operation *op ) 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 ) { /* @@ -328,17 +405,34 @@ meta_back_op_result( struct metaconn *lc, Operation *op ) LDAP_OPT_MATCHED_DN, &match ); err = ldap_back_map_result( err ); +#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 : "" ) )); +#else /* !NEW_LOGGING */ + Debug(LDAP_DEBUG_ANY, + "==> 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" + * FIXME: need to rewrite "match" (need rwinfo) */ - send_ldap_result( lc->conn, op, err, match, msg, - NULL, NULL ); - - Debug(LDAP_DEBUG_ANY, -"==> meta_back_op_result: target <%d> sending msg \"%s\" (matched \"%s\")\n", - i, - ( msg ? msg : "" ), - ( match ? match : "" ) ); + switch ( err ) { + default: + rerr = err; + rmsg = msg; + msg = NULL; + rmatch = match; + match = NULL; + break; + } /* better test the pointers before freeing? */ if ( match ) { @@ -347,10 +441,11 @@ meta_back_op_result( struct metaconn *lc, Operation *op ) 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 ); }