First stable an implementing latest namedref specification.

Includes rewriting of URLs where the DN of the referral object
and the DN of the ref attribute attribute are not the same.
Also, always returns explicit DN and scope.
Currently, back-ldbm only.  Needs to be ported to back-bdb.
This commit is contained in:
Kurt Zeilenga 2001-10-26 02:05:14 +00:00
parent f3f72c5d2a
commit 82fad7d0c8
25 changed files with 678 additions and 301 deletions

View file

@ -17,7 +17,7 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \
repl.c lock.c controls.c extended.c kerberos.c passwd.c \
schema.c schema_check.c schema_init.c schema_prep.c \
schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \
configinfo.c starttls.c index.c sets.c \
configinfo.c starttls.c index.c sets.c referral.c \
root_dse.c sasl.c module.c suffixalias.c mra.c mods.c \
limits.c \
$(@PLAT@_SRCS)
@ -30,7 +30,7 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \
repl.o lock.o controls.o extended.o kerberos.o passwd.o \
schema.o schema_check.o schema_init.o schema_prep.o \
schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \
configinfo.o starttls.o index.o sets.o \
configinfo.o starttls.o index.o sets.o referral.o \
root_dse.o sasl.o module.o suffixalias.o mra.o mods.o \
limits.o \
$(@PLAT@_OBJS)

View file

