From 250c0967130bd16283b44088416b822f1b9981ed Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sat, 1 Jan 2005 16:11:38 +0000 Subject: [PATCH] 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... --- servers/slapd/overlays/rwm.c | 28 ++-- servers/slapd/overlays/rwm.h | 6 +- servers/slapd/overlays/rwmdn.c | 255 +++++++++++++++++++------------- servers/slapd/overlays/rwmmap.c | 96 ++++++++---- 4 files changed, 243 insertions(+), 142 deletions(-) diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c index 1c1da03a81..b56915824f 100644 --- a/servers/slapd/overlays/rwm.c +++ b/servers/slapd/overlays/rwm.c @@ -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; diff --git a/servers/slapd/overlays/rwm.h b/servers/slapd/overlays/rwm.h index 4b01146498..932275ccca 100644 --- a/servers/slapd/overlays/rwm.h +++ b/servers/slapd/overlays/rwm.h @@ -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 *); diff --git a/servers/slapd/overlays/rwmdn.c b/servers/slapd/overlays/rwmdn.c index bcf5f6a28a..1fc7692705 100644 --- a/servers/slapd/overlays/rwmdn.c +++ b/servers/slapd/overlays/rwmdn.c @@ -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 ( !BER_BVISNULL( &normal ) ) { - ch_free( normal.bv_val ); + if ( tmpin.bv_val != in->bv_val ) { + ch_free( tmpin.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; } diff --git a/servers/slapd/overlays/rwmmap.c b/servers/slapd/overlays/rwmmap.c index 033e84b51c..2086daa4e6 100644 --- a/servers/slapd/overlays/rwmmap.c +++ b/servers/slapd/overlays/rwmmap.c @@ -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: /* -- 2.39.5