From: Pierangelo Masarati Date: Thu, 15 Apr 2010 05:26:21 +0000 (+0000) Subject: allow to specify a per-database list of attributes that need to be always collected... X-Git-Tag: MIGRATION_CVS2GIT~623 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=9d2e03f0527b31ac2fc994fddb7d858d010d566d;p=openldap allow to specify a per-database list of attributes that need to be always collected, even if not explicitly requested by clients (addresses ITS#6513) --- diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5 index 5048a8a996..69e024d6cd 100644 --- a/doc/man/man5/slapd-config.5 +++ b/doc/man/man5/slapd-config.5 @@ -446,6 +446,20 @@ upon StartTLS operation receipt. disallows the StartTLS operation if authenticated (see also .BR tls_2_anon ). .TP +.B olcExtraAttrs: +Lists what attributes need to be added to search requests. +Local storage backends return the entire entry to the frontend. +The frontend takes care of only returning the requested attributes +that are allowed by ACLs. +However, features like access checking and so may need specific +attributes that are not automatically returned by remote storage +backends, like proxy backends and so on. +.B +is an attribute that is needed for internal purposes +and thus always needs to be collected, even when not explicitly +requested by clients. +This attribute is multi-valued. +.TP .B olcGentleHUP: { TRUE | FALSE } A SIGHUP signal will only cause a 'gentle' shutdown-attempt: .B Slapd diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index 1217610706..4bfd01d6dd 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -1216,6 +1216,19 @@ by default. See the manual page for more details on ACL requirements for Add operations. .TP +.B extra_attrs +Lists what attributes need to be added to search requests. +Local storage backends return the entire entry to the frontend. +The frontend takes care of only returning the requested attributes +that are allowed by ACLs. +However, features like access checking and so may need specific +attributes that are not automatically returned by remote storage +backends, like proxy backends and so on. +.B +is a list of attributes that are needed for internal purposes +and thus always need to be collected, even when not explicitly +requested by clients. +.TP .B hidden on | off Controls whether the database will be used to answer queries. A database that is hidden will never be diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index e2125e82b0..f168a87a5d 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -163,7 +163,7 @@ ldap_back_search( msgid; struct berval match = BER_BVNULL, filter = BER_BVNULL; - int i; + int i, x; char **attrs = NULL; int freetext = 0, freefilter = 0; int do_retry = 1, dont_retry = 0; @@ -191,22 +191,48 @@ ldap_back_search( LDAP_BACK_TV_SET( &tv ); } + i = 0; if ( op->ors_attrs ) { - for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) + for ( ; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) /* just count attrs */ ; + } + + x = 0; + if ( op->o_bd->be_extra_anlist ) { + for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) + /* just count attrs */ ; + } - attrs = op->o_tmpalloc( ( i + 1 )*sizeof( char * ), + if ( i > 0 || x > 0 ) { + int j = 0; + + attrs = op->o_tmpalloc( ( i + x + 1 )*sizeof( char * ), op->o_tmpmemctx ); if ( attrs == NULL ) { rs->sr_err = LDAP_NO_MEMORY; rc = -1; goto finish; } - - for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) { - attrs[ i ] = op->ors_attrs[i].an_name.bv_val; + + if ( i > 0 ) { + for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++, j++ ) { + attrs[ j ] = op->ors_attrs[i].an_name.bv_val; + } + } + + if ( x > 0 ) { + for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++, j++ ) { + if ( op->o_bd->be_extra_anlist[x].an_desc && + ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, op->ors_attrs ) ) + { + continue; + } + + attrs[ j ] = op->o_bd->be_extra_anlist[x].an_name.bv_val; + } } - attrs[ i ] = NULL; + + attrs[ j ] = NULL; } ctrls = op->o_ctrls; diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index ee14f97dcd..52276bc722 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -114,11 +114,11 @@ ldap_back_map_filter( int ldap_back_map_attrs( + Operation *op, struct ldapmap *at_map, AttributeName *a, int remap, - char ***mapped_attrs, - void *memctx ); + char ***mapped_attrs ); extern int ldap_back_map_config( struct ldapmap *oc_map, diff --git a/servers/slapd/back-meta/map.c b/servers/slapd/back-meta/map.c index 7df929eb41..9e6439c573 100644 --- a/servers/slapd/back-meta/map.c +++ b/servers/slapd/back-meta/map.c @@ -174,42 +174,73 @@ ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv, int ldap_back_map_attrs( + Operation *op, struct ldapmap *at_map, AttributeName *an, int remap, - char ***mapped_attrs, - void *memctx ) + char ***mapped_attrs ) { - int i, j; + int i, x, j; char **na; struct berval mapped; - if ( an == NULL ) { + if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) { *mapped_attrs = NULL; return LDAP_SUCCESS; } - for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) - /* */ ; + i = 0; + if ( an != NULL ) { + for ( ; !BER_BVISNULL( &an[i].an_name ); i++ ) + /* */ ; + } + + x = 0; + if ( op->o_bd->be_extra_anlist != NULL ) { + for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) + /* */ ; + } - na = (char **)ber_memcalloc_x( i + 1, sizeof(char *), memctx ); + assert( i > 0 || x > 0 ); + + na = (char **)ber_memcalloc_x( i + x + 1, sizeof(char *), op->o_tmpmemctx ); if ( na == NULL ) { *mapped_attrs = NULL; return LDAP_NO_MEMORY; } - for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) { - ldap_back_map( at_map, &an[i].an_name, &mapped, remap ); - if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) { - na[j++] = mapped.bv_val; + j = 0; + if ( i > 0 ) { + for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) { + ldap_back_map( at_map, &an[i].an_name, &mapped, remap ); + if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) { + na[j++] = mapped.bv_val; + } + } + } + + if ( x > 0 ) { + for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) { + if ( op->o_bd->be_extra_anlist[x].an_desc && + ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, an ) ) + { + continue; + } + + ldap_back_map( at_map, &op->o_bd->be_extra_anlist[x].an_name, &mapped, remap ); + if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) { + na[j++] = mapped.bv_val; + } } } - if ( j == 0 && i != 0 ) { + + if ( j == 0 && ( i > 0 || x > 0 ) ) { na[j++] = LDAP_NO_ATTRS; } na[j] = NULL; *mapped_attrs = na; + return LDAP_SUCCESS; } diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index ae1a4f64e4..2f98806d57 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -573,9 +573,8 @@ meta_back_search_start( /* * Maps required attributes */ - rc = ldap_back_map_attrs( &mt->mt_rwmap.rwm_at, - op->ors_attrs, BACKLDAP_MAP, &mapped_attrs, - op->o_tmpmemctx ); + rc = ldap_back_map_attrs( op, &mt->mt_rwmap.rwm_at, + op->ors_attrs, BACKLDAP_MAP, &mapped_attrs ); if ( rc != LDAP_SUCCESS ) { /* * this target is no longer candidate diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 6c197c0954..58ec6ffb6f 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -464,6 +464,9 @@ void backend_destroy_one( BackendDB *bd, int dynamic ) } acl_destroy( bd->be_acl ); limits_destroy( bd->be_limits ); + if ( bd->be_extra_anlist ) { + anlist_free( bd->be_extra_anlist, 1, NULL ); + } if ( !BER_BVISNULL( &bd->be_update_ndn ) ) { ch_free( bd->be_update_ndn.bv_val ); } diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index a20852e011..2987bf6d9a 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -135,6 +135,7 @@ static ConfigDriver config_referral; static ConfigDriver config_loglevel; static ConfigDriver config_updatedn; static ConfigDriver config_updateref; +static ConfigDriver config_extra_attrs; static ConfigDriver config_include; static ConfigDriver config_obsolete; #ifdef HAVE_TLS @@ -362,6 +363,10 @@ static ConfigTable config_back_cf_table[] = { "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, + { "extra_attrs", "attrlist", 2, 2, 0, ARG_DB|ARG_MAGIC, + &config_extra_attrs, "( OLcfgDbAt:0.20 NAME 'olcExtraAttrs' " + "EQUALITY caseIgnoreMatch " + "SYNTAX OMsDirectoryString )", NULL, NULL }, { "gentlehup", "on|off", 2, 2, 0, #ifdef SIGHUP ARG_ON_OFF, &global_gentlehup, @@ -822,7 +827,7 @@ static ConfigOCs cf_ocs[] = { "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ " "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncUseSubentry $ olcSyncrepl $ " "olcTimeLimit $ olcUpdateDN $ olcUpdateRef $ olcMirrorMode $ " - "olcMonitoring ) )", + "olcMonitoring $ olcExtraAttrs ) )", Cft_Database, NULL, cfAddDatabase }, { "( OLcfgGlOc:5 " "NAME 'olcOverlayConfig' " @@ -3139,6 +3144,58 @@ config_requires(ConfigArgs *c) { return(0); } +static int +config_extra_attrs(ConfigArgs *c) +{ + assert( c->be != NULL ); + + if ( c->op == SLAP_CONFIG_EMIT ) { + int i; + + if ( c->be->be_extra_anlist == NULL ) { + return 1; + } + + for ( i = 0; !BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ); i++ ) { + value_add_one( &c->rvalue_vals, &c->be->be_extra_anlist[i].an_name ); + } + + } else if ( c->op == LDAP_MOD_DELETE ) { + if ( c->be->be_extra_anlist == NULL ) { + return 1; + } + + if ( c->valx < 0 ) { + anlist_free( c->be->be_extra_anlist, 1, NULL ); + c->be->be_extra_anlist = NULL; + + } else { + int i; + + for ( i = 0; i < c->valx && !BER_BVISNULL( &c->be->be_extra_anlist[i + 1].an_name ); i++ ) + ; + + if ( BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ) ) { + return 1; + } + + ch_free( c->be->be_extra_anlist[i].an_name.bv_val ); + + for ( ; !BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ); i++ ) { + c->be->be_extra_anlist[i] = c->be->be_extra_anlist[i + 1]; + } + } + + } else { + c->be->be_extra_anlist = str2anlist( c->be->be_extra_anlist, c->argv[1], " ,\t" ); + if ( c->be->be_extra_anlist == NULL ) { + return 1; + } + } + + return 0; +} + static slap_verbmasks *loglevel_ops; static int diff --git a/servers/slapd/overlays/rwmmap.c b/servers/slapd/overlays/rwmmap.c index bd0af8c941..c92fb9c0ba 100644 --- a/servers/slapd/overlays/rwmmap.c +++ b/servers/slapd/overlays/rwmmap.c @@ -186,19 +186,30 @@ rwm_map_attrnames( AttributeName **anp, int remap ) { - int i, j; + int i, j, x; assert( anp != NULL ); *anp = NULL; - if ( an == NULL ) { + if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) { return LDAP_SUCCESS; } - for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) - /* just count */ ; - *anp = op->o_tmpalloc( ( i + 1 )* sizeof( AttributeName ), + i = 0; + if ( an != NULL ) { + for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) + /* just count */ ; + } + + x = 0; + if ( op->o_bd->be_extra_anlist ) { + for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) + /* just count */ ; + } + + assert( i > 0 || x > 0 ); + *anp = op->o_tmpalloc( ( i + x + 1 )* sizeof( AttributeName ), op->o_tmpmemctx ); if ( *anp == NULL ) { return LDAP_NO_MEMORY; @@ -321,7 +332,22 @@ rwm_map_attrnames( } } - if ( j == 0 && i != 0 ) { + if ( op->o_bd->be_extra_anlist != NULL ) { + /* we assume be_extra_anlist are already mapped */ + for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) { + BER_BVZERO( &(*anp)[j].an_name ); + if ( op->o_bd->be_extra_anlist[x].an_desc && + ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, *anp ) ) + { + continue; + } + + (*anp)[j] = op->o_bd->be_extra_anlist[x]; + j++; + } + } + + if ( j == 0 && ( i != 0 || x != 0 ) ) { memset( &(*anp)[0], 0, sizeof( AttributeName ) ); (*anp)[0].an_name = *slap_bv_no_attrs; j = 1; diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index bda67a8f09..829b6973d1 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1936,6 +1936,7 @@ struct BackendDB { struct slap_limits **be_limits; /* regex-based size and time limits */ AccessControl *be_acl; /* access control list for this backend */ slap_access_t be_dfltaccess; /* access given if no acl matches */ + AttributeName *be_extra_anlist; /* attributes that need to be added to search requests (ITS#6513) */ /* Replica Information */ struct berval be_update_ndn; /* allowed to make changes (in replicas) */