X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=servers%2Fslapd%2Fbackend.c;h=b36b65c3d1030cefeb69d3c5157580914f744089;hb=5b526d2544c512f0a7233439efa53dcc5dc02672;hp=5ee85ecc4ac93dbf2f1dc4af25c2461ecd58072f;hpb=ea560284f073a034023a813c0d71d0d4febdd751;p=openldap diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 5ee85ecc4a..b36b65c3d1 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2007 The OpenLDAP Foundation. + * Copyright 1998-2008 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,6 +34,7 @@ #include #include "slap.h" +#include "config.h" #include "lutil.h" #include "lber_pvt.h" @@ -189,7 +190,7 @@ backend_set_controls( BackendDB *be ) } /* startup a specific backend database */ -int backend_startup_one(Backend *be) +int backend_startup_one(Backend *be, ConfigReply *cr) { int rc = 0; @@ -208,8 +209,19 @@ int backend_startup_one(Backend *be) /* set database controls */ (void)backend_set_controls( be ); +#if 0 + if ( !BER_BVISEMPTY( &be->be_rootndn ) + && select_backend( &be->be_rootndn, 0 ) == be + && BER_BVISNULL( &be->be_rootpw ) ) + { + /* warning: if rootdn entry is created, + * it can take rootdn privileges; + * set empty rootpw to prevent */ + } +#endif + if ( be->bd_info->bi_db_open ) { - rc = be->bd_info->bi_db_open( be ); + rc = be->bd_info->bi_db_open( be, cr ); if ( rc == 0 ) { (void)backend_set_controls( be ); @@ -228,6 +240,7 @@ int backend_startup(Backend *be) int i; int rc = 0; BackendInfo *bi; + ConfigReply cr={0, ""}; if( ! ( nBackendDB > 0 ) ) { /* no databases */ @@ -251,12 +264,12 @@ int backend_startup(Backend *be) /* append global access controls */ acl_append( &be->be_acl, frontendDB->be_acl, -1 ); - return backend_startup_one( be ); + return backend_startup_one( be, &cr ); } /* open frontend, if required */ if ( frontendDB->bd_info->bi_db_open ) { - rc = frontendDB->bd_info->bi_db_open( frontendDB ); + rc = frontendDB->bd_info->bi_db_open( frontendDB, NULL ); if ( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "backend_startup: bi_db_open(frontend) failed! (%d)\n", @@ -300,7 +313,7 @@ int backend_startup(Backend *be) /* append global access controls */ acl_append( &be->be_acl, frontendDB->be_acl, -1 ); - rc = backend_startup_one( be ); + rc = backend_startup_one( be, &cr ); if ( rc ) return rc; } @@ -336,7 +349,7 @@ int backend_shutdown( Backend *be ) } if ( be->bd_info->bi_db_close ) { - be->bd_info->bi_db_close( be ); + be->bd_info->bi_db_close( be, NULL ); } if( be->bd_info->bi_close ) { @@ -349,7 +362,7 @@ int backend_shutdown( Backend *be ) /* close each backend database */ LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { if ( be->bd_info->bi_db_close ) { - be->bd_info->bi_db_close( be ); + be->bd_info->bi_db_close( be, NULL ); } if(rc != 0) { @@ -373,7 +386,7 @@ int backend_shutdown( Backend *be ) /* close frontend, if required */ if ( frontendDB->bd_info->bi_db_close ) { - rc = frontendDB->bd_info->bi_db_close ( frontendDB ); + rc = frontendDB->bd_info->bi_db_close ( frontendDB, NULL ); if ( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "backend_startup: bi_db_close(frontend) failed! (%d)\n", @@ -411,7 +424,7 @@ backend_stopdown_one( BackendDB *bd ) } if ( bd->bd_info->bi_db_destroy ) { - bd->bd_info->bi_db_destroy( bd ); + bd->bd_info->bi_db_destroy( bd, NULL ); } } @@ -476,7 +489,7 @@ int backend_destroy(void) bd = frontendDB; if ( bd ) { if ( bd->bd_info->bi_db_destroy ) { - bd->bd_info->bi_db_destroy( bd ); + bd->bd_info->bi_db_destroy( bd, NULL ); } ber_bvarray_free( bd->be_suffix ); ber_bvarray_free( bd->be_nsuffix ); @@ -547,7 +560,8 @@ BackendDB * backend_db_init( const char *type, BackendDB *b0, - int idx ) + int idx, + ConfigReply *cr) { BackendInfo *bi = backend_info(type); BackendDB *be = b0; @@ -586,7 +600,7 @@ backend_db_init( be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; if ( bi->bi_db_init ) { - rc = bi->bi_db_init( be ); + rc = bi->bi_db_init( be, cr ); } if ( rc != 0 ) { @@ -611,12 +625,12 @@ be_db_close( void ) LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { if ( be->bd_info->bi_db_close ) { - be->bd_info->bi_db_close( be ); + be->bd_info->bi_db_close( be, NULL ); } } if ( frontendDB->bd_info->bi_db_close ) { - frontendDB->bd_info->bi_db_close( frontendDB ); + frontendDB->bd_info->bi_db_close( frontendDB, NULL ); } } @@ -624,12 +638,11 @@ be_db_close( void ) Backend * select_backend( struct berval * dn, - int manageDSAit, int noSubs ) { int j; ber_len_t len, dnlen = dn->bv_len; - Backend *be, *b2 = NULL; + Backend *be; LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { if ( be->be_nsuffix == NULL || SLAP_DBHIDDEN( be )) { @@ -663,39 +676,12 @@ select_backend( if ( strcmp( be->be_nsuffix[j].bv_val, &dn->bv_val[dnlen-len] ) == 0 ) { - if ( b2 == NULL ) { - b2 = be; - -#if 0 - /* causes ITS#4986: a catchall relay - * database with empty suffix points - * to another database; operations - * directed to a specific database - * fail if manageDSAit is set. - * Not clear what's the purpose - * of this test */ - if ( manageDSAit && len == dnlen && - !SLAP_GLUE_SUBORDINATE( be ) ) - { - continue; - } -#endif - - } else { - /* If any parts of the tree are glued, use the first - * match regardless of manageDSAit. Otherwise use the - * last match. - */ - if( !( SLAP_DBFLAGS( be ) & ( SLAP_DBFLAG_GLUE_INSTANCE | - SLAP_DBFLAG_GLUE_SUBORDINATE ))) - b2 = be; - } - return b2; + return be; } } } - return b2; + return be; } int @@ -718,6 +704,26 @@ be_issuffix( return 0; } +int +be_issubordinate( + Backend *be, + struct berval *bvsubordinate ) +{ + int i; + + if ( be->be_nsuffix == NULL ) { + return 0; + } + + for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) { + if ( dnIsSuffix( bvsubordinate, &be->be_nsuffix[i] ) ) { + return 1; + } + } + + return 0; +} + int be_isroot_dn( Backend *be, struct berval *ndn ) { @@ -770,28 +776,82 @@ be_isroot( Operation *op ) int be_isroot_pw( Operation *op ) { - int result; + return be_rootdn_bind( op, NULL ) == LDAP_SUCCESS; +} - if ( ! be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) { - return 0; +/* + * checks if binding as rootdn + * + * return value: + * SLAP_CB_CONTINUE if not the rootdn, or if rootpw is null + * LDAP_SUCCESS if rootdn & rootpw + * LDAP_INVALID_CREDENTIALS if rootdn & !rootpw + * + * if rs != NULL + * if LDAP_SUCCESS, op->orb_edn is set + * if LDAP_INVALID_CREDENTIALS, response is sent to client + */ +int +be_rootdn_bind( Operation *op, SlapReply *rs ) +{ + int rc; +#ifdef SLAPD_SPASSWD + void *old_authctx = NULL; +#endif + + assert( op->o_tag == LDAP_REQ_BIND ); + assert( op->orb_method == LDAP_AUTH_SIMPLE ); + + if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) { + return SLAP_CB_CONTINUE; + } + + if ( BER_BVISNULL( &op->o_bd->be_rootpw ) ) { + /* give the database a chance */ + return SLAP_CB_CONTINUE; } if ( BER_BVISEMPTY( &op->o_bd->be_rootpw ) ) { - return 0; + /* rootdn bind explicitly disallowed */ + rc = LDAP_INVALID_CREDENTIALS; + if ( rs ) { + goto send_result; + } + + return rc; } #ifdef SLAPD_SPASSWD - ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, - op->o_conn->c_sasl_authctx, NULL ); + ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind, + op->o_conn->c_sasl_authctx, 0, &old_authctx, NULL ); #endif - result = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL ); + rc = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL ); #ifdef SLAPD_SPASSWD - ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, NULL, NULL ); + ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind, + old_authctx, 0, NULL, NULL ); #endif - return result == 0; + rc = ( rc == 0 ? LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS ); + if ( rs ) { +send_result:; + rs->sr_err = rc; + + Debug( LDAP_DEBUG_TRACE, "%s: rootdn=\"%s\" bind%s\n", + op->o_log_prefix, op->o_bd->be_rootdn.bv_val, + rc == LDAP_SUCCESS ? " succeeded" : " failed" ); + + if ( rc == LDAP_SUCCESS ) { + /* Set to the pretty rootdn */ + ber_dupbv( &op->orb_edn, &op->o_bd->be_rootdn ); + + } else { + send_ldap_result( op, rs ); + } + } + + return rc; } int @@ -1290,7 +1350,7 @@ fe_acl_group( GroupAssertion *g; Backend *be = op->o_bd; - op->o_bd = select_backend( gr_ndn, 0, 0 ); + op->o_bd = select_backend( gr_ndn, 0 ); for ( g = op->o_groups; g; g = g->ga_next ) { if ( g->ga_be != op->o_bd || g->ga_oc != group_oc || @@ -1408,7 +1468,7 @@ fe_acl_group( if ( user == NULL ) { int rc2; - op->o_bd = select_backend( op_ndn, 0, 0 ); + op->o_bd = select_backend( op_ndn, 0 ); op->o_private = NULL; rc2 = be_entry_get_rw( op, op_ndn, NULL, NULL, 0, &user ); user_priv = op->o_private; @@ -1445,10 +1505,10 @@ loopit: op->o_bd = b2; } else { - rc = value_find_ex( group_at, + rc = attr_valfind( a, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, - a->a_nvals, op_ndn, op->o_tmpmemctx ); + op_ndn, NULL, op->o_tmpmemctx ); if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) { rc = LDAP_COMPARE_FALSE; } @@ -1527,7 +1587,7 @@ fe_acl_attribute( AccessControlState acl_state = ACL_STATE_INIT; Backend *be = op->o_bd; - op->o_bd = select_backend( edn, 0, 0 ); + op->o_bd = select_backend( edn, 0 ); if ( target && dn_match( &target->e_nname, edn ) ) { e = target; @@ -1592,9 +1652,7 @@ fe_acl_attribute( goto freeit; } - for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) - ; - + i = a->a_numvals; v = op->o_tmpalloc( sizeof(struct berval) * ( i + 1 ), op->o_tmpmemctx ); for ( i = 0, j = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) @@ -1680,7 +1738,7 @@ backend_access( assert( edn != NULL ); assert( access > ACL_NONE ); - op->o_bd = select_backend( edn, 0, 0 ); + op->o_bd = select_backend( edn, 0 ); if ( target && dn_match( &target->e_nname, edn ) ) { e = target; @@ -1772,7 +1830,7 @@ fe_aux_operational( SlapReply *rs ) { Attribute **ap; - int rc = 0; + int rc = LDAP_SUCCESS; for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) /* just count them */ ; @@ -1802,7 +1860,7 @@ fe_aux_operational( BackendDB *be_orig = op->o_bd; /* Let the overlays have a chance at this */ - op->o_bd = select_backend( &op->o_req_ndn, 0, 0 ); + op->o_bd = select_backend( &op->o_req_ndn, 0 ); if ( op->o_bd != NULL && !be_match( op->o_bd, frontendDB ) && ( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) && op->o_bd->be_operational != NULL )