@ -209,8 +209,13 @@ do_add( Connection *conn, Operation *op )
*/
be = select_backend( e->e_ndn, manageDSAit );
if ( be == NULL ) {
struct berval **ref = referral_rewrite( default_referral,
NULL, e->e_dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, default_referral, NULL );
NULL, NULL, ref ? ref : default_referral, NULL );
ber_bvecfree( ref );
goto done;
}
@ -294,8 +299,15 @@ do_add( Connection *conn, Operation *op )
#ifndef SLAPD_MULTIMASTER
} else {
struct berval **defref = be->be_update_refs
? be->be_update_refs : default_referral;
struct berval **ref = referral_rewrite( defref,
NULL, e->e_dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
be->be_update_refs ? be->be_update_refs : default_referral, NULL );
ref ? ref : defref, NULL );
ber_bvecfree( ref );
#endif
}
} else {
@ -387,4 +399,3 @@ static int slap_mods2entry(
return LDAP_SUCCESS;
}

View file

@ -42,7 +42,6 @@ ldbm_back_add(
Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
#endif
/* nobody else can add until we lock our parent */
ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
@ -90,7 +89,7 @@ ldbm_back_add(
/* get parent with writer lock */
if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
char *matched_dn;
char *matched_dn = NULL;
struct berval **refs;
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
@ -98,13 +97,14 @@ ldbm_back_add(
if ( matched != NULL ) {
matched_dn = ch_strdup( matched->e_dn );
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
? get_entry_referrals( be, conn, op, matched,
e->e_dn, LDAP_SCOPE_DEFAULT )
: NULL;
cache_return_entry_r( &li->li_cache, matched );
} else {
matched_dn = NULL;
refs = default_referral;
refs = referral_rewrite( default_referral,
NULL, e->e_dn, LDAP_SCOPE_DEFAULT );
}
#ifdef NEW_LOGGING
@ -116,15 +116,12 @@ ldbm_back_add(
0, 0, 0 );
#endif
send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn,
refs == NULL ? "parent does not exist" : "parent is referral",
refs, NULL );
if( matched != NULL ) {
ber_bvecfree( refs );
free( matched_dn );
}
free( pdn );
return -1;
@ -182,7 +179,8 @@ ldbm_back_add(
/* parent is a referral, don't allow add */
char *matched_dn = ch_strdup( p->e_dn );
struct berval **refs = is_entry_referral( p )
? get_entry_referrals( be, conn, op, p )
? get_entry_referrals( be, conn, op, p,
e->e_dn, LDAP_SCOPE_DEFAULT )
: NULL;
/* free parent and writer lock */
@ -290,7 +288,6 @@ ldbm_back_add(
0 );
#endif
send_ldap_result( conn, op,
rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OTHER,
NULL, rc > 0 ? NULL : "cache add failed", NULL, NULL );

View file

@ -63,12 +63,15 @@ ldbm_back_bind(
matched_dn = ch_strdup( matched->e_dn );
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
? get_entry_referrals( be, conn, op, matched,
dn, LDAP_SCOPE_DEFAULT )
: NULL;
cache_return_entry_r( &li->li_cache, matched );
} else {
refs = default_referral;
refs = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
}
/* allow noauth binds */
@ -96,10 +99,8 @@ ldbm_back_bind(
NULL, NULL, NULL, NULL );
}
if ( matched != NULL ) {
ber_bvecfree( refs );
free( matched_dn );
}
return( rc );
}
@ -128,7 +129,7 @@ ldbm_back_bind(
if ( is_entry_referral( e ) ) {
/* entry is a referral, don't allow bind */
struct berval **refs = get_entry_referrals( be,
conn, op, e );
conn, op, e, dn, LDAP_SCOPE_DEFAULT );
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,

View file

@ -41,20 +41,20 @@ ldbm_back_compare(
if ( matched != NULL ) {
matched_dn = ch_strdup( matched->e_dn );
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
? get_entry_referrals( be, conn, op, matched,
dn, LDAP_SCOPE_DEFAULT )
: NULL;
cache_return_entry_r( &li->li_cache, matched );
} else {
refs = default_referral;
refs = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
}
send_ldap_result( conn, op, LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
if( matched != NULL ) {
ber_bvecfree( refs );
free( matched_dn );
}
return( 1 );
}
@ -62,7 +62,7 @@ ldbm_back_compare(
if (!manageDSAit && is_entry_referral( e ) ) {
/* entry is a referral, don't allow add */
struct berval **refs = get_entry_referrals( be,
conn, op, e );
conn, op, e, dn, LDAP_SCOPE_DEFAULT );
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,

View file

@ -41,11 +41,10 @@ ldbm_back_delete(
Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn, 0, 0);
#endif
/* get entry with writer lock */
if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) {
char *matched_dn = NULL;
struct berval **refs = NULL;
struct berval **refs;
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
@ -55,24 +54,24 @@ ldbm_back_delete(
dn, 0, 0);
#endif
if ( matched != NULL ) {
matched_dn = ch_strdup( matched->e_dn );
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
? get_entry_referrals( be, conn, op, matched,
dn, LDAP_SCOPE_DEFAULT )
: NULL;
cache_return_entry_r( &li->li_cache, matched );
} else {
refs = default_referral;
refs = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
}
send_ldap_result( conn, op, LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
if ( matched != NULL ) {
ber_bvecfree( refs );
free( matched_dn );
}
return( -1 );
}
@ -81,7 +80,7 @@ ldbm_back_delete(
/* parent is a referral, don't allow add */
/* parent is an alias, don't allow add */
struct berval **refs = get_entry_referrals( be,
conn, op, e );
conn, op, e, dn, LDAP_SCOPE_DEFAULT );
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,

View file

@ -270,25 +270,25 @@ ldbm_back_modify(
/* acquire and lock entry */
if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) {
char* matched_dn = NULL;
struct berval **refs = NULL;
struct berval **refs;
if ( matched != NULL ) {
matched_dn = ch_strdup( matched->e_dn );
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
? get_entry_referrals( be, conn, op, matched,
dn, LDAP_SCOPE_DEFAULT )
: NULL;
cache_return_entry_r( &li->li_cache, matched );
} else {
refs = default_referral;
refs = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
}
send_ldap_result( conn, op, LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
if ( matched != NULL ) {
ber_bvecfree( refs );
free( matched_dn );
}
return( -1 );
}
@ -297,7 +297,7 @@ ldbm_back_modify(
/* parent is a referral, don't allow add */
/* parent is an alias, don't allow add */
struct berval **refs = get_entry_referrals( be,
conn, op, e );
conn, op, e, dn, LDAP_SCOPE_DEFAULT );
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,

View file

@ -88,25 +88,25 @@ ldbm_back_modrdn(
/* get entry with writer lock */
if ( (e = dn2entry_w( be, ndn, &matched )) == NULL ) {
char* matched_dn = NULL;
struct berval** refs = NULL;
struct berval** refs;
if( matched != NULL ) {
matched_dn = strdup( matched->e_dn );
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
? get_entry_referrals( be, conn, op, matched,
dn, LDAP_SCOPE_DEFAULT )
: NULL;
cache_return_entry_r( &li->li_cache, matched );
} else {
refs = default_referral;
refs = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
}
send_ldap_result( conn, op, LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
if ( matched != NULL ) {
ber_bvecfree( refs );
free( matched_dn );
}
return( -1 );
}
@ -115,13 +115,13 @@ ldbm_back_modrdn(
/* parent is a referral, don't allow add */
/* parent is an alias, don't allow add */
struct berval **refs = get_entry_referrals( be,
conn, op, e );
conn, op, e, dn, LDAP_SCOPE_DEFAULT );
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
"ldbm_back_modrdn: entry %s is a referral\n", e->e_dn ));
#else
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
Debug( LDAP_DEBUG_TRACE, "entry %s is referral\n", e->e_dn,
0, 0 );
#endif
@ -137,7 +137,7 @@ ldbm_back_modrdn(
LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
"ldbm_back_modrdn: entry %s has children\n", e->e_dn ));
#else
Debug( LDAP_DEBUG_TRACE, "entry %s referral\n", e->e_dn,
Debug( LDAP_DEBUG_TRACE, "entry %s has children\n", e->e_dn,
0, 0 );
#endif
@ -337,8 +337,8 @@ ldbm_back_modrdn(
"ldbm_back_modrdn: entry (%s) is a referral\n",
np->e_dn ));
#else
Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
0, 0 );
Debug( LDAP_DEBUG_TRACE, "entry (%s) is referral\n",
np->e_dn, 0, 0 );
#endif
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,

View file

@ -42,7 +42,7 @@ ldbm_back_referrals(
e = dn2entry_r( be, ndn, &matched );
if ( e == NULL ) {
char *matched_dn = NULL;
struct berval **refs = default_referral;
struct berval **refs = NULL;
if ( matched != NULL ) {
matched_dn = ch_strdup( matched->e_dn );
@ -57,32 +57,42 @@ ldbm_back_referrals(
op->o_tag, dn, matched_dn );
#endif
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
: NULL;
if( is_entry_referral( matched ) ) {
rc = LDAP_OTHER;
refs = get_entry_referrals( be, conn, op, matched,
dn, LDAP_SCOPE_DEFAULT );
}
cache_return_entry_r( &li->li_cache, matched );
} else if ( default_referral != NULL ) {
rc = LDAP_OTHER;
refs = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
}
if( refs != NULL ) {
/* send referrals */
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
}
if( matched != NULL ) {
ber_bvecfree( refs );
free( matched_dn );
} else if ( rc != LDAP_SUCCESS ) {
send_ldap_result( conn, op, rc, matched_dn,
matched_dn ? "bad referral object" : "bad default referral",
NULL, NULL );
}
free( matched_dn );
return rc;
}
if ( is_entry_referral( e ) ) {
/* entry is a referral */
struct berval **refs = get_entry_referrals( be,
conn, op, e );
conn, op, e, dn, LDAP_SCOPE_DEFAULT );
struct berval **rrefs = referral_rewrite(
refs, e->e_dn, dn, LDAP_SCOPE_DEFAULT );
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
@ -94,13 +104,18 @@ ldbm_back_referrals(
op->o_tag, dn, e->e_dn );
#endif
if( refs != NULL ) {
if( rrefs != NULL ) {
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
e->e_dn, NULL, refs, NULL );
e->e_dn, NULL, rrefs, NULL );
ber_bvecfree( rrefs );
} else {
send_ldap_result( conn, op, rc = LDAP_OTHER, e->e_dn,
"bad referral object", NULL, NULL );
}
ber_bvecfree( refs );
if( refs != NULL ) ber_bvecfree( refs );
}
cache_return_entry_r( &li->li_cache, e );

View file

@ -52,6 +52,7 @@ ldbm_back_search(
char *realbase = NULL;
int nentries = 0;
int manageDSAit = get_manageDSAit( op );
int cscope = LDAP_SCOPE_DEFAULT;
struct slap_limits_set *limit = NULL;
int isroot = 0;
@ -95,34 +96,42 @@ ldbm_back_search(
struct berval **refs = NULL;
if ( matched != NULL ) {
struct berval **erefs;
matched_dn = ch_strdup( matched->e_dn );
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
erefs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched,
base, scope )
: NULL;
cache_return_entry_r( &li->li_cache, matched );
if( erefs ) {
refs = referral_rewrite( erefs, matched_dn,
base, scope );
ber_bvecfree( erefs );
}
} else {
refs = default_referral;
refs = referral_rewrite( default_referral,
NULL, base, scope );
}
send_ldap_result( conn, op, err,
matched_dn, text, refs, NULL );
if( matched != NULL ) {
ber_bvecfree( refs );
free( matched_dn );
}
return 1;
}
if (!manageDSAit && is_entry_referral( e ) ) {
/* entry is a referral, don't allow add */
char *matched_dn = ch_strdup( e->e_dn );
struct berval **refs = get_entry_referrals( be,
conn, op, e );
struct berval **erefs = get_entry_referrals( be,
conn, op, e, base, scope );
struct berval **refs = NULL;
cache_return_entry_r( &li->li_cache, e );
@ -136,13 +145,24 @@ ldbm_back_search(
0, 0, 0 );
#endif
if( erefs ) {
refs = referral_rewrite( erefs, matched_dn,
base, scope );
ber_bvecfree( erefs );
}
if( refs ) {
send_ldap_result( conn, op, LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
ber_bvecfree( refs );
free( matched_dn );
} else {
send_ldap_result( conn, op, LDAP_OTHER, matched_dn,
"bad referral object", NULL, NULL );
}
free( matched_dn );
return 1;
}
@ -152,9 +172,12 @@ ldbm_back_search(
}
if ( scope == LDAP_SCOPE_BASE ) {
cscope = LDAP_SCOPE_BASE;
candidates = base_candidate( be, e );
} else {
cscope = ( scope != LDAP_SCOPE_SUBTREE )
? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE;
candidates = search_candidates( be, e, filter,
scope, deref, manageDSAit );
}
@ -175,7 +198,6 @@ searchit:
0, 0, 0 );
#endif
send_search_result( conn, op,
LDAP_SUCCESS,
NULL, NULL, NULL, NULL, 0 );
@ -291,7 +313,6 @@ searchit:
id, 0, 0 );
#endif
goto loop_continue;
}
@ -327,10 +348,10 @@ searchit:
/* alias is within scope */
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
"ldbm_search: \"%s\" in subtree\n", e->e_dn ));
"ldbm_search: alias \"%s\" in subtree\n", e->e_dn ));
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: \"%s\" in subtree\n",
"ldbm_search: alias \"%s\" in subtree\n",
e->e_dn, 0, 0 );
#endif
@ -373,11 +394,13 @@ searchit:
}
if( scopeok ) {
struct berval **refs = get_entry_referrals(
be, conn, op, e );
struct berval **erefs = get_entry_referrals(
be, conn, op, e, NULL, cscope );
struct berval **refs = referral_rewrite( erefs, e->e_dn,
NULL, scope );
send_search_reference( be, conn, op,
e, refs, scope, NULL, &v2refs );
e, refs, NULL, &v2refs );
ber_bvecfree( refs );
@ -452,24 +475,23 @@ searchit:
} else {
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL2,
"ldbm_search: candidate %ld scope not okay\n", id ));
"ldbm_search: candidate entry %ld scope not okay\n", id ));
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: candidate %ld scope not okay\n",
"ldbm_search: candidate entry %ld scope not okay\n",
id, 0, 0 );
#endif
}
} else {
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL2,
"ldbm_search: candidate %ld does not match filter\n", id ));
"ldbm_search: candidate entry %ld does not match filter\n", id ));
#else
Debug( LDAP_DEBUG_TRACE,
"ldbm_search: candidate %ld does not match filter\n",
"ldbm_search: candidate entry %ld does not match filter\n",
id, 0, 0 );
#endif
}
loop_continue:
@ -480,6 +502,7 @@ loop_continue:
ldap_pvt_thread_yield();
}
send_search_result( conn, op,
v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
NULL, NULL, v2refs, NULL, nentries );

View file

@ -430,8 +430,13 @@ do_bind(
if ( (be = select_backend( ndn, 0 )) == NULL ) {
if ( default_referral ) {
struct berval **ref = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, default_referral, NULL );
NULL, NULL, ref ? ref : default_referral, NULL );
ber_bvecfree( ref );
} else {
/* noSuchObject is not allowed to be returned by bind */

View file

@ -224,8 +224,13 @@ do_compare(
* if we don't hold it.
*/
if ( (be = select_backend( ndn, manageDSAit )) == NULL ) {
struct berval **ref = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, default_referral, NULL );
NULL, NULL, ref ? ref : default_referral, NULL );
ber_bvecfree( ref );
rc = 0;
goto cleanup;
}

View file

@ -1487,6 +1487,19 @@ read_config( const char *fname )
return( 1 );
}
if( validate_global_referral( cargv[1] ) ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
"invalid URL (%s) in \"referral\" line.\n",
fname, lineno, cargv[1] ));
#else
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"invalid URL (%s) in \"referral\" line.\n",
fname, lineno, cargv[1] );
#endif
return 1;
}
vals[0]->bv_val = cargv[1];
vals[0]->bv_len = strlen( vals[0]->bv_val );
value_add( &default_referral, vals );
@ -1772,12 +1785,12 @@ read_config( const char *fname )
} else if ( strcasecmp( cargv[0], "updateref" ) == 0 ) {
if ( cargc < 2 ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
"%s: line %d: missing url in \"updateref <ldapurl>\" "
"line.\n", fname, lineno ));
LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
"missing url in \"updateref <ldapurl>\" line.\n",
fname, lineno ));
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing url in \"updateref <ldapurl>\" line\n",
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"missing url in \"updateref <ldapurl>\" line\n",
fname, lineno, 0 );
#endif
@ -1785,31 +1798,45 @@ read_config( const char *fname )
}
if ( be == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_INFO,
"%s: line %d: updateref line must appear inside "
"a database definition (ignored)\n", fname, lineno ));
LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
"updateref line must appear inside a database definition "
"(ignored)\n", fname, lineno ));
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: updateref line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"updateref line must appear inside a database definition "
"(ignored)\n", fname, lineno, 0 );
#endif
return 1;
} else if ( be->be_update_ndn == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_INFO,
"%s: line %d: updateref line must come after updatedn "
"(ignored).\n", fname, lineno ));
LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
"updateref line must come after updatedn (ignored).\n",
fname, lineno ));
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: updateref line must after updatedn (ignored)\n",
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"updateref line must after updatedn (ignored)\n",
fname, lineno, 0 );
#endif
return 1;
}
if( validate_global_referral( cargv[1] ) ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
"invalid URL (%s) in \"updateref\" line.\n",
fname, lineno, cargv[1] ));
#else
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"invalid URL (%s) in \"updateref\" line.\n",
fname, lineno, cargv[1] );
#endif
return 1;
}
} else {
vals[0]->bv_val = cargv[1];
vals[0]->bv_len = strlen( vals[0]->bv_val );
value_add( &be->be_update_refs, vals );
}
/* replication log file to which changes are appended */
} else if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {

View file

@ -125,8 +125,13 @@ do_delete(
* if we don't hold it.
*/
if ( (be = select_backend( ndn, manageDSAit )) == NULL ) {
struct berval **ref = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, default_referral, NULL );
NULL, NULL, ref ? ref : default_referral, NULL );
ber_bvecfree( ref );
goto cleanup;
}
@ -171,8 +176,15 @@ do_delete(
}
#ifndef SLAPD_MULTIMASTER
} else {
struct berval **defref = be->be_update_refs
? be->be_update_refs : default_referral;
struct berval **ref = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
be->be_update_refs ? be->be_update_refs : default_referral, NULL );
ref ? ref : defref, NULL );
ber_bvecfree( ref );
#endif
}

View file

@ -187,12 +187,15 @@ do_extended(
&rspoid, &rspdata, &rspctrls, &text, &refs );
if( rc != SLAPD_ABANDON ) {
if (rc == LDAP_REFERRAL) {
refs = default_referral;
if ( rc == LDAP_REFERRAL && refs == NULL ) {
refs = referral_rewrite( default_referral,
NULL, NULL, LDAP_SCOPE_DEFAULT );
}
send_ldap_extended( conn, op, rc, NULL, text, refs,
rspoid, rspdata, rspctrls );
ber_bvecfree( refs );
}
if ( rspoid != NULL ) {

View file

@ -252,8 +252,13 @@ do_modify(
* if we don't hold it.
*/
if ( (be = select_backend( ndn, manageDSAit )) == NULL ) {
struct berval **ref = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, default_referral, NULL );
NULL, NULL, ref ? ref : default_referral, NULL );
ber_bvecfree( ref );
goto cleanup;
}
@ -337,9 +342,15 @@ do_modify(
#ifndef SLAPD_MULTIMASTER
/* send a referral */
} else {
struct berval **defref = be->be_update_refs
? be->be_update_refs : default_referral;
struct berval **ref = referral_rewrite( defref,
NULL, dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
be->be_update_refs ? be->be_update_refs : default_referral,
NULL );
ref ? ref : defref, NULL );
ber_bvecfree( ref );
#endif
}
} else {

View file

@ -250,8 +250,13 @@ do_modrdn(
* if we don't hold it.
*/
if ( (be = select_backend( ndn, manageDSAit )) == NULL ) {
struct berval **ref = referral_rewrite( default_referral,
NULL, dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, default_referral, NULL );
NULL, NULL, ref ? ref : default_referral, NULL );
ber_bvecfree( ref );
goto cleanup;
}
@ -321,8 +326,15 @@ do_modrdn(
}
#ifndef SLAPD_MULTIMASTER
} else {
struct berval **defref = be->be_update_refs
? be->be_update_refs : default_referral;
struct berval **ref = referral_rewrite( defref,
NULL, dn, LDAP_SCOPE_DEFAULT );
send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
be->be_update_refs ? be->be_update_refs : default_referral, NULL );
ref ? ref : defref, NULL );
ber_bvecfree( ref );
#endif
}
} else {

View file

@ -45,7 +45,8 @@ int passwd_extop(
} else if( conn->c_authz_backend->be_update_ndn != NULL ) {
/* we SHOULD return a referral in this case */
*refs = conn->c_authz_backend->be_update_refs;
*refs = referral_rewrite( conn->c_authz_backend->be_update_refs,
NULL, NULL, LDAP_SCOPE_DEFAULT );
rc = LDAP_REFERRAL;
} else {

View file

@ -503,12 +503,24 @@ LDAP_SLAPD_F (int) add_replica_suffix LDAP_P(( Backend *be, int nr, const char *
LDAP_SLAPD_F (void) replog LDAP_P(( Backend *be, Operation *op, char *dn, void *change ));
/*
* result.c
* referral.c
*/
LDAP_SLAPD_F (int) validate_global_referral LDAP_P((
const char *url ));
LDAP_SLAPD_F (struct berval **) get_entry_referrals LDAP_P((
Backend *be, Connection *conn, Operation *op,
Entry *e ));
Entry *e, const char *target, int scope ));
LDAP_SLAPD_F (struct berval **) referral_rewrite LDAP_P((
struct berval **refs,
const char *base,
const char *target,
int scope ));
/*
* result.c
*/
LDAP_SLAPD_F (void) send_ldap_result LDAP_P((
Connection *conn, Operation *op,
@ -549,7 +561,7 @@ LDAP_SLAPD_F (void) send_search_result LDAP_P((
LDAP_SLAPD_F (int) send_search_reference LDAP_P((
Backend *be, Connection *conn, Operation *op,
Entry *e, struct berval **refs, int scope,
Entry *e, struct berval **refs,
LDAPControl **ctrls,
struct berval ***v2refs ));

336
servers/slapd/referral.c Normal file
View file

@ -0,0 +1,336 @@
/* referral.c - muck with referrals */
/* $OpenLDAP$ */
/*
* Copyright 1998-2001 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#include "portable.h"
#include <stdio.h>
#include <ac/socket.h>
#include <ac/errno.h>
#include <ac/signal.h>
#include <ac/string.h>
#include <ac/ctype.h>
#include <ac/time.h>
#include <ac/unistd.h>
#include "slap.h"
/*
* This routine generates the DN appropriate to return in
* an LDAP referral.
*/
static char * referral_dn_muck(
const char * refDN,
const char * baseDN,
const char * targetDN )
{
char *tmp;
char *nrefDN = NULL;
char *nbaseDN = NULL;
char *ntargetDN = NULL;
if( !baseDN ) {
/* no base, return target */
return targetDN ? ch_strdup( targetDN ) : NULL;
}
if( refDN ) {
nrefDN = dn_validate( tmp = ch_strdup( refDN ) );
if( !nrefDN ) {
/* Invalid refDN */
ch_free( tmp );
return NULL;
}
}
if( !targetDN ) {
/* continuation reference
* if refDN present return refDN
* else return baseDN
*/
return nrefDN ? nrefDN : ch_strdup( baseDN );
}
ntargetDN = dn_validate( tmp = ch_strdup( targetDN ) );
if( !ntargetDN ) {
ch_free( tmp );
ch_free( nrefDN );
return NULL;
}
if( nrefDN ) {
nbaseDN = dn_validate( tmp = ch_strdup( baseDN ) );
if( !nbaseDN ) {
/* Invalid baseDN */
ch_free( ntargetDN );
ch_free( nrefDN );
ch_free( tmp );
return NULL;
}
if( strcasecmp( nbaseDN, nrefDN ) == 0 ) {
ch_free( nrefDN );
ch_free( nbaseDN );
return ntargetDN;
}
{
/*
* FIXME: string based mucking
*/
char *muck;
size_t reflen, baselen, targetlen, mucklen;
reflen = strlen( nrefDN );
baselen = strlen( nbaseDN );
targetlen = strlen( ntargetDN );
if( targetlen < baselen ) {
ch_free( nrefDN );
ch_free( nbaseDN );
return ntargetDN;
}
if( strcasecmp( &ntargetDN[targetlen-baselen], nbaseDN ) ) {
/* target not subordinate to base */
ch_free( nrefDN );
ch_free( nbaseDN );
return ntargetDN;
}
mucklen = targetlen + reflen - baselen;
muck = ch_malloc( 1 + mucklen );
strncpy( muck, ntargetDN, targetlen-baselen );
strcpy( &muck[targetlen-baselen], nrefDN );
ch_free( nrefDN );
ch_free( nbaseDN );
ch_free( ntargetDN );
return muck;
}
}
return ntargetDN;
}
/* validate URL for global referral use
* LDAP URLs must not have:
* DN, attrs, scope, nor filter
* Any non-LDAP URL is okay
*
* XXYYZ: should return an error string
*/
int validate_global_referral( const char *url )
{
int rc;
LDAPURLDesc *lurl;
rc = ldap_url_parse_ext( url, &lurl );
switch( rc ) {
case LDAP_URL_SUCCESS:
break;
case LDAP_URL_ERR_BADSCHEME:
/* not LDAP hence valid */
return 0;
default:
/* other error, bail */
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
"referral: invalid URL (%s): %s (%d)\n",
url, "" /* ldap_url_error2str(rc) */, rc ));
#else
Debug( LDAP_DEBUG_ANY,
"referral: invalid URL (%s): %s (%d)\n",
url, "" /* ldap_url_error2str(rc) */, rc );
#endif
return 1;
}
rc = 0;
if( lurl->lud_dn && *lurl->lud_dn ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
"referral: URL (%s): contains DN\n",
url ));
#else
Debug( LDAP_DEBUG_ANY,
"referral: URL (%s): contains DN\n",
url, 0, 0 );
#endif
rc = 1;
} else if( lurl->lud_attrs ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
"referral: URL (%s): requests attributes\n",
url ));
#else
Debug( LDAP_DEBUG_ANY,
"referral: URL (%s): requests attributes\n",
url, 0, 0 );
#endif
rc = 1;
} else if( lurl->lud_scope != LDAP_SCOPE_DEFAULT ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
"referral: URL (%s): contains explicit scope\n",
url ));
#else
Debug( LDAP_DEBUG_ANY,
"referral: URL (%s): contains explicit scope\n",
url, 0, 0 );
#endif
rc = 1;
} else if( lurl->lud_filter ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
"referral: URL (%s): contains explicit filter\n",
url ));
#else
Debug( LDAP_DEBUG_ANY,
"referral: URL (%s): contains explicit filter\n",
url, 0, 0 );
#endif
rc = 1;
}
ldap_free_urldesc( lurl );
return rc;
}
struct berval ** referral_rewrite(
struct berval **in,
const char *base,
const char *target,
int scope )
{
int i, j;
struct berval **refs;
if( in == NULL ) return NULL;
for( i=0; in[i] != NULL ; i++ ) {
/* just count them */
}
if( i < 1 ) return NULL;
refs = ch_malloc( (i+1) * sizeof( struct berval * ) );
for( i=0,j=0; in[i] != NULL ; i++ ) {
LDAPURLDesc *url;
int rc = ldap_url_parse_ext( in[i]->bv_val, &url );
if( rc == LDAP_URL_ERR_BADSCHEME ) {
refs[j++] = ber_bvdup( in[i] );
continue;
} else if( rc != LDAP_URL_SUCCESS ) {
continue;
}
{
char *dn = url->lud_dn;
url->lud_dn = referral_dn_muck(
( dn && *dn ) ? dn : NULL, base, target );
ldap_memfree( dn );
}
if( url->lud_scope == LDAP_SCOPE_DEFAULT ) {
url->lud_scope = scope;
}
refs[j] = ch_malloc( sizeof( struct berval ) );
refs[j]->bv_val = ldap_url_desc2str( url );
refs[j]->bv_len = strlen( refs[j]->bv_val );
ldap_free_urldesc( url );
j++;
}
if( j == 0 ) {
ch_free( refs );
refs = NULL;
} else {
refs[j] = NULL;
}
return refs;
}
struct berval **get_entry_referrals(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
const char *dn,
int scope )
{
Attribute *attr;
struct berval **refs;
unsigned i, j;
AttributeDescription *ad_ref = slap_schema.si_ad_ref;
attr = attr_find( e->e_attrs, ad_ref );
if( attr == NULL ) return NULL;
for( i=0; attr->a_vals[i] != NULL; i++ ) {
/* count references */
}
if( i < 1 ) return NULL;
refs = ch_malloc( (i + 1) * sizeof(struct berval *));
for( i=0, j=0; attr->a_vals[i] != NULL; i++ ) {
unsigned k;
struct berval *ref = ber_bvdup( attr->a_vals[i] );
/* trim the label */
for( k=0; k<ref->bv_len; k++ ) {
if( isspace(ref->bv_val[k]) ) {
ref->bv_val[k] = '\0';
ref->bv_len = k;
break;
}
}
if( ref->bv_len > 0 ) {
refs[j++] = ref;
} else {
ber_bvfree( ref );
}
}
if( j == 0 ) {
ber_bvecfree( refs );
refs = NULL;
} else {
refs[j] = NULL;
}
/* we should check that a referral value exists... */
return refs;
}

View file

@ -95,87 +95,6 @@ static ber_tag_t req2res( ber_tag_t tag )
return tag;
}
static void trim_refs_urls(
struct berval **refs )
{
unsigned i;
if( refs == NULL ) return;
for( i=0; refs[i] != NULL; i++ ) {
if( refs[i]->bv_len > sizeof("ldap://")-1 &&
strncasecmp( refs[i]->bv_val, "ldap://",
sizeof("ldap://")-1 ) == 0 )
{
unsigned j;
for( j=sizeof("ldap://")-1; j<refs[i]->bv_len ; j++ ) {
if( refs[i]->bv_val[j] == '/' ) {
refs[i]->bv_val[j] = '\0';
refs[i]->bv_len = j;
break;
}
}
}
}
}
struct berval **get_entry_referrals(
Backend *be,
Connection *conn,
Operation *op,
Entry *e )
{
Attribute *attr;
struct berval **refs;
unsigned i, j;
AttributeDescription *ad_ref = slap_schema.si_ad_ref;
attr = attr_find( e->e_attrs, ad_ref );
if( attr == NULL ) return NULL;
for( i=0; attr->a_vals[i] != NULL; i++ ) {
/* count references */
}
if( i < 1 ) return NULL;
refs = ch_malloc( (i + 1) * sizeof(struct berval *));
for( i=0, j=0; attr->a_vals[i] != NULL; i++ ) {
unsigned k;
struct berval *ref = ber_bvdup( attr->a_vals[i] );
/* trim the label */
for( k=0; k<ref->bv_len; k++ ) {
if( isspace(ref->bv_val[k]) ) {
ref->bv_val[k] = '\0';
ref->bv_len = k;
break;
}
}
if( ref->bv_len > 0 ) {
refs[j++] = ref;
} else {
ber_bvfree( ref );
}
}
refs[j] = NULL;
if( j == 0 ) {
ber_bvecfree( refs );
refs = NULL;
}
/* we should check that a referral value exists... */
return refs;
}
static long send_ldap_ber(
Connection *conn,
BerElement *ber )
@ -511,15 +430,10 @@ send_ldap_result(
ref[0] && ref[0]->bv_val ? ref[0]->bv_val : "NULL",
NULL, NULL );
#endif
}
assert( err != LDAP_PARTIAL_RESULTS );
if( op->o_tag != LDAP_REQ_SEARCH ) {
trim_refs_urls( ref );
}
if ( err == LDAP_REFERRAL ) {
if( ref == NULL ) {
err = LDAP_NO_SUCH_OBJECT;
@ -654,8 +568,6 @@ send_search_result(
assert( err != LDAP_PARTIAL_RESULTS );
trim_refs_urls( refs );
if( op->o_protocol < LDAP_VERSION3 ) {
/* send references in search results */
if( err == LDAP_REFERRAL ) {
@ -1095,7 +1007,6 @@ send_search_reference(
Operation *op,
Entry *e,
struct berval **refs,
int scope,
LDAPControl **ctrls,
struct berval ***v2refs
)
@ -1227,7 +1138,6 @@ send_search_reference(
Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
#endif
return 0;
}

View file

@ -268,9 +268,13 @@ do_search(
* if we don't hold it.
*/
if ( (be = select_backend( nbase, manageDSAit )) == NULL ) {
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, default_referral, NULL );
struct berval **ref = referral_rewrite( default_referral,
NULL, base, scope );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
NULL, NULL, ref ? ref : default_referral, NULL );
ber_bvecfree( ref );
goto return_results;
}

View file

@ -47,7 +47,8 @@ SLAPD_OBJS = ../config.o ../ch_malloc.o ../backend.o ../charray.o \
../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
../controls.o ../kerberos.o ../passwd.o ../index.o \
../extended.o ../starttls.o ../sets.o ../mra.o
../extended.o ../starttls.o ../sets.o ../mra.o \
../referral.o
SLAPOBJS = $(SLAPD_OBJS) slapcommon.o mimic.o

View file

@ -123,7 +123,6 @@ int send_search_reference(
Operation *op,
Entry *e,
struct berval **refs,
int scope,
LDAPControl **ctrls,
struct berval ***v2refs
)
@ -132,13 +131,6 @@ int send_search_reference(
return -1;
}
struct berval **get_entry_referrals(
Backend *be, Connection *conn, Operation *op, Entry *e )
{
assert(0);
return NULL;
}
int slap_sasl_init(void)
{
return LDAP_SUCCESS;

View file

@ -24,7 +24,7 @@ directory ./test-repl
rootdn "cn=Replica, o=University of Michigan, c=US"
rootpw secret
updatedn "cn=Replica, o=University of Michigan, c=US"
updateref "ldap://localhost:9009/o=University%20of%20Michigan,c=US"
updateref "ldap://localhost:9009"
#ldbm#index objectClass eq
#ldbm#index cn,sn,uid pres,eq,sub
#bdb#index objectClass eq