]> 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)
committerPierangelo Masarati <ando@openldap.org>
Thu, 15 Apr 2010 05:26:21 +0000 (05:26 +0000)
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 5048a8a9968d8530cfef1c50e8a1d3473b4a28bd..69e024d6cd45ca5e0554b16ec8e3e94c2f75710e 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 121761070620620ac00bfed41a18014137e9bc8e..4bfd01d6dda496af3941e247de47ac01cf90a58e 100644 (file)
@@ -1216,6 +1216,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 e2125e82b0ac64d6a6070bb8a8867af7cea4faf5..f168a87a5dc3ee28370a80026d2214eb72b5dc2e 100644 (file)
@@ -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;
index ee14f97dcd60b657599681bb1f6e6e37071dfb9f..52276bc722273e88c72bf85391f04d161ac7b04b 100644 (file)
@@ -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,
index 7df929eb41b30bda48d201f5e138e5163d72f9ef..9e6439c5730a403681109fbd0b5815bb99602c97 100644 (file)
@@ -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;
 }
 
index ae1a4f64e4dd1f901c692cc8e1e286b43d413bea..2f98806d5739c496aa2262d0fc4cef701fc8d042 100644 (file)
@@ -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
index 6c197c09544c2cf4685192ca71050a3fc15d4edf..58ec6ffb6f81649ee30858343a44675772da895f 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 a20852e0119ba9b40959e39861bf31fe8d8144f7..2987bf6d9ac98bd6ced629102d533c38d79be296 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
@@ -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
index bd0af8c9418670972513882f594ac64e2abd9d52..c92fb9c0baea6efc8ae2025d77d34c275ba69b20 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 bda67a8f0906ed13192c953cd3d5b309742112df..829b6973d159f3dfcece95dce48b5fb334f1f169 100644 (file)
@@ -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) */