rework internal handling of strings to minimize temporary allocation; impacts rewrite() and rewrite_session() behavior in case of no rewriting; set LDAPURLDesc lud_scope to LDAP_SCOPE_DEFAULT if set to LDAP_SCOPE_BASE, so no trailing '??base' is added to referrals...

This commit is contained in:
Pierangelo Masarati 2005-01-01 16:11:38 +00:00
parent 52b878dcc0
commit 250c096713
4 changed files with 243 additions and 142 deletions

View file

@ -34,7 +34,6 @@ rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
(struct ldaprwmap *)on->on_bi.bi_private;
struct berval dn = BER_BVNULL,
*dnp = NULL,
ndn = BER_BVNULL;
int rc = 0;
dncookie dc;
@ -56,28 +55,32 @@ rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
* and the caller sets op->o_req_dn = op->o_req_ndn,
* only rewrite the op->o_req_ndn and use it as
* op->o_req_dn as well */
ndn = op->o_req_ndn;
if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
dnp = &dn;
dn = op->o_req_dn;
rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
} else {
rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
}
rc = rwm_dn_massage( &dc, &op->o_req_dn, dnp, &ndn );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
if ( ( dnp && dn.bv_val == op->o_req_dn.bv_val ) ||
( !dnp && ndn.bv_val == op->o_req_ndn.bv_val ) ) {
if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
|| ndn.bv_val == op->o_req_ndn.bv_val )
{
return LDAP_SUCCESS;
}
op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
if ( dnp ) {
op->o_req_ndn = ndn;
if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
op->o_req_dn = dn;
} else {
op->o_req_dn = ndn;
}
op->o_req_ndn = ndn;
return LDAP_SUCCESS;
}
@ -494,7 +497,9 @@ rwm_op_modrdn( Operation *op, SlapReply *rs )
dc.tofrom = 0;
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
rc = rwm_dn_massage( &dc, op->orr_newSup, &newSup, &nnewSup );
newSup = *op->orr_newSup;
nnewSup = *op->orr_nnewSup;
rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
@ -709,7 +714,8 @@ rwm_matched( Operation *op, SlapReply *rs )
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
ber_str2bv( rs->sr_matched, 0, 0, &dn );
rc = rwm_dn_massage( &dc, &dn, &mdn, NULL );
mdn = dn;
rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
if ( rc != LDAP_SUCCESS ) {
rs->sr_err = rc;
rs->sr_text = "Rewrite error";
@ -938,7 +944,9 @@ rwm_send_entry( Operation *op, SlapReply *rs )
* from the one known to the meta, and a DN with unknown
* attributes is returned.
*/
rc = rwm_dn_massage( &dc, &e->e_name, &dn, &ndn );
dn = e->e_name;
ndn = e->e_nname;
rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
if ( rc != LDAP_SUCCESS ) {
rc = 1;
goto fail;

View file

@ -96,8 +96,10 @@ typedef struct dncookie {
#endif /* !ENABLE_REWRITE */
} dncookie;
int rwm_dn_massage( dncookie *dc, struct berval *in,
struct berval *dn, struct berval *ndn );
int rwm_dn_massage( dncookie *dc, struct berval *in, struct berval *dn );
int rwm_dn_massage_pretty( dncookie *dc, struct berval *in, struct berval *pdn );
int rwm_dn_massage_normalize( dncookie *dc, struct berval *in, struct berval *ndn );
int rwm_dn_massage_pretty_normalize( dncookie *dc, struct berval *in, struct berval *pdn, struct berval *ndn );
/* attributeType/objectClass mapping */
int rwm_mapping_cmp (const void *, const void *);

View file

@ -36,64 +36,148 @@
/* FIXME: after rewriting, we should also remap attributes ... */
/*
* massages "in" and normalizes it into "ndn"
*
* "ndn" may be untouched if no massaging occurred and its value was not null
*/
int
rwm_dn_massage_normalize(
dncookie *dc,
struct berval *in,
struct berval *ndn )
{
int rc;
struct berval mdn = BER_BVNULL;
/* massage and normalize a DN */
rc = rwm_dn_massage( dc, in, &mdn );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
if ( mdn.bv_val == in->bv_val && !BER_BVISNULL( ndn ) ) {
return rc;
}
rc = dnNormalize( 0, NULL, NULL, &mdn, ndn, NULL );
if ( mdn.bv_val != in->bv_val ) {
ch_free( mdn.bv_val );
}
return rc;
}
/*
* massages "in" and prettifies it into "pdn"
*
* "pdn" may be untouched if no massaging occurred and its value was not null
*/
int
rwm_dn_massage_pretty(
dncookie *dc,
struct berval *in,
struct berval *pdn )
{
int rc;
struct berval mdn = BER_BVNULL;
/* massage and pretty a DN */
rc = rwm_dn_massage( dc, in, &mdn );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
if ( mdn.bv_val == in->bv_val && !BER_BVISNULL( pdn ) ) {
return rc;
}
rc = dnPretty( NULL, &mdn, pdn, NULL );
if ( mdn.bv_val != in->bv_val ) {
ch_free( mdn.bv_val );
}
return rc;
}
/*
* massages "in" and prettifies and normalizes it into "pdn" and "ndn"
*
* "pdn" may be untouched if no massaging occurred and its value was not null;
* "ndn" may be untouched if no massaging occurred and its value was not null;
* if no massage occurred and "ndn" value was not null, it is filled
* with the normaized value of "pdn", much like ndn = dnNormalize( pdn )
*/
int
rwm_dn_massage_pretty_normalize(
dncookie *dc,
struct berval *in,
struct berval *pdn,
struct berval *ndn )
{
int rc;
struct berval mdn = BER_BVNULL;
/* massage, pretty and normalize a DN */
rc = rwm_dn_massage( dc, in, &mdn );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
if ( mdn.bv_val == in->bv_val && !BER_BVISNULL( pdn ) ) {
if ( BER_BVISNULL( ndn ) ) {
rc = dnNormalize( 0, NULL, NULL, &mdn, ndn, NULL );
}
return rc;
}
rc = dnPrettyNormal( NULL, &mdn, pdn, ndn, NULL );
if ( mdn.bv_val != in->bv_val ) {
ch_free( mdn.bv_val );
}
return rc;
}
#ifdef ENABLE_REWRITE
/*
* massages "in" into "dn"
*
* "dn" may contain the value of "in" if no massage occurred
*/
int
rwm_dn_massage(
dncookie *dc,
struct berval *in,
struct berval *dn,
struct berval *ndn
struct berval *dn
)
{
int rc = 0;
struct berval mdn;
assert( dc );
assert( in );
if ( dn == NULL && ndn == NULL ) {
return LDAP_OTHER;
}
assert( dn );
rc = rewrite_session( dc->rwmap->rwm_rw, dc->ctx,
( in->bv_len ? in->bv_val : "" ),
dc->conn, &mdn.bv_val );
switch ( rc ) {
case REWRITE_REGEXEC_OK:
if ( !BER_BVISNULL( &mdn ) ) {
if ( !BER_BVISNULL( &mdn ) && mdn.bv_val != in->bv_val ) {
mdn.bv_len = strlen( mdn.bv_val );
if ( dn != NULL && ndn != NULL ) {
rc = dnPrettyNormal( NULL, &mdn, dn, ndn, NULL );
} else if ( dn != NULL ) {
rc = dnPretty( NULL, &mdn, dn, NULL );
} else if ( ndn != NULL) {
rc = dnNormalize( 0, NULL, NULL, &mdn, ndn, NULL );
}
if ( mdn.bv_val != in->bv_val ) {
ch_free( mdn.bv_val );
}
*dn = mdn;
} else {
/* we assume the input string is already in pretty form,
* and that the normalized version is already available */
if ( dn ) {
*dn = *in;
if ( ndn ) {
BER_BVZERO( ndn );
}
} else {
*ndn = *in;
}
rc = LDAP_SUCCESS;
*dn = *in;
}
rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_ARGS,
"[rw] %s: \"%s\" -> \"%s\"\n",
dc->ctx, in->bv_val, dn ? dn->bv_val : ndn->bv_val );
dc->ctx, in->bv_val, dn->bv_val );
break;
case REWRITE_REGEXEC_UNWILLING:
@ -125,39 +209,25 @@ rwm_dn_massage(
int
rwm_dn_massage(
dncookie *dc,
struct berval *tmpin,
struct berval *dn,
struct berval *ndn
struct berval *in,
struct berval *dn
)
{
int i, src, dst;
struct berval pretty = BER_BVNULL,
normal = BER_BVNULL,
*in = tmpin;
struct berval tmpin;
if ( dn == NULL && ndn == NULL ) {
return LDAP_OTHER;
}
assert( dc );
assert( in );
assert( dn );
if ( in == NULL || BER_BVISNULL( in ) ) {
if ( dn ) {
BER_BVZERO( dn );
}
if ( ndn ) {
BER_BVZERO( ndn );
}
BER_BVZERO( dn );
if ( BER_BVISNULL( in ) ) {
return LDAP_SUCCESS;
}
if ( dc->rwmap == NULL || dc->rwmap->rwm_suffix_massage == NULL ) {
if ( dn ) {
*dn = *in;
if ( ndn ) {
BER_BVZERO( ndn );
}
} else {
*ndn = *in;
}
*dn = *in;
return LDAP_SUCCESS;
}
@ -165,6 +235,8 @@ rwm_dn_massage(
src = 0 + dc->normalized;
dst = 2 + dc->normalized;
tmpin = *in;
} else {
int rc;
@ -174,39 +246,31 @@ rwm_dn_massage(
/* DN from remote server may be in arbitrary form.
* Pretty it so we can parse reliably.
*/
if ( dc->normalized && dn == NULL ) {
rc = dnNormalize( 0, NULL, NULL, in, &normal, NULL );
} else if ( !dc->normalized && ndn == NULL ) {
rc = dnPretty( NULL, in, &pretty, NULL );
if ( dc->normalized ) {
rc = dnNormalize( 0, NULL, NULL, in, &tmpin, NULL );
} else {
rc = dnPrettyNormal( NULL, in, &pretty, &normal, NULL );
rc = dnPretty( NULL, in, &tmpin, NULL );
}
if ( rc != LDAP_SUCCESS ) {
return rc;
}
if ( dc->normalized && !BER_BVISNULL( &normal ) ) {
in = &normal;
} else if ( !dc->normalized && !BER_BVISNULL( &pretty ) ) {
in = &pretty;
}
}
for ( i = 0;
dc->rwmap->rwm_suffix_massage[i].bv_val != NULL;
i += 4 ) {
!BER_BVISNULL( &dc->rwmap->rwm_suffix_massage[i] );
i += 4 )
{
int aliasLength = dc->rwmap->rwm_suffix_massage[i+src].bv_len;
int diff = in->bv_len - aliasLength;
int diff = tmpin.bv_len - aliasLength;
if ( diff < 0 ) {
/* alias is longer than dn */
continue;
} else if ( diff > 0 && ( !DN_SEPARATOR(in->bv_val[diff-1]))) {
} else if ( diff > 0 && ( !DN_SEPARATOR(tmpin.bv_val[diff-1])))
{
/* FIXME: DN_SEPARATOR() is intended to work
* on a normalized/pretty DN, so that ';'
* is never used as a DN separator */
@ -214,45 +278,28 @@ rwm_dn_massage(
/* At a DN Separator */
}
if ( !strcmp( dc->rwmap->rwm_suffix_massage[i+src].bv_val, &in->bv_val[diff] ) ) {
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 );
if ( !strcmp( dc->rwmap->rwm_suffix_massage[i+src].bv_val,
&tmpin.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, tmpin.bv_val, diff );
strcpy( &dn->bv_val[diff], dc->rwmap->rwm_suffix_massage[i+dst].bv_val );
Debug( LDAP_DEBUG_ARGS,
"rwm_dn_massage:"
" converted \"%s\" to \"%s\"\n",
in->bv_val, out->bv_val, 0 );
if ( dn && ndn ) {
rc = dnNormalize( 0, NULL, NULL, dn, ndn, NULL );
}
in->bv_val, dn->bv_val, 0 );
break;
}
}
if ( !BER_BVISNULL( &pretty ) ) {
ch_free( pretty.bv_val );
if ( tmpin.bv_val != in->bv_val ) {
ch_free( tmpin.bv_val );
}
if ( !BER_BVISNULL( &normal ) ) {
ch_free( normal.bv_val );
}
in = tmpin;
/* Nothing matched, just return the original DN */
if ( dc->normalized && BER_BVISNULL( ndn ) ) {
*ndn = *in;
} else if ( !dc->normalized && BER_BVISNULL( dn ) ) {
if ( BER_BVISNULL( dn ) ) {
*dn = *in;
}

View file

@ -360,7 +360,7 @@ map_attr_value(
struct berval *mapped_value,
int remap )
{
struct berval vtmp;
struct berval vtmp = BER_BVNULL;
int freeval = 0;
rwm_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap );
@ -388,7 +388,8 @@ map_attr_value(
fdc.ctx = "searchFilterAttrDN";
#endif /* ENABLE_REWRITE */
rc = rwm_dn_massage( &fdc, value, NULL, &vtmp );
vtmp = *value;
rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
switch ( rc ) {
case LDAP_SUCCESS:
if ( vtmp.bv_val != value->bv_val ) {
@ -762,7 +763,8 @@ rwm_referral_rewrite(
int i, last;
dncookie dc;
struct berval dn, ndn, *ndnp = NULL;
struct berval dn = BER_BVNULL,
ndn = BER_BVNULL;
assert( a_vals );
@ -779,16 +781,16 @@ rwm_referral_rewrite(
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ );
for ( last = 0; !BER_BVISNULL( &a_vals[last] ); 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) );
*pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
}
}
last--;
for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
struct berval olddn, oldval;
@ -804,9 +806,26 @@ rwm_referral_rewrite(
}
continue;
}
/* FIXME: URLs like "ldap:///dc=suffix" if passed
* thru ldap_url_parse() and ldap_url_desc2str()
* get rewritten as "ldap:///dc=suffix??base";
* we don't want this to occur... */
if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
ludp->lud_scope = LDAP_SCOPE_DEFAULT;
}
ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
rc = rwm_dn_massage( &dc, &olddn, &dn, ndnp );
dn = olddn;
if ( pa_nvals ) {
ndn = olddn;
rc = rwm_dn_massage_pretty_normalize( &dc, &olddn,
&dn, &ndn );
} else {
rc = rwm_dn_massage_pretty( &dc, &olddn, &dn );
}
switch ( rc ) {
case LDAP_UNWILLING_TO_PERFORM:
/*
@ -834,9 +853,12 @@ rwm_referral_rewrite(
ludp->lud_dn = dn.bv_val;
newurl = ldap_url_desc2str( ludp );
ludp->lud_dn = olddn.bv_val;
ch_free( dn.bv_val );
if ( newurl == NULL ) {
/* FIXME: leave attr untouched
* even if ldap_url_desc2str failed... */
* even if ldap_url_desc2str failed...
*/
break;
}
@ -846,9 +868,12 @@ rwm_referral_rewrite(
if ( pa_nvals ) {
ludp->lud_dn = ndn.bv_val;
newurl = ldap_url_desc2str( ludp );
ludp->lud_dn = olddn.bv_val;
ch_free( ndn.bv_val );
if ( newurl == NULL ) {
/* FIXME: leave attr untouched
* even if ldap_url_desc2str failed... */
* even if ldap_url_desc2str failed...
*/
ch_free( a_vals[i].bv_val );
a_vals[i] = oldval;
break;
@ -901,12 +926,12 @@ rwm_dnattr_rewrite(
int i, last;
dncookie dc;
struct berval dn, *dnp = NULL, ndn, *ndnp = NULL;
struct berval dn = BER_BVNULL,
ndn = BER_BVNULL;
BerVarray in;
if ( a_vals ) {
in = a_vals;
dnp = &dn;
} else {
if ( pa_nvals == NULL || *pa_nvals == NULL ) {
@ -929,20 +954,30 @@ rwm_dnattr_rewrite(
#endif /* ! ENABLE_REWRITE */
for ( last = 0; !BER_BVISNULL( &in[last] ); 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) );
*pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
}
}
last--;
for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
int rc;
rc = rwm_dn_massage( &dc, &in[i], dnp, ndnp );
if ( a_vals ) {
dn = in[i];
if ( pa_nvals ) {
ndn = (*pa_nvals)[i];
rc = rwm_dn_massage_pretty_normalize( &dc, &in[i], &dn, &ndn );
} else {
rc = rwm_dn_massage_pretty( &dc, &in[i], &dn );
}
} else {
ndn = in[i];
rc = rwm_dn_massage_normalize( &dc, &in[i], &ndn );
}
switch ( rc ) {
case LDAP_UNWILLING_TO_PERFORM:
/*
@ -979,8 +1014,6 @@ rwm_dnattr_rewrite(
}
} 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;
@ -1022,9 +1055,18 @@ rwm_referral_result_rewrite(
continue;
}
/* FIXME: URLs like "ldap:///dc=suffix" if passed
* thru ldap_url_parse() and ldap_url_desc2str()
* get rewritten as "ldap:///dc=suffix??base";
* we don't want this to occur... */
if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
ludp->lud_scope = LDAP_SCOPE_DEFAULT;
}
ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
rc = rwm_dn_massage( dc, &olddn, &dn, NULL );
dn = olddn;
rc = rwm_dn_massage_pretty( dc, &olddn, &dn );
switch ( rc ) {
case LDAP_UNWILLING_TO_PERFORM:
/*
@ -1050,7 +1092,8 @@ rwm_referral_result_rewrite(
newurl = ldap_url_desc2str( ludp );
if ( newurl == NULL ) {
/* FIXME: leave attr untouched
* even if ldap_url_desc2str failed... */
* even if ldap_url_desc2str failed...
*/
break;
}
@ -1083,7 +1126,8 @@ rwm_dnattr_result_rewrite(
struct berval dn;
int rc;
rc = rwm_dn_massage( dc, &a_vals[i], &dn, NULL );
dn = a_vals[i];
rc = rwm_dn_massage_pretty( dc, &a_vals[i], &dn );
switch ( rc ) {
case LDAP_UNWILLING_TO_PERFORM:
/*