]> git.sur5r.net Git - openldap/commitdiff
slightly rework user/operational attributes handling (including fixing a bug in the...
authorPierangelo Masarati <ando@openldap.org>
Sun, 25 Jul 2004 23:16:40 +0000 (23:16 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sun, 25 Jul 2004 23:16:40 +0000 (23:16 +0000)
23 files changed:
doc/man/man5/slapd-relay.5
doc/man/man5/slapo-rwm.5
servers/slapd/attr.c
servers/slapd/back-bdb/operational.c
servers/slapd/back-ldap/search.c
servers/slapd/back-ldap/unbind.c
servers/slapd/back-ldbm/operational.c
servers/slapd/back-meta/search.c
servers/slapd/back-monitor/operational.c
servers/slapd/back-sql/compare.c
servers/slapd/back-sql/operational.c
servers/slapd/backend.c
servers/slapd/overlays/rwm.c
servers/slapd/overlays/rwm.h
servers/slapd/overlays/rwmconf.c
servers/slapd/overlays/rwmdn.c
servers/slapd/overlays/rwmmap.c
servers/slapd/proto-slap.h
servers/slapd/result.c
servers/slapd/slap.h
tests/data/relay.out
tests/scripts/defines.sh
tests/scripts/test030-relay

index ad8466eae23483d190571fc14b7cfc894244ed86..5a165f3b5ba156baef4a1eb033b47cd312b38209 100644 (file)
@@ -17,34 +17,63 @@ It requires the
 .LP
 This backend and the above mentioned overlay are experimental.
 .SH CONFIGURATION
-These
+The following
 .B slapd.conf
-options apply to the relay backend database.
+directives apply to the relay backend database.
 That is, they must follow a "database relay" line and come before any
 subsequent "backend" or "database" lines.
 Other database options are described in the
 .BR slapd.conf (5)
-manual page.
+manual page; only the
+.B suffix
+directive is required by the 
+.I relay
+backend.
 .TP
 .B relay <real naming context> [massage]
 The naming context of the database that is presented 
 under a virtual naming context.
-The presence of the directive implies that one single database
+The presence of this directive implies that one specific database,
+i.e. the one serving the
+.BR "real naming context" ,
 will be presented under a virtual naming context.
 This directive automatically instantiates the 
-.B rwm
-.BR overlay .
+.IR "rwm overlay" .
 If the optional
 .B massage
 keyword is present, the suffix massaging is automatically
-configured as well.
+configured as well; otherwise, specific massaging instructions
+are required by means of the
+.I rewrite
+directives described in
+.BR slapo-rwm (5).
+
+.SH ACCESS RULES
+One important issue is that access rules are based on the identity
+that issued the operation.
+After massaging from the virtual to the real naming context, the
+frontend sees the operation as performed by the identty in the
+real naming context.
+Moreover, since
+.B back-relay
+bypasses the real database frontend operations by short-circuiting
+operations thru the internal backend API, the original database
+access rules do not apply but in selected cases, i.e. when the
+backend itself applies access control.
+As a consequence, the instances of the relay database must provide
+own access rules that are consistent with those of the original
+database, possibly adding further specific restrictions.
+So, access rules in the
+.B relay
+database must refer to identities in the real naming context.
+Examples are reported in the EXAMPLES section.
 
 .SH SCENARIOS
 .LP
 If no
 .B relay
 directive is given, the 
-.B relay
+.I relay
 database does not refer to any specific database, but the most
 appropriate one is looked-up after rewriting the request DN
 for the operation that is being handled.
@@ -52,7 +81,8 @@ for the operation that is being handled.
 This allows to write carefully crafted rewrite rules that
 cause some of the requests to be directed to one database, and
 some to another; e.g., authentication can be mapped to one 
-database, and searches to another and so.
+database, and searches to another, or different target databases
+can be selected based on the DN of the request, and so.
 .LP
 Another possibility is to map the same operation to different 
 databases based on details of the virtual naming context,
@@ -61,7 +91,7 @@ e.g. groups on one database and persons on another.
 .SH Caveats
 The
 .B rwm overlay
-is far from complete.
+is experimental.
 .LP
 .SH EXAMPLES
 To implement a plain virtual naming context mapping
@@ -84,6 +114,10 @@ that looks up the real naming context for each operation, use
           "dc=real,dc=naming,dc=context"
 .fi
 .LP
+This is useful, for instance, to relay different databases that
+share the terminal portion of the naming context (the one that
+is rewritten).
+.LP
 To implement the old-fashioned suffixalias, e.g. mapping
 the virtual to the real naming context, but not the results
 back from the real to the virtual naming context, use
@@ -95,11 +129,11 @@ back from the real to the virtual naming context, use
   rewriteEngine   on
   rewriteContext  default
   rewriteRule     "dc=virtual,dc=naming,dc=context"
-          "dc=real,dc=naming,dc=context" ":"
-  rewriteRule     searchFilter
-  rewriteRule     searchResult
-  rewriteRule     searchResultAttrDN
-  rewriteRule     matchedDN
+          "dc=real,dc=naming,dc=context" ":@"
+  rewriteContext  searchFilter
+  rewriteContext  searchEntryDN
+  rewriteContext  searchAttrDN
+  rewriteContext  matchedDN
 .fi
 .LP
 Note that the virtual database is bound to a single real database,
@@ -108,10 +142,45 @@ so the
 is automatically instantiated, but the rewrite rules 
 are written explicitly to map all the virtual to real 
 naming context data flow, but none of the real to virtual.
+.LP
+Access rules:
+.LP
+.nf
+  database        bdb
+  suffix          "dc=example,dc=com"
+  # skip...
+  access to dn.subtree="dc=example,dc=com"
+          by dn.exact="cn=Supervisor,dc=example,dc=com" write
+          by * read
+
+  database        relay
+  suffix          "o=Example,c=US"
+  relay           "dc=example,dc=com" massage
+  # skip ...
+  access to dn.subtree="o=Example,c=US"
+          by dn.exact="cn=Supervisor,dc=example,dc=com" write
+          by dn.exact="cn=Relay Supervisor,dc=example,dc=com" write
+          by * read
+.fi
+.LP
+Note that, in both databases, the identities (the 
+.B <who> 
+clause) are in the
+.BR "real naming context" ,
+i.e.
+.BR "`dc=example,dc=com'" ,
+while the targets (the 
+.B <what> 
+clause) are in the
+.B real
+and in the
+.BR "virtual naming context" ,
+respectively.
 .SH FILES
 .TP
 ETCDIR/slapd.conf
 default slapd configuration file
 .SH SEE ALSO
 .BR slapd.conf (5),
+.BR slapo-rwm (5),
 .BR slapd (8).
index 1541477ebeae4aaeddd1fa6f98597390ad853b50..658ee218daeefa1b545b421558957bae1565a815 100644 (file)
@@ -52,6 +52,15 @@ with
 .IR "distinguishedName syntax" ,
 requires the knowledge of the attributeType syntax.
 See the REWRITING section for details.
+.LP
+Note that when mapping DN-valued attributes from local to remote,
+first the DN is rewritten, and then the attributeType is mapped;
+while mapping from remote to local, first the attributeType is mapped,
+and then the DN is rewritten.
+As such, it is important that the local attributeType is appropriately
+defined as using the distinguishedName syntax.
+Also, note that there are DN-related syntaxes, like nameAndOptionalUID,
+whose values are currenlty not rewritten.
 .SH SUFFIX MASSAGING
 A basic feature of the
 .B rwm
@@ -287,13 +296,13 @@ searchFilterAttrDN   search
 compareDN            compare
 compareAttrDN        compare AVA
 addDN                add
-addAttrDN            add AVA
+addAttrDN            add AVA (including "ref")
 modifyDN             modify
-modifyAttrDN         modify AVA
+modifyAttrDN         modify AVA (including "ref")
 modrDN               modrdn
 newSuperiorDN        modrdn
 deleteDN             delete
-exopPasswdDN         passwd exop DN if proxy
+exopPasswdDN         passwd exop DN
 .fi
 .RE
 .LP
@@ -308,6 +317,8 @@ searchAttrDN         search AVA (only if defined; defaults
                      attributes of search results)
 matchedDN            all ops (only if applicable; defaults
                      to searchEntryDN)
+referralDN           all ops (only if applicable; defaults
+                     to searchEntryDN)
 .fi
 .RE
 .LP
index afee05201a424b50893c6ecc2166a42374eeae59..762c90cb6f5025d49df038935175307bebe0f94a 100644 (file)
@@ -44,8 +44,9 @@
 void
 attr_free( Attribute *a )
 {
+       if ( a->a_nvals && a->a_nvals != a->a_vals )
+               ber_bvarray_free( a->a_nvals );
        ber_bvarray_free( a->a_vals );
-       if (a->a_nvals != a->a_vals) ber_bvarray_free( a->a_nvals );
        free( a );
 }
 
index 5b72c32f038efedcf6bd80813c98ea75f27d9711..3ff7aa2bc97bfb2cee412057afb6ab0c9f1ca2fe 100644 (file)
@@ -100,7 +100,7 @@ bdb_operational(
        for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
                /* just count */ ;
 
-       if ( rs->sr_opattrs == SLAP_OPATTRS ||
+       if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
                        ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
        {
                int     hasSubordinates;
index 5d83ca441e29f61346913ba682954aa8b4763eaf..753d7fa6ab95ba3e84a5a84fc33c97f80e48fc3f 100644 (file)
@@ -41,8 +41,6 @@ ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent,
         struct berval *bdn, int flags );
 #define LDAP_BUILD_ENTRY_PRIVATE       0x01
 
-static struct berval dummy = BER_BVNULL;
-
 int
 ldap_back_search(
     Operation  *op,
@@ -200,7 +198,7 @@ fail:;
                                        ent.e_attrs = a->a_next;
 
                                        v = a->a_vals;
-                                       if ( a->a_vals != &dummy ) {
+                                       if ( a->a_vals != &slap_dummy_bv ) {
                                                ber_bvarray_free(a->a_vals);
                                        }
                                        if ( a->a_nvals != v ) {
@@ -453,7 +451,7 @@ ldap_build_entry(
                         * values result filter
                         */
                        if ( private ) {
-                               attr->a_vals = &dummy;
+                               attr->a_vals = &slap_dummy_bv;
                        } else {
                                attr->a_vals = ch_malloc( sizeof( struct berval ) );
                                BER_BVZERO( &attr->a_vals[0] );
index d2d416a5691eacb5871f6f57ebd20f6cd87d0b7e..66e713940999cd82919b6549bc713294c1e2ca89 100644 (file)
@@ -38,7 +38,7 @@ ldap_back_conn_destroy(
 )
 {
        struct ldapinfo *li = (struct ldapinfo *) be->be_private;
-       struct ldapconn *lc, lc_curr;
+       struct ldapconn *lc = NULL, lc_curr;
 
 #ifdef NEW_LOGGING
        LDAP_LOG( BACK_LDAP, INFO,
@@ -56,6 +56,13 @@ ldap_back_conn_destroy(
        lc = avl_delete( &li->conntree, (caddr_t)&lc_curr, ldap_back_conn_cmp );
        ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
 
+#ifdef ENABLE_REWRITE
+       /*
+        * Cleanup rewrite session
+        */
+       rewrite_session_delete( li->rwmap.rwm_rw, conn );
+#endif /* ENABLE_REWRITE */
+
        if (lc) {
 #ifdef NEW_LOGGING
                LDAP_LOG( BACK_LDAP, DETAIL1, 
@@ -67,13 +74,6 @@ ldap_back_conn_destroy(
                        lc->conn->c_connid, 0, 0 );
 #endif
 
-#ifdef ENABLE_REWRITE
-               /*
-                * Cleanup rewrite session
-                */
-               rewrite_session_delete( li->rwmap.rwm_rw, conn );
-#endif /* ENABLE_REWRITE */
-
                /*
                 * Needs a test because the handler may be corrupted,
                 * and calling ldap_unbind on a corrupted header results
index e3070e5e19611a41f0b4ae34ab35b529a96ea952..de927c72bd50462a57fc0be1647a3c14431dc8e2 100644 (file)
@@ -60,7 +60,7 @@ ldbm_back_operational(
        for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
                /* just count */ ;
 
-       if ( rs->sr_opattrs == SLAP_OPATTRS ||
+       if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
                        ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
        {
                int     hs;
index 1a2bf3d85d4e36ffd40ad9ec57778f8499cd4f57..91311fbe5152dbd07c7cb39ae2cd4b6b7c9f233a 100644 (file)
@@ -556,7 +556,6 @@ meta_send_entry(
        Entry                   ent = {0};
        BerElement              ber = *e->lm_ber;
        Attribute               *attr, **attrp;
-       struct berval           dummy = BER_BVNULL;
        struct berval           *bv, bdn;
        const char              *text;
        dncookie                dc;
@@ -652,7 +651,7 @@ meta_send_entry(
 
                if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR 
                                || attr->a_vals == NULL ) {
-                       attr->a_vals = &dummy;
+                       attr->a_vals = &slap_dummy_bv;
 
                } else if ( attr->a_desc == slap_schema.si_ad_objectClass
                                || attr->a_desc == slap_schema.si_ad_structuralObjectClass ) {
@@ -724,7 +723,7 @@ meta_send_entry(
        while ( ent.e_attrs ) {
                attr = ent.e_attrs;
                ent.e_attrs = attr->a_next;
-               if ( attr->a_vals != &dummy ) {
+               if ( attr->a_vals != &slap_dummy_bv ) {
                        ber_bvarray_free( attr->a_vals );
                }
                free( attr );
index 3fc3d9689c4d34bc97ec22a2357008585e4eff21..6c78297a85e0a864d01408de4d9e7b7835fe3ddb 100644 (file)
@@ -46,7 +46,7 @@ monitor_back_operational(
        for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
                /* just count */ ;
 
-       if ( rs->sr_opattrs == SLAP_OPATTRS ||
+       if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
                        ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
        {
                int                     hs;
index 4a32a0e2798a79dca374fcc54f9c843aba47d87d..b5a4582a814d4e95ab2b02a0b895f726febc9c19 100644 (file)
@@ -95,7 +95,7 @@ backsql_compare( Operation *op, SlapReply *rs )
 
                nrs.sr_attrs = anlist;
                nrs.sr_entry = &user_entry;
-               nrs.sr_opattrs = SLAP_OPATTRS_NO;
+               nrs.sr_attr_flags = SLAP_OPATTRS_NO;
                nrs.sr_operational_attrs = NULL;
 
                rs->sr_err = backsql_operational( op, &nrs );
index 0f66e1495c959353a1a251f1df2cff9a3330d54d..7f701857347dba94358876acfdcfdd9925c3bce3 100644 (file)
@@ -49,7 +49,7 @@ backsql_operational(
        for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
                /* just count */ ;
 
-       if ( ( rs->sr_opattrs == SLAP_OPATTRS || ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) 
+       if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) 
                        && attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL ) {
                
                rc = backsql_get_db_conn( op, &dbh );
index 59a1267f678a9cc6a39da705766b3448f5d008ca..3524370b4e473b993a6d71685b433654a2b7e712 100644 (file)
@@ -1502,19 +1502,25 @@ int backend_operational(
         * and the backend supports specific operational attributes, 
         * add them to the attribute list
         */
-       if ( rs->sr_opattrs == SLAP_OPATTRS || ( op->ors_attrs &&
+       if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( op->ors_attrs &&
                ad_inlist( slap_schema.si_ad_subschemaSubentry, op->ors_attrs )) ) {
                *ap = slap_operational_subschemaSubentry( op->o_bd );
 
                ap = &(*ap)->a_next;
        }
 
-       if ( ( rs->sr_opattrs == SLAP_OPATTRS || op->ors_attrs ) && op->o_bd &&
+       if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || op->ors_attrs ) && op->o_bd &&
                op->o_bd->be_operational != NULL )
        {
+               Attribute       *a;
+               
+               a = rs->sr_operational_attrs;
                rs->sr_operational_attrs = NULL;
                rc = op->o_bd->be_operational( op, rs );
                *ap = rs->sr_operational_attrs;
+               if ( a != NULL ) {
+                       rs->sr_operational_attrs = a;
+               }
 
                for ( ; *ap; ap = &(*ap)->a_next )
                        /* just count them */ ;
index f5c05dcd277d32f32ad5facebff83ada86df43f6..f1bf2fdce764db02c08b5373a0e45b968e3a538e 100644 (file)
@@ -40,7 +40,7 @@ rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
        dncookie                dc;
 
        /*
-        * Rewrite the bind dn if needed
+        * Rewrite the dn if needed
         */
        dc.rwmap = rwmap;
 #ifdef ENABLE_REWRITE
@@ -73,14 +73,11 @@ rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
        op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
        if ( dnp ) {
                op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
-       }
-
-       op->o_req_ndn = ndn;
-       if ( dnp ) {
                op->o_req_dn = dn;
        } else {
                op->o_req_dn = ndn;
        }
+       op->o_req_ndn = ndn;
 
        return LDAP_SUCCESS;
 }
@@ -110,8 +107,8 @@ rwm_add( Operation *op, SlapReply *rs )
        }
 
        if ( olddn != op->o_req_dn.bv_val ) {
-               ber_memfree( op->ora_e->e_name.bv_val );
-               ber_memfree( op->ora_e->e_nname.bv_val );
+               ch_free( op->ora_e->e_name.bv_val );
+               ch_free( op->ora_e->e_nname.bv_val );
 
                ber_dupbv( &op->ora_e->e_name, &op->o_req_dn );
                ber_dupbv( &op->ora_e->e_nname, &op->o_req_ndn );
@@ -151,8 +148,23 @@ rwm_add( Operation *op, SlapReply *rs )
                        if ( rc ) {
                                goto cleanup_attr;
                        }
+
+               } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
+#ifdef ENABLE_REWRITE
+                       rc = rwm_referral_rewrite( op, rs, "addAttrDN",
+                                       (*ap)->a_vals,
+                                       (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
+#else
+                       rc = 1;
+                       rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals,
+                                       (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
+#endif
+                       if ( rc != LDAP_SUCCESS ) {
+                               goto cleanup_attr;
+                       }
                }
 
+
 next_attr:;
                ap = &(*ap)->a_next;
                continue;
@@ -261,13 +273,18 @@ rwm_compare( Operation *op, SlapReply *rs )
                }
                if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
                {
+                       struct berval   *mapped_valsp[2];
+                       
+                       mapped_valsp[0] = &mapped_vals[0];
+                       mapped_valsp[1] = &mapped_vals[1];
+
                        mapped_vals[0] = op->orc_ava->aa_value;
 
 #ifdef ENABLE_REWRITE
-                       rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", mapped_vals, NULL );
+                       rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
 #else
                        rc = 1;
-                       rc = rwm_dnattr_rewrite( op, rs, &rc, mapped_vals, NULL );
+                       rc = rwm_dnattr_rewrite( op, rs, &rc, NULL, mapped_valsp );
 #endif
 
                        if ( rc != LDAP_SUCCESS ) {
@@ -276,10 +293,7 @@ rwm_compare( Operation *op, SlapReply *rs )
                                return -1;
                        }
 
-                       if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
-                               free( op->orc_ava->aa_value.bv_val );
-                               op->orc_ava->aa_value = mapped_vals[0];
-                       }
+                       op->orc_ava->aa_value = mapped_vals[0];
                }
        }
 
@@ -397,7 +411,7 @@ rwm_modify( Operation *op, SlapReply *rs )
                                                slap_schema.si_syn_distinguishedName )
                                {
 #ifdef ENABLE_REWRITE
-                                       rc = rwm_dnattr_rewrite( op, rs, "modifyDN",
+                                       rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
                                                        (*mlp)->sml_values,
                                                        (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
 #else
@@ -406,6 +420,20 @@ rwm_modify( Operation *op, SlapReply *rs )
                                                        (*mlp)->sml_values,
                                                        (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
 #endif
+                               } else if ( (*mlp)->sml_desc == slap_schema.si_ad_ref ) {
+#ifdef ENABLE_REWRITE
+                                       rc = rwm_referral_rewrite( op, rs, "modifyAttrDN",
+                                                       (*mlp)->sml_values,
+                                                       (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
+#else
+                                       rc = 1;
+                                       rc = rwm_referral_rewrite( op, rs, &rc,
+                                                       (*mlp)->sml_values,
+                                                       (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
+#endif
+                                       if ( rc != LDAP_SUCCESS ) {
+                                               goto cleanup_mod;
+                                       }
                                }
 
                                if ( rc != LDAP_SUCCESS ) {
@@ -470,6 +498,9 @@ rwm_modrdn( Operation *op, SlapReply *rs )
                }
        }
 
+       /*
+        * Rewrite the dn, if needed
+        */
 #ifdef ENABLE_REWRITE
        rc = rwm_op_dn_massage( op, rs, "renameDN" );
 #else
@@ -539,7 +570,7 @@ rwm_search( Operation *op, SlapReply *rs )
        }
 
        /*
-        * Rewrite the bind dn if needed
+        * Rewrite the dn if needed
         */
        dc.rwmap = rwmap;
 #ifdef ENABLE_REWRITE
@@ -698,13 +729,12 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
        Attribute               **ap;
 
        /*
-        * Rewrite the dn of the result, if needed
+        * Rewrite the dn attrs, if needed
         */
        dc.rwmap = rwmap;
 #ifdef ENABLE_REWRITE
        dc.conn = op->o_conn;
        dc.rs = NULL; 
-       dc.ctx = "searchAttrDN";
 #else
        dc.tofrom = 0;
        dc.normalized = 0;
@@ -728,11 +758,13 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
                int                     last;
                Attribute               *a;
 
-               if ( rs->sr_opattrs == SLAP_OPATTRS && is_at_operational( (*ap)->a_desc->ad_type ) )
+               if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
                {
                        /* go on */ ;
                        
-               } else if ( op->ors_attrs != NULL && !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
+               } else if ( op->ors_attrs != NULL && 
+                               !SLAP_USERATTRS( rs->sr_attr_flags ) && 
+                               !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
                {
                        goto cleanup_attr;
                }
@@ -781,7 +813,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
                                         * the value is replaced by
                                         * ch_alloc'ed memory
                                         */
-                                       free( bv[0].bv_val );
+                                       ch_free( bv[0].bv_val );
                                        ber_dupbv( &bv[0], &mapped );
                                }
                        }
@@ -801,10 +833,22 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
                } else if ( (*ap)->a_desc->ad_type->sat_syntax ==
                                slap_schema.si_syn_distinguishedName )
                {
+#ifdef ENABLE_REWRITE
+                       dc.ctx = "searchAttrDN";
+#endif
                        rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals );
                        if ( rc != LDAP_SUCCESS ) {
                                goto cleanup_attr;
                        }
+
+               } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
+#ifdef ENABLE_REWRITE
+                       dc.ctx = "searchAttrDN";
+#endif
+                       rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
+                       if ( rc != LDAP_SUCCESS ) {
+                               goto cleanup_attr;
+                       }
                }
 
                if ( m != NULL ) {
@@ -882,12 +926,13 @@ rwm_send_entry( Operation *op, SlapReply *rs )
         */
        rc = rwm_dn_massage( &dc, &e->e_name, &dn, &ndn );
        if ( rc != LDAP_SUCCESS ) {
+               rc = 1;
                goto fail;
        }
 
        if ( e->e_name.bv_val != dn.bv_val ) {
-               free( e->e_name.bv_val );
-               free( e->e_nname.bv_val );
+               ch_free( e->e_name.bv_val );
+               ch_free( e->e_nname.bv_val );
 
                e->e_name = dn;
                e->e_nname = ndn;
@@ -899,7 +944,7 @@ rwm_send_entry( Operation *op, SlapReply *rs )
        /* FIXME: the entries are in the remote mapping form;
         * so we need to select those attributes we are willing
         * to return, and remap them accordingly */
-       rwm_attrs( op, rs, &e->e_attrs );
+       (void)rwm_attrs( op, rs, &e->e_attrs );
 
        rs->sr_entry = e;
        rs->sr_flags = flags;
@@ -1060,6 +1105,10 @@ rwm_m_config(
 static int
 rwm_response( Operation *op, SlapReply *rs )
 {
+       slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
+       struct ldaprwmap        *rwmap = 
+                       (struct ldaprwmap *)on->on_bi.bi_private;
+
        int             rc;
 
        if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
@@ -1083,6 +1132,27 @@ rwm_response( Operation *op, SlapReply *rs )
        case LDAP_REQ_MODIFY:
        case LDAP_REQ_COMPARE:
        case LDAP_REQ_EXTENDED:
+               if ( rs->sr_ref ) {
+                       dncookie                dc;
+
+                       /*
+                        * Rewrite the dn of the referrals, if needed
+                        */
+                       dc.rwmap = rwmap;
+#ifdef ENABLE_REWRITE
+                       dc.conn = op->o_conn;
+                       dc.rs = NULL; 
+                       dc.ctx = "referralDN";
+#else
+                       dc.tofrom = 0;
+                       dc.normalized = 0;
+#endif
+                       rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
+                       if ( rc != LDAP_SUCCESS ) {
+                               rc = 1;
+                               break;
+                       }
+               }
                rc = rwm_matched( op, rs );
                break;
 
index 9d3cf31f418a59cdca7f441580bdd1497c5b6701..3bdee4f6564d354f132a7243e0d78af4e9c98b4a 100644 (file)
@@ -156,7 +156,14 @@ extern int rwm_dnattr_rewrite(
        void                    *cookie,
        BerVarray               a_vals,
        BerVarray               *pa_nvals );
+extern int rwm_referral_rewrite(
+       Operation               *op,
+       SlapReply               *rs,
+       void                    *cookie,
+       BerVarray               a_vals,
+       BerVarray               *pa_nvals );
 extern int rwm_dnattr_result_rewrite( dncookie *dc, BerVarray a_vals );
+extern int rwm_referral_result_rewrite( dncookie *dc, BerVarray a_vals );
 
 LDAP_END_DECL
 
index be1e7f870ed77d521aa2faec0995fd1b2b7dab2e..f25229882607a949fcb2e252c89f267ffd8c04a6 100644 (file)
@@ -244,9 +244,12 @@ rwm_suffix_massage_regexize( const char *s )
                        p = r + 1, i++ )
                ;
 
-       res = ch_calloc( sizeof( char ), strlen( s ) + 4 + 4*i + 1 );
+       res = ch_calloc( sizeof( char ), strlen( s )
+                       + STRLENOF( "((.+),)?" )
+                       + STRLENOF( "[ ]?" ) * i
+                       + STRLENOF( "$" ) + 1 );
 
-       ptr = lutil_strcopy( res, "(.*)" );
+       ptr = lutil_strcopy( res, "((.+),)?" );
        for ( i = 0, p = s;
                        ( r = strchr( p, ',' ) ) != NULL;
                        p = r + 1 , i++ ) {
@@ -257,7 +260,9 @@ rwm_suffix_massage_regexize( const char *s )
                        r++;
                }
        }
-       lutil_strcopy( ptr, p );
+       ptr = lutil_strcopy( ptr, p );
+       ptr[0] = '$';
+       ptr[1] = '\0';
 
        return res;
 }
@@ -333,6 +338,13 @@ rwm_suffix_massage_config(
        rargv[ 4 ] = NULL;
        rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
 
+       rargv[ 0 ] = "rewriteContext";
+       rargv[ 1 ] = "referralDN";
+       rargv[ 2 ] = "alias";
+       rargv[ 3 ] = "searchEntryDN";
+       rargv[ 4 ] = NULL;
+       rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
+
        rargv[ 0 ] = "rewriteContext";
        rargv[ 1 ] = "searchAttrDN";
        rargv[ 2 ] = "alias";
index 85c929b2c31ba9a8953aebf2cd77b33848001d1e..4892e4365e1d4ea3230faed3b5590c90ae7edb71 100644 (file)
@@ -48,6 +48,12 @@ rwm_dn_massage(
        int             rc = 0;
        struct berval   mdn;
 
+       assert( in );
+
+       if ( dn == NULL && ndn == NULL ) {
+               return LDAP_OTHER;
+       }
+
        rc = rewrite_session( dc->rwmap->rwm_rw, dc->ctx,
                        ( in->bv_len ? in->bv_val : "" ), 
                        dc->conn, &mdn.bv_val );
@@ -74,9 +80,13 @@ rwm_dn_massage(
                } else {
                        /* we assume the input string is already in pretty form,
                         * and that the normalized version is already available */
-                       *dn = *in;
-                       if ( ndn != NULL ) {
-                               BER_BVZERO( ndn );
+                       if ( dn ) {
+                               *dn = *in;
+                               if ( ndn ) {
+                                       BER_BVZERO( ndn );
+                               }
+                       } else {
+                               *ndn = *in;
                        }
                        rc = LDAP_SUCCESS;
                }
@@ -84,11 +94,11 @@ rwm_dn_massage(
 #ifdef NEW_LOGGING
                LDAP_LOG( BACK_LDAP, DETAIL1, 
                        "[rw] %s: \"%s\" -> \"%s\"\n",
-                       dc->ctx, in->bv_val, dn->bv_val );
+                       dc->ctx, in->bv_val, dn ? dn->bv_val : ndn->bv_val );
 #else /* !NEW_LOGGING */
                Debug( LDAP_DEBUG_ARGS,
                        "[rw] %s: \"%s\" -> \"%s\"\n",
-                       dc->ctx, in->bv_val, dn->bv_val );              
+                       dc->ctx, in->bv_val, dn ? dn->bv_val : ndn->bv_val );
 #endif /* !NEW_LOGGING */
                break;
                
@@ -131,15 +141,29 @@ rwm_dn_massage(
                        normal = BER_BVNULL,
                        *in = tmpin;
 
-       assert( dn );
+       if ( dn == NULL && ndn == NULL ) {
+               return LDAP_OTHER;
+       }
 
        if ( in == NULL || BER_BVISNULL( in ) ) {
-               dn->bv_val = NULL;
-               dn->bv_len = 0;
+               if ( dn ) {
+                       BER_BVZERO( dn );
+               }
+               if ( ndn ) {
+                       BER_BVZERO( ndn );
+               }
                return LDAP_SUCCESS;
        }
+
        if ( dc->rwmap == NULL || dc->rwmap->rwm_suffix_massage == NULL ) {
-               *dn = *in;
+               if ( dn ) {
+                       *dn = *in;
+                       if ( ndn ) {
+                               BER_BVZERO( ndn );
+                       }
+               } else {
+                       *ndn = *in;
+               }
                return LDAP_SUCCESS;
        }
 
@@ -170,7 +194,7 @@ rwm_dn_massage(
                        return rc;
                }
 
-               if ( dc->normalized && !BER_BVISNULL( &normal) ) {
+               if ( dc->normalized && !BER_BVISNULL( &normal ) ) {
                        in = &normal;
 
                } else if ( !dc->normalized && !BER_BVISNULL( &pretty ) ) {
@@ -197,20 +221,31 @@ rwm_dn_massage(
                }
 
                if ( !strcmp( dc->rwmap->rwm_suffix_massage[i+src].bv_val, &in->bv_val[diff] ) ) {
-                       dn->bv_len = diff + dc->rwmap->rwm_suffix_massage[i+dst].bv_len;
-                       dn->bv_val = ch_malloc( dn->bv_len + 1 );
-                       strncpy( dn->bv_val, in->bv_val, diff );
-                       strcpy( &dn->bv_val[diff], dc->rwmap->rwm_suffix_massage[i+dst].bv_val );
+                       struct berval   *out;
+
+                       if ( dn ) {
+                               out = dn;
+                       } else {
+                               out = ndn;
+                       }
+                       out->bv_len = diff + dc->rwmap->rwm_suffix_massage[i+dst].bv_len;
+                       out->bv_val = ch_malloc( out->bv_len + 1 );
+                       strncpy( out->bv_val, in->bv_val, diff );
+                       strcpy( &out->bv_val[diff], dc->rwmap->rwm_suffix_massage[i+dst].bv_val );
 #ifdef NEW_LOGGING
                        LDAP_LOG ( BACK_LDAP, ARGS, 
                                "rwm_dn_massage: converted \"%s\" to \"%s\"\n",
-                               in->bv_val, dn->bv_val, 0 );
+                               in->bv_val, out->bv_val, 0 );
 #else
                        Debug( LDAP_DEBUG_ARGS,
                                "rwm_dn_massage:"
                                " converted \"%s\" to \"%s\"\n",
-                               in->bv_val, dn->bv_val, 0 );
+                               in->bv_val, out->bv_val, 0 );
 #endif
+                       if ( dn && ndn ) {
+                               rc = dnNormalize( 0, NULL, NULL, dn, ndn, NULL );
+                       }
+
                        break;
                }
        }
index 526d399128ee9e6afd3848ed03b83148522493e8..89543c445396c79153fd6fd6e4ebaf2be071256d 100644 (file)
@@ -163,6 +163,10 @@ rwm_map_attrnames(
 {
        int             i, j;
 
+       assert( anp );
+
+       *anp = NULL;
+
        if ( an == NULL ) {
                return LDAP_SUCCESS;
        }
@@ -384,7 +388,7 @@ map_attr_value(
                fdc.ctx = "searchFilterAttrDN";
 #endif
 
-               rc = rwm_dn_massage( &fdc, value, &vtmp, NULL );
+               rc = rwm_dn_massage( &fdc, value, NULL, &vtmp );
                switch ( rc ) {
                case LDAP_SUCCESS:
                        if ( vtmp.bv_val != value->bv_val ) {
@@ -413,7 +417,7 @@ map_attr_value(
        filter_escape_value( &vtmp, mapped_value );
 
        if ( freeval ) {
-               ber_memfree( vtmp.bv_val );
+               ch_free( vtmp.bv_val );
        }
        
        return 0;
@@ -453,12 +457,12 @@ rwm_int_filter_map_rewrite(
                }
 
                fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
-               fstr->bv_val = malloc( fstr->bv_len + 1 );
+               fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
                        atmp.bv_val, vtmp.bv_val );
 
-               ber_memfree( vtmp.bv_val );
+               ch_free( vtmp.bv_val );
                break;
 
        case LDAP_FILTER_GE:
@@ -469,12 +473,12 @@ rwm_int_filter_map_rewrite(
                }
 
                fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
-               fstr->bv_val = malloc( fstr->bv_len + 1 );
+               fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
                        atmp.bv_val, vtmp.bv_val );
 
-               ber_memfree( vtmp.bv_val );
+               ch_free( vtmp.bv_val );
                break;
 
        case LDAP_FILTER_LE:
@@ -485,12 +489,12 @@ rwm_int_filter_map_rewrite(
                }
 
                fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
-               fstr->bv_val = malloc( fstr->bv_len + 1 );
+               fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
                        atmp.bv_val, vtmp.bv_val );
 
-               ber_memfree( vtmp.bv_val );
+               ch_free( vtmp.bv_val );
                break;
 
        case LDAP_FILTER_APPROX:
@@ -501,12 +505,12 @@ rwm_int_filter_map_rewrite(
                }
 
                fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
-               fstr->bv_val = malloc( fstr->bv_len + 1 );
+               fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
                        atmp.bv_val, vtmp.bv_val );
 
-               ber_memfree( vtmp.bv_val );
+               ch_free( vtmp.bv_val );
                break;
 
        case LDAP_FILTER_SUBSTRINGS:
@@ -519,7 +523,7 @@ rwm_int_filter_map_rewrite(
                /* cannot be a DN ... */
 
                fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
-               fstr->bv_val = malloc( fstr->bv_len + 128 );
+               fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
                        atmp.bv_val );
@@ -536,7 +540,7 @@ rwm_int_filter_map_rewrite(
                                /* "(attr=" */ "%s*)",
                                vtmp.bv_val );
 
-                       ber_memfree( vtmp.bv_val );
+                       ch_free( vtmp.bv_val );
                }
 
                if ( f->f_sub_any != NULL ) {
@@ -550,7 +554,7 @@ rwm_int_filter_map_rewrite(
                                snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
                                        /* "(attr=[init]*[any*]" */ "%s*)",
                                        vtmp.bv_val );
-                               ber_memfree( vtmp.bv_val );
+                               ch_free( vtmp.bv_val );
                        }
                }
 
@@ -566,7 +570,7 @@ rwm_int_filter_map_rewrite(
                                /* "(attr=[init*][any*]" */ "%s)",
                                vtmp.bv_val );
 
-                       ber_memfree( vtmp.bv_val );
+                       ch_free( vtmp.bv_val );
                }
 
                break;
@@ -579,7 +583,7 @@ rwm_int_filter_map_rewrite(
                }
 
                fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" );
-               fstr->bv_val = malloc( fstr->bv_len + 1 );
+               fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
                        atmp.bv_val );
@@ -589,7 +593,7 @@ rwm_int_filter_map_rewrite(
        case LDAP_FILTER_OR:
        case LDAP_FILTER_NOT:
                fstr->bv_len = STRLENOF( "(%)" );
-               fstr->bv_val = malloc( fstr->bv_len + 128 );
+               fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
                        f->f_choice == LDAP_FILTER_AND ? '&' :
@@ -632,7 +636,7 @@ rwm_int_filter_map_rewrite(
                        ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
                        ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
                        vtmp.bv_len + STRLENOF( "(:=)" );
-               fstr->bv_val = malloc( fstr->bv_len + 1 );
+               fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
 
                snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
                        atmp.bv_val,
@@ -640,8 +644,9 @@ rwm_int_filter_map_rewrite(
                        !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
                        !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
                        vtmp.bv_val );
-               ber_memfree( vtmp.bv_val );
-               } break;
+               ch_free( vtmp.bv_val );
+               break;
+       }
 
        case SLAPD_FILTER_COMPUTED:
                switch ( f->f_result ) {
@@ -701,7 +706,7 @@ rwm_filter_map_rewrite(
        case REWRITE_REGEXEC_OK:
                if ( !BER_BVISNULL( fstr ) ) {
                        fstr->bv_len = strlen( fstr->bv_val );
-                       free( ftmp.bv_val );
+                       ch_free( ftmp.bv_val );
 
                } else {
                        *fstr = ftmp;
@@ -748,7 +753,7 @@ rwm_filter_map_rewrite(
  * routines may be macros with args
  */
 int
-rwm_dnattr_rewrite(
+rwm_referral_rewrite(
        Operation               *op,
        SlapReply               *rs,
        void                    *cookie,
@@ -762,12 +767,12 @@ rwm_dnattr_rewrite(
        int                     i, last;
 
        dncookie                dc;
-       struct berval           dn, ndn, *pndn = NULL;
+       struct berval           dn, ndn, *ndnp = NULL;
 
        assert( a_vals );
 
        /*
-        * Rewrite the bind dn if needed
+        * Rewrite the dn if needed
         */
        dc.rwmap = rwmap;
 #ifdef ENABLE_REWRITE
@@ -781,7 +786,7 @@ rwm_dnattr_rewrite(
 
        for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
        if ( pa_nvals != NULL ) {
-               pndn = &ndn;
+               ndnp = &ndn;
 
                if ( *pa_nvals == NULL ) {
                        *pa_nvals = ch_malloc( last * sizeof(struct berval) );
@@ -791,9 +796,22 @@ rwm_dnattr_rewrite(
        last--;
 
        for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
+               struct berval   olddn, oldval;
                int             rc;
+               LDAPURLDesc     *ludp;
+
+               oldval = a_vals[i];
+               rc = ldap_url_parse( oldval.bv_val, &ludp );
+               if ( rc != LDAP_URL_SUCCESS ) {
+                       /* leave attr untouched if massage failed */
+                       if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
+                               ber_dupbv( &(*pa_nvals)[i], &oldval );
+                       }
+                       continue;
+               }
+               ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
 
-               rc = rwm_dn_massage( &dc, &a_vals[i], &dn, pndn );
+               rc = rwm_dn_massage( &dc, &olddn, &dn, ndnp );
                switch ( rc ) {
                case LDAP_UNWILLING_TO_PERFORM:
                        /*
@@ -816,21 +834,168 @@ rwm_dnattr_rewrite(
                        break;
                
                case LDAP_SUCCESS:
-                       if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) {
-                               ch_free( a_vals[i].bv_val );
-                               a_vals[i] = dn;
+                       if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) {
+                               char    *newurl;
+
+                               ludp->lud_dn = dn.bv_val;
+                               newurl = ldap_url_desc2str( ludp );
+                               if ( newurl == NULL ) {
+                                       /* FIXME: leave attr untouched
+                                        * even if ldap_url_desc2str failed... */
+                                       break;
+                               }
+
+                               ber_str2bv( newurl, 0, 1, &a_vals[i] );
+                               LDAP_FREE( newurl );
+
                                if ( pa_nvals ) {
+                                       ludp->lud_dn = ndn.bv_val;
+                                       newurl = ldap_url_desc2str( ludp );
+                                       if ( newurl == NULL ) {
+                                               /* FIXME: leave attr untouched
+                                                * even if ldap_url_desc2str failed... */
+                                               ch_free( a_vals[i].bv_val );
+                                               a_vals[i] = oldval;
+                                               break;
+                                       }
+
                                        if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
                                                ch_free( (*pa_nvals)[i].bv_val );
                                        }
-                                       (*pa_nvals)[i] = *pndn;
+                                       ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] );
+                                       LDAP_FREE( newurl );
                                }
+
+                               ch_free( oldval.bv_val );
+                               ludp->lud_dn = olddn.bv_val;
                        }
                        break;
 
                default:
                        /* leave attr untouched if massage failed */
                        if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
+                               ber_dupbv( &(*pa_nvals)[i], &a_vals[i] );
+                       }
+                       break;
+               }
+               ldap_free_urldesc( ludp );
+       }
+       
+       return 0;
+}
+
+/*
+ * I don't like this much, but we need two different
+ * functions because different heap managers may be
+ * in use in back-ldap/meta to reduce the amount of
+ * calls to malloc routines, and some of the free()
+ * routines may be macros with args
+ */
+int
+rwm_dnattr_rewrite(
+       Operation               *op,
+       SlapReply               *rs,
+       void                    *cookie,
+       BerVarray               a_vals,
+       BerVarray               *pa_nvals )
+{
+       slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
+       struct ldaprwmap        *rwmap = 
+                       (struct ldaprwmap *)on->on_bi.bi_private;
+
+       int                     i, last;
+
+       dncookie                dc;
+       struct berval           dn, *dnp = NULL, ndn, *ndnp = NULL;
+       BerVarray               in;
+
+       if ( a_vals ) {
+               in = a_vals;
+               dnp = &dn;
+
+       } else {
+               if ( pa_nvals == NULL || *pa_nvals == NULL ) {
+                       return LDAP_OTHER;
+               }
+               in = *pa_nvals;
+       }
+
+       /*
+        * Rewrite the dn if needed
+        */
+       dc.rwmap = rwmap;
+#ifdef ENABLE_REWRITE
+       dc.conn = op->o_conn;
+       dc.rs = rs;
+       dc.ctx = (char *)cookie;
+#else
+       dc.tofrom = ((int *)cookie)[0];
+       dc.normalized = 0;
+#endif
+
+       for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
+       if ( pa_nvals != NULL ) {
+               ndnp = &ndn;
+
+               if ( *pa_nvals == NULL ) {
+                       *pa_nvals = ch_malloc( last * sizeof(struct berval) );
+                       memset( *pa_nvals, 0, last * sizeof(struct berval) );
+               }
+       }
+       last--;
+
+       for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
+               int             rc;
+
+               rc = rwm_dn_massage( &dc, &in[i], dnp, ndnp );
+               switch ( rc ) {
+               case LDAP_UNWILLING_TO_PERFORM:
+                       /*
+                        * FIXME: need to check if it may be considered 
+                        * legal to trim values when adding/modifying;
+                        * it should be when searching (e.g. ACLs).
+                        */
+                       ch_free( in[i].bv_val );
+                       if (last > i ) {
+                               in[i] = in[last];
+                               if ( a_vals && pa_nvals ) {
+                                       (*pa_nvals)[i] = (*pa_nvals)[last];
+                               }
+                       }
+                       BER_BVZERO( &in[last] );
+                       if ( a_vals && pa_nvals ) {
+                               BER_BVZERO( &(*pa_nvals)[last] );
+                       }
+                       last--;
+                       break;
+               
+               case LDAP_SUCCESS:
+                       if ( a_vals ) {
+                               if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) {
+                                       ch_free( a_vals[i].bv_val );
+                                       a_vals[i] = dn;
+
+                                       if ( pa_nvals ) {
+                                               if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
+                                                       ch_free( (*pa_nvals)[i].bv_val );
+                                               }
+                                               (*pa_nvals)[i] = ndn;
+                                       }
+                               }
+                               
+                       } else {
+                               assert( ndnp != NULL );
+
+                               if ( !BER_BVISNULL( &ndn ) && ndn.bv_val != (*pa_nvals)[i].bv_val ) {
+                                       ch_free( (*pa_nvals)[i].bv_val );
+                                       (*pa_nvals)[i] = ndn;
+                               }
+                       }
+                       break;
+
+               default:
+                       /* leave attr untouched if massage failed */
+                       if ( a_vals && pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
                                dnNormalize( 0, NULL, NULL, &a_vals[i], &(*pa_nvals)[i], NULL );
                        }
                        break;
@@ -840,6 +1005,73 @@ rwm_dnattr_rewrite(
        return 0;
 }
 
+int
+rwm_referral_result_rewrite(
+       dncookie                *dc,
+       BerVarray               a_vals
+)
+{
+       int             i, last;
+
+       for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
+       last--;
+
+       for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
+               struct berval   dn, olddn;
+               int             rc;
+               LDAPURLDesc     *ludp;
+
+               rc = ldap_url_parse( a_vals[i].bv_val, &ludp );
+               if ( rc != LDAP_URL_SUCCESS ) {
+                       /* leave attr untouched if massage failed */
+                       continue;
+               }
+
+               ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
+               
+               rc = rwm_dn_massage( dc, &olddn, &dn, NULL );
+               switch ( rc ) {
+               case LDAP_UNWILLING_TO_PERFORM:
+                       /*
+                        * FIXME: need to check if it may be considered 
+                        * legal to trim values when adding/modifying;
+                        * it should be when searching (e.g. ACLs).
+                        */
+                       ch_free( &a_vals[i].bv_val );
+                       if ( last > i ) {
+                               a_vals[i] = a_vals[last];
+                       }
+                       BER_BVZERO( &a_vals[last] );
+                       last--;
+                       break;
+
+               default:
+                       /* leave attr untouched if massage failed */
+                       if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) {
+                               char    *newurl;
+
+                               ludp->lud_dn = dn.bv_val;
+                               newurl = ldap_url_desc2str( ludp );
+                               if ( newurl == NULL ) {
+                                       /* FIXME: leave attr untouched
+                                        * even if ldap_url_desc2str failed... */
+                                       break;
+                               }
+
+                               ch_free( a_vals[i].bv_val );
+                               ber_str2bv( newurl, 0, 1, &a_vals[i] );
+                               LDAP_FREE( newurl );
+                               ludp->lud_dn = olddn.bv_val;
+                       }
+                       break;
+               }
+
+               ldap_free_urldesc( ludp );
+       }
+
+       return 0;
+}
+
 int
 rwm_dnattr_result_rewrite(
        dncookie                *dc,
@@ -863,7 +1095,7 @@ rwm_dnattr_result_rewrite(
                         * legal to trim values when adding/modifying;
                         * it should be when searching (e.g. ACLs).
                         */
-                       LBER_FREE( &a_vals[i].bv_val );
+                       ch_free( &a_vals[i].bv_val );
                        if ( last > i ) {
                                a_vals[i] = a_vals[last];
                        }
@@ -874,7 +1106,7 @@ rwm_dnattr_result_rewrite(
                default:
                        /* leave attr untouched if massage failed */
                        if ( !BER_BVISNULL( &dn ) && a_vals[i].bv_val != dn.bv_val ) {
-                               LBER_FREE( a_vals[i].bv_val );
+                               ch_free( a_vals[i].bv_val );
                                a_vals[i] = dn;
                        }
                        break;
index ca6b1ce69e534e3fa3cc51e263a2f433a8bea272..eee6982e237043b9d3f5ce965980a0b165efa944 100644 (file)
@@ -975,6 +975,8 @@ LDAP_SLAPD_F (int) str2result LDAP_P(( char *s,
        int *code, char **matched, char **info ));
 LDAP_SLAPD_F (int) slap_map_api2result LDAP_P(( SlapReply *rs ));
 
+LDAP_SLAPD_V( const struct berval ) slap_dummy_bv;
+
 /*
  * root_dse.c
  */
index 446497206c2cca0fbc04a87e6a29a6a5cb2480dd..579526c1f274bcda204a05f5c6046d689b1c98c6 100644 (file)
@@ -41,6 +41,8 @@
 #include "slapi/slapi.h"
 #endif
 
+const struct berval slap_dummy_bv = BER_BVNULL;
+
 int slap_null_cb( Operation *op, SlapReply *rs )
 {
        return 0;
@@ -784,8 +786,15 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
        /* FIXME: maybe we could se this flag at the operation level;
         * however, in principle the caller of send_search_entry() may
         * change the attribute list at each call */
-       rs->sr_opattrs = ( rs->sr_attrs == NULL ) ? SLAP_OPATTRS_NO
-               : ( an_find( rs->sr_attrs, &AllOper ) ? SLAP_OPATTRS : SLAP_OPATTRS_NO );
+       if ( rs->sr_attrs == NULL ) {
+               rs->sr_attr_flags = ( SLAP_OPATTRS_NO | SLAP_USERATTRS_YES );
+
+       } else {
+               rs->sr_attr_flags |= an_find( rs->sr_attrs, &AllOper ) ?
+                       SLAP_OPATTRS_YES : SLAP_OPATTRS_NO;
+               rs->sr_attr_flags |= an_find( rs->sr_attrs, &AllUser ) ?
+                       SLAP_USERATTRS_YES : SLAP_USERATTRS_NO;
+       }
 
        rc = backend_operational( op, rs );
        if ( rc ) {
@@ -967,7 +976,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                } else {
                        /* specific attrs requested */
                        if ( is_at_operational( desc->ad_type ) ) {
-                               if ( rs->sr_opattrs != SLAP_OPATTRS &&
+                               if ( !SLAP_OPATTRS( rs->sr_attr_flags ) &&
                                                !ad_inlist( desc, rs->sr_attrs ) )
                                {
                                        continue;
@@ -1177,7 +1186,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                } else {
                        /* specific attrs requested */
                        if( is_at_operational( desc->ad_type ) ) {
-                               if ( rs->sr_opattrs != SLAP_OPATTRS && 
+                               if ( !SLAP_OPATTRS( rs->sr_attr_flags ) && 
                                                !ad_inlist( desc, rs->sr_attrs ) )
                                {
                                        continue;
@@ -1295,7 +1304,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                ctx.cac_attrs = rs->sr_attrs;
                ctx.cac_attrsonly = op->ors_attrsonly;
                ctx.cac_userattrs = userattrs;
-               ctx.cac_opattrs = rs->sr_opattrs;
+               ctx.cac_opattrs = rs->sr_attr_flags;
                ctx.cac_acl_state = acl_state;
                ctx.cac_private = (void *)ber;
 
@@ -1433,7 +1442,7 @@ error_return:;
                attrs_free( rs->sr_operational_attrs );
                rs->sr_operational_attrs = NULL;
        }
-       rs->sr_opattrs = SLAP_OPATTRS_UNDEFINED;
+       rs->sr_attr_flags = SLAP_ATTRS_UNDEFINED;
 
        /* FIXME: I think rs->sr_type should be explicitly set to
         * REP_SEARCH here. That's what it was when we entered this
index c42930f02231715102cd37e70d8358394813ac7a..d78df940a00e83339bcbba7846cbbd5c266fefd9 100644 (file)
@@ -1687,10 +1687,16 @@ typedef struct rep_extended_s {
 
 typedef struct rep_search_s {
        Entry *r_entry;
-       int r_opattrs;
-#define SLAP_OPATTRS_UNDEFINED (0)
-#define SLAP_OPATTRS_NO                (-1)
-#define SLAP_OPATTRS           (1)
+       int r_attr_flags;
+#define SLAP_ATTRS_UNDEFINED   (0)
+#define SLAP_OPATTRS_NO                (0x01)
+#define SLAP_OPATTRS_YES       (0x02)
+#define SLAP_USERATTRS_NO      (0x10)
+#define SLAP_USERATTRS_YES     (0x20)
+#define SLAP_OPATTRS_MASK(f)   ( (f) & (SLAP_OPATTRS_NO|SLAP_OPATTRS_YES) )
+#define SLAP_OPATTRS(f)                ( (f) & SLAP_OPATTRS_YES )
+#define SLAP_USERATTRS_MASK(f) ( (f) & (SLAP_USERATTRS_NO|SLAP_USERATTRS_YES) )
+#define SLAP_USERATTRS(f)      ( (f) & SLAP_USERATTRS_YES )
        Attribute *r_operational_attrs;
        AttributeName *r_attrs;
        int r_nentries;
@@ -1722,7 +1728,7 @@ typedef struct slap_rep {
 #define        sr_attrs sr_un.sru_search.r_attrs
 #define        sr_entry sr_un.sru_search.r_entry
 #define        sr_operational_attrs sr_un.sru_search.r_operational_attrs
-#define sr_opattrs sr_un.sru_search.r_opattrs
+#define sr_attr_flags sr_un.sru_search.r_attr_flags
 #define        sr_v2ref sr_un.sru_search.r_v2ref
 #define        sr_nentries sr_un.sru_search.r_nentries
 #define        sr_rspoid sr_un.sru_extended.r_rspoid
index 3f93a013e33cf3e7c8c69621c9a2216c95ddfb3e..3d545eaa32af85ba016c3711776f2f1ecd6f9706 100644 (file)
@@ -2031,7 +2031,8 @@ homePhone: +1 313 555 8421
 pager: +1 313 555 2844
 facsimileTelephoneNumber: +1 313 555 9700
 telephoneNumber: +1 313 555 5331
-description: Just added self in o=Beispiel,c=DE virtual naming context
+description: Just added self to seeAlso in o=Beispiel,c=DE virtual naming cont
+ ext
 
 dn: cn=Added User,ou=Alumni Association,ou=People,o=Esempio,c=IT
 objectClass: OpenLDAPperson
@@ -2042,5 +2043,69 @@ seeAlso: cn=All Staff,ou=Groups,o=Esempio,c=IT
 homePhone: +49 1234567890
 drink: Beer
 mail: auser@mail.alumni.example.com
-telephoneNumber: +1 313 555 4178
+telephoneNumber: +49 1234-567-890
+description: Just added in o=Beispiel,c=DE naming context
+
+
+dn: ou=Referrals,dc=example,dc=com
+objectClass: referral
+objectClass: extensibleObject
+ou: Referrals
+description: Just added as ldap://localhost:9011/ou=Referrals,o=Beispiel,c=DE
+description: ...and modified as ldap://localhost:9012/ou=Referrals,o=Beispiel,
+ c=DE
+ref: ldap://localhost:9012/ou=Referrals,dc=example,dc=com??base
+
+dn: ou=Referrals,o=Example,c=US
+objectClass: referral
+objectClass: extensibleObject
+ou: Referrals
+description: Just added as ldap://localhost:9011/ou=Referrals,o=Beispiel,c=DE
+description: ...and modified as ldap://localhost:9012/ou=Referrals,o=Beispiel,
+ c=DE
+ref: ldap://localhost:9012/ou=Referrals,o=Example,c=US??base
+
+dn: ou=Referrals,o=Esempio,c=IT
+objectClass: referral
+objectClass: extensibleObject
+ou: Referrals
+description: Just added as ldap://localhost:9011/ou=Referrals,o=Beispiel,c=DE
+description: ...and modified as ldap://localhost:9012/ou=Referrals,o=Beispiel,
+ c=DE
+ref: ldap://localhost:9012/ou=Referrals,o=Esempio,c=IT??base
+
+dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Example,c
+ =US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
+dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Example,c=U
+ S
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
+dn: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=Example,c=US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
+dn: cn=James A Jones 1,ou=Alumni Association,ou=People,o=Example,c=US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
+dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Example,
+ c=US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
+dn: cn=Jane Q. Doe,ou=Information Technology Division,ou=People,o=Example,c=US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
+dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=Example,c=US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
+dn: cn=John P. Doe,ou=Information Technology Division,ou=People,o=Example,c=US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
+dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Example,c=US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+seeAlso: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Example,c=US
+
+dn: cn=Added User,ou=Alumni Association,ou=People,o=Example,c=US
+seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
+
 
index f38b5343751612d8a7c2705d327004843c16b0ae..ec50ee8dddab71aa6bd0882f861765110e66d740 100755 (executable)
@@ -120,7 +120,7 @@ PORT4=9014
 PORT5=9015
 PORT6=9016
 URI1="ldap://${LOCALHOST}:$PORT1/"
-URI2="ldap://${LOCALHOST}:$PORT2"
+URI2="ldap://${LOCALHOST}:$PORT2/"
 URI3="ldap://${LOCALHOST}:$PORT3/"
 URI4="ldap://${LOCALHOST}:$PORT4/"
 URI5="ldap://${LOCALHOST}:$PORT5/"
index 807ca64956377f6de80f8fd1711cd1b46831047d..4aef13abfa9b0510081fd63929250b0ae270510a 100755 (executable)
@@ -114,7 +114,7 @@ fi
 BASEDN="o=Beispiel,c=DE"
 echo "modifying database \"$BASEDN\"..."
 $LDAPMODIFY -v -D "cn=Manager,$BASEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
-       >> $TESTOUT 2>&1 << EOMODS
+       -e manageDSAit >> $TESTOUT 2>&1 << EOMODS
 dn: cn=Added User,ou=Alumni Association,ou=People,$BASEDN
 changetype: add
 objectClass: OpenLDAPperson
@@ -125,7 +125,8 @@ seealso: cn=All Staff,ou=Groups,$BASEDN
 homephone: +49 1234567890
 drink: Beer
 mail: auser@mail.alumni.example.com
-telephonenumber: +1 313 555 4178
+telephonenumber: +49 1234-567-890
+description: Just added in o=Beispiel,c=DE naming context
 
 dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,$BASEDN
 changetype: modify
@@ -133,7 +134,7 @@ add: seeAlso
 seeAlso: cn=Ursula Hampster,ou=Alumni Association,ou=People,$BASEDN
 -
 add: description
-description: Just added self in $BASEDN virtual naming context
+description: Just added self to seeAlso in $BASEDN virtual naming context
 -
 
 dn: cn=Mark Elliot,ou=Alumni Association,ou=People,$BASEDN
@@ -150,6 +151,22 @@ newrdn: cn=Jane Q. Doe
 deleteoldrdn: 1
 newsuperior: ou=Information Technology Division,ou=People,$BASEDN
 
+dn: ou=Referrals,$BASEDN
+changetype: add
+objectclass: referral
+objectclass: extensibleObject
+ou: Referrals
+ref: ${URI1}ou=Referrals,$BASEDN
+description: Just added as ${URI1}ou=Referrals,$BASEDN
+
+dn: ou=Referrals,$BASEDN
+changetype: modify
+replace: ref
+ref: ${URI2}ou=Referrals,$BASEDN
+-
+add: description
+description: ...and modified as ${URI2}ou=Referrals,$BASEDN
+-
 EOMODS
 
 if test $RC != 0 ; then
@@ -168,6 +185,57 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
+FILTER="(objectClass=referral)"
+echo "searching filter=\"$FILTER\""
+echo " attrs=\"'*' ref\"..."
+
+BASEDN="dc=example,dc=com"
+echo " base=\"$BASEDN\"..."
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" "$FILTER" "*" ref \
+       -e manageDSAit >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "Search failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+BASEDN="o=Example,c=US"
+echo " base=\"$BASEDN\"..."
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" "$FILTER" "*" ref \
+       -e manageDSAit >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "Search failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+BASEDN="o=Esempio,c=IT"
+echo " base=\"$BASEDN\"..."
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" "$FILTER" "*" ref \
+       -e manageDSAit >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "Search failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+BASEDN="o=Example,c=US"
+FILTER="(seeAlso=cn=all staff,ou=Groups,$BASEDN)"
+echo "searching filter=\"$FILTER\""
+echo " attrs=\"seeAlso\"..."
+echo " base=\"$BASEDN\""
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" "$FILTER" seeAlso \
+       >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "Search failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
 echo "Filtering ldapsearch results..."
 . $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
 echo "Filtering original ldif used to create database..."
@@ -193,6 +261,7 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
+BASEDN="o=Beispiel,c=DE"
 echo "binding with newly changed password to database \"$BASEDN\"..."
 $LDAPWHOAMI -h $LOCALHOST -p $PORT1 \
        -D "cn=Added User,ou=Alumni Association,ou=People,$BASEDN" \