]> git.sur5r.net Git - openldap/commitdiff
allow to specify a per-database list of attributes that need to be always collected...
authorPierangelo Masarati <ando@openldap.org>
Thu, 15 Apr 2010 05:26:21 +0000 (05:26 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Mon, 13 Jun 2011 21:24:12 +0000 (14:24 -0700)
doc/man/man5/slapd-config.5
doc/man/man5/slapd.conf.5
servers/slapd/back-ldap/search.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/map.c
servers/slapd/back-meta/search.c
servers/slapd/backend.c
servers/slapd/bconfig.c
servers/slapd/overlays/rwmmap.c
servers/slapd/slap.h

index 80e0bce7ac025bd9de2947f2028f2dcb8f76871f..43dec6df8ec467ded3f9c0dcbe4697bf034cd188 100644 (file)
@@ -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
index b28a2ebc5020d6afd3a2f3af6b164d23f247071a..dd6899bcea0622c95c97135a7a32d34b535d9451 100644 (file)
@@ -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
index 0120640e6d537801c78a8b4087795114250999a3..f5c9d30e7b4e12aa4a138aaa6544defcf64e664b 100644 (file)
@@ -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;
index 0aa7304a3974875d5508d5de9059b4128943927b..3f98381350073738de8a142cbd83cdfa2b64b975 100644 (file)
@@ -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,
index 0bdb1f765a123c66e29122a06d5d690004b0f33e..7bb172469b7362a308d468688d1351765d9887d3 100644 (file)
@@ -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;
 }
 
index a187939159105670b1af881a381dd34701a408f8..f4135fe2aba22549a91946805f7bbeebf612c3a3 100644 (file)
@@ -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
index 0982a22485d7e2f78b5084b09c6ba51f43e54574..006c47370e97297b14fc0de87d38d3d13e155b85 100644 (file)
@@ -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 );
        }
index 42861ec1873b7190e1162b701658bccefa84de85..006647bf23f0ea76d5db4c4bc64b9098a9ee64c7 100644 (file)
@@ -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
index d3c8c19a1dd316f472f7756969e8387156886bda..5141e6714a9463de3b4bc15fc6911ad62fe9da91 100644 (file)
@@ -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;
index 3ebc10a7d20719675fe1ffad4b16cd5ed6885124..9d524c6cbc73fe9304377a7556eaf178ef111e31 100644 (file)
@@ -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) */