.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.
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,
.SH Caveats
The
.B rwm overlay
-is far from complete.
+is experimental.
.LP
.SH EXAMPLES
To implement a plain virtual naming context mapping
"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
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,
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).
.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
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
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
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 );
}
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;
struct berval *bdn, int flags );
#define LDAP_BUILD_ENTRY_PRIVATE 0x01
-static struct berval dummy = BER_BVNULL;
-
int
ldap_back_search(
Operation *op,
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 ) {
* 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] );
)
{
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,
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,
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
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;
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;
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 ) {
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 );
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;
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 );
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 );
* 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 */ ;
dncookie dc;
/*
- * Rewrite the bind dn if needed
+ * Rewrite the dn if needed
*/
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
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;
}
}
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 );
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;
}
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 ) {
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];
}
}
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
(*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 ) {
}
}
+ /*
+ * Rewrite the dn, if needed
+ */
#ifdef ENABLE_REWRITE
rc = rwm_op_dn_massage( op, rs, "renameDN" );
#else
}
/*
- * Rewrite the bind dn if needed
+ * Rewrite the dn if needed
*/
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
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;
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;
}
* 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 );
}
}
} 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 ) {
*/
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;
/* 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;
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 ) {
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;
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
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++ ) {
r++;
}
}
- lutil_strcopy( ptr, p );
+ ptr = lutil_strcopy( ptr, p );
+ ptr[0] = '$';
+ ptr[1] = '\0';
return res;
}
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";
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 );
} 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;
}
#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;
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;
}
return rc;
}
- if ( dc->normalized && !BER_BVISNULL( &normal) ) {
+ if ( dc->normalized && !BER_BVISNULL( &normal ) ) {
in = &normal;
} else if ( !dc->normalized && !BER_BVISNULL( &pretty ) ) {
}
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;
}
}
{
int i, j;
+ assert( anp );
+
+ *anp = NULL;
+
if ( an == NULL ) {
return LDAP_SUCCESS;
}
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 ) {
filter_escape_value( &vtmp, mapped_value );
if ( freeval ) {
- ber_memfree( vtmp.bv_val );
+ ch_free( vtmp.bv_val );
}
return 0;
}
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:
}
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:
}
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:
}
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:
/* 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 );
/* "(attr=" */ "%s*)",
vtmp.bv_val );
- ber_memfree( vtmp.bv_val );
+ ch_free( vtmp.bv_val );
}
if ( f->f_sub_any != NULL ) {
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 );
}
}
/* "(attr=[init*][any*]" */ "%s)",
vtmp.bv_val );
- ber_memfree( vtmp.bv_val );
+ ch_free( vtmp.bv_val );
}
break;
}
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 );
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 ? '&' :
( 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,
!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 ) {
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;
* routines may be macros with args
*/
int
-rwm_dnattr_rewrite(
+rwm_referral_rewrite(
Operation *op,
SlapReply *rs,
void *cookie,
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
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) );
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:
/*
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;
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,
* 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];
}
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;
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
*/
#include "slapi/slapi.h"
#endif
+const struct berval slap_dummy_bv = BER_BVNULL;
+
int slap_null_cb( Operation *op, SlapReply *rs )
{
return 0;
/* 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 ) {
} 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;
} 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;
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;
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
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;
#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
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
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
+
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/"
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
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
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
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
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..."
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" \