From bcf9571e76074023fc5af8360cd3359927cf5101 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati <ando@openldap.org> Date: Thu, 15 Apr 2010 05:26:21 +0000 Subject: [PATCH] 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) --- doc/man/man5/slapd-config.5 | 14 +++++++ doc/man/man5/slapd.conf.5 | 13 +++++++ servers/slapd/back-ldap/search.c | 40 +++++++++++++++---- servers/slapd/back-meta/back-meta.h | 4 +- servers/slapd/back-meta/map.c | 55 +++++++++++++++++++++------ servers/slapd/back-meta/search.c | 5 +-- servers/slapd/backend.c | 3 ++ servers/slapd/bconfig.c | 59 ++++++++++++++++++++++++++++- servers/slapd/overlays/rwmmap.c | 38 ++++++++++++++++--- servers/slapd/slap.h | 1 + 10 files changed, 201 insertions(+), 31 deletions(-) diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5 index 80e0bce7ac..43dec6df8e 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: <attr> +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 <attr> +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 b28a2ebc50..dd6899bcea 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -1278,6 +1278,19 @@ by default. See the manual page for more details on ACL requirements for Add operations. .TP +.B extra_attrs <attrlist> +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 <attrlist> +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 0120640e6d..f5c9d30e7b 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -141,7 +141,7 @@ ldap_back_search( msgid; struct berval match = BER_BVNULL, filter = BER_BVNULL; - int i; + int i, x; char **attrs = NULL; int freetext = 0, filter_undef = 0; int do_retry = 1, dont_retry = 0; @@ -169,22 +169,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 0aa7304a39..3f98381350 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -118,11 +118,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 0bdb1f765a..7bb172469b 100644 --- a/servers/slapd/back-meta/map.c +++ b/servers/slapd/back-meta/map.c @@ -171,42 +171,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 a187939159..f4135fe2ab 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -603,9 +603,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 0982a22485..006c47370e 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 42861ec187..006647bf23 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 @@ -366,6 +367,10 @@ static ConfigTable config_back_cf_table[] = { "SUBSTR caseIgnoreSubstringsMatch " "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, @@ -837,7 +842,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' " @@ -3174,6 +3179,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 d3c8c19a1d..5141e6714a 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 3ebc10a7d2..9d524c6cbc 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1939,6 +1939,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) */ -- GitLab