From: Pierangelo Masarati Date: Thu, 25 Aug 2005 21:14:26 +0000 (+0000) Subject: allow undefined attrs to be "proxied" (ITS#3959) X-Git-Tag: OPENLDAP_REL_ENG_2_2_MP~576 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6cb8b144358fb705149b6ef0d0e4ca334c25c11f;p=openldap allow undefined attrs to be "proxied" (ITS#3959) --- diff --git a/servers/slapd/ad.c b/servers/slapd/ad.c index e3c64a2445..cc9a8fd889 100644 --- a/servers/slapd/ad.c +++ b/servers/slapd/ad.c @@ -668,7 +668,7 @@ int ad_inlist( if (!slap_schema.si_at_undefined->sat_ad) { const char *text; slap_bv2undef_ad(&attrs->an_name, - &attrs->an_desc, &text); + &attrs->an_desc, &text, 0); } else { attrs->an_desc = slap_schema.si_at_undefined->sat_ad; @@ -683,21 +683,24 @@ int ad_inlist( int slap_str2undef_ad( const char *str, AttributeDescription **ad, - const char **text ) + const char **text, + unsigned flags ) { struct berval bv; bv.bv_val = (char *) str; bv.bv_len = strlen( str ); - return slap_bv2undef_ad( &bv, ad, text ); + return slap_bv2undef_ad( &bv, ad, text, flags ); } int slap_bv2undef_ad( struct berval *bv, AttributeDescription **ad, - const char **text ) + const char **text, + unsigned flags ) { AttributeDescription *desc; + AttributeType *at; assert( ad != NULL ); @@ -712,23 +715,33 @@ int slap_bv2undef_ad( return LDAP_UNDEFINED_TYPE; } - for( desc = slap_schema.si_at_undefined->sat_ad; desc; - desc=desc->ad_next ) - { + /* use the appropriate type */ + if ( flags & SLAP_AD_PROXIED ) { + at = slap_schema.si_at_proxied; + + } else { + at = slap_schema.si_at_undefined; + } + + for( desc = at->sat_ad; desc; desc=desc->ad_next ) { if( desc->ad_cname.bv_len == bv->bv_len && - !strcasecmp( desc->ad_cname.bv_val, bv->bv_val )) + !strcasecmp( desc->ad_cname.bv_val, bv->bv_val ) ) { break; } } - + if( !desc ) { + if ( flags & SLAP_AD_NOINSERT ) { + *text = NULL; + return LDAP_UNDEFINED_TYPE; + } + desc = ch_malloc(sizeof(AttributeDescription) + 1 + bv->bv_len); desc->ad_flags = SLAP_DESC_NONE; - desc->ad_tags.bv_val = NULL; - desc->ad_tags.bv_len = 0; + BER_BVZERO( &desc->ad_tags ); desc->ad_cname.bv_len = bv->bv_len; desc->ad_cname.bv_val = (char *)(desc+1); @@ -738,7 +751,7 @@ int slap_bv2undef_ad( ldap_pvt_str2upper( desc->ad_cname.bv_val ); /* shouldn't we protect this for concurrency? */ - desc->ad_type = slap_schema.si_at_undefined; + desc->ad_type = at; ldap_pvt_thread_mutex_lock( &ad_undef_mutex ); desc->ad_next = desc->ad_type->sat_ad; desc->ad_type->sat_ad = desc; @@ -754,6 +767,56 @@ int slap_bv2undef_ad( return LDAP_SUCCESS; } +static int +undef_remove( + AttributeType *at, + char *name ) +{ + AttributeDescription **u_ad; + + for ( u_ad = &at->sat_ad; *u_ad; ) { + struct berval bv; + + ber_str2bv( name, 0, 0, &bv ); + + /* remove iff undef == name or undef == name;tag */ + if ( (*u_ad)->ad_cname.bv_len >= bv.bv_len + && strncasecmp( (*u_ad)->ad_cname.bv_val, bv.bv_val, bv.bv_len ) == 0 + && ( (*u_ad)->ad_cname.bv_val[ bv.bv_len ] == '\0' + || (*u_ad)->ad_cname.bv_val[ bv.bv_len ] == ';' ) ) + { + AttributeDescription *tmp = *u_ad; + + *u_ad = (*u_ad)->ad_next; + + ch_free( tmp ); + + } else { + u_ad = &(*u_ad)->ad_next; + } + } + + return 0; +} + +int +slap_ad_undef_remove( + char *name ) +{ + int rc; + + ldap_pvt_thread_mutex_lock( &ad_undef_mutex ); + + rc = undef_remove( slap_schema.si_at_undefined, name ); + if ( rc == 0 ) { + rc = undef_remove( slap_schema.si_at_proxied, name ); + } + + ldap_pvt_thread_mutex_unlock( &ad_undef_mutex ); + + return rc; +} + int an_find( AttributeName *a, diff --git a/servers/slapd/at.c b/servers/slapd/at.c index 44ec64c2e0..1b3b7b5991 100644 --- a/servers/slapd/at.c +++ b/servers/slapd/at.c @@ -247,6 +247,10 @@ at_destroy( void ) if ( slap_schema.si_at_undefined ) { ad_destroy(slap_schema.si_at_undefined->sat_ad); } + + if ( slap_schema.si_at_proxied ) { + ad_destroy(slap_schema.si_at_proxied->sat_ad); + } } int @@ -400,6 +404,18 @@ at_insert( } } + if ( sat->sat_oid ) { + slap_ad_undef_remove( sat->sat_oid ); + } + + names = sat->sat_names; + if ( names ) { + while ( *names ) { + slap_ad_undef_remove( *names ); + names++; + } + } + LDAP_STAILQ_INSERT_TAIL( &attr_list, sat, sat_next ); return 0; diff --git a/servers/slapd/ava.c b/servers/slapd/ava.c index 48c9b5a03f..07b13e2fc7 100644 --- a/servers/slapd/ava.c +++ b/servers/slapd/ava.c @@ -85,10 +85,15 @@ get_ava( rc = slap_bv2ad( &type, &aa->aa_desc, text ); if( rc != LDAP_SUCCESS ) { - Debug( LDAP_DEBUG_FILTER, - "get_ava: unknown attributeType %s\n", type.bv_val, 0, 0 ); - op->o_tmpfree( aa, op->o_tmpmemctx ); - return rc; + rc = slap_bv2undef_ad( &type, &aa->aa_desc, text, + SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); + + if( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_FILTER, + "get_ava: unknown attributeType %s\n", type.bv_val, 0, 0 ); + op->o_tmpfree( aa, op->o_tmpmemctx ); + return rc; + } } rc = asserted_value_validate_normalize( diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 09ad79807e..b38b3db935 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -534,12 +534,13 @@ ldap_build_entry( if ( slap_bv2ad( &a, &attr->a_desc, &text ) != LDAP_SUCCESS ) { - if ( slap_bv2undef_ad( &a, &attr->a_desc, &text ) - != LDAP_SUCCESS ) + if ( slap_bv2undef_ad( &a, &attr->a_desc, &text, + SLAP_AD_PROXIED ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, - "slap_bv2undef_ad(%s): %s\n", - a.bv_val, text, 0 ); + "%s ldap_build_entry: " + "slap_bv2undef_ad(%s): %s\n", + op->o_log_prefix, a.bv_val, text ); ch_free( attr ); continue; } diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index 996161dded..143bbe573a 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -897,7 +897,20 @@ ldap_back_map_config( /* * FIXME: this should become an err */ - goto error_return; + /* + * we create a fake "proxied" ad + * and add it here. + */ + + rc = slap_bv2undef_ad( &mapping->src, + &ad, &text, SLAP_AD_PROXIED ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "%s: line %d: source attributeType '%s': %d (%s)\n", + fname, lineno, src, + rc, text ? text : "" ); + goto error_return; + } } ad = NULL; @@ -909,6 +922,21 @@ ldap_back_map_config( "%s: line %d: warning, destination attributeType '%s' " "is not defined in schema\n", fname, lineno, dst ); + + /* + * we create a fake "proxied" ad + * and add it here. + */ + + rc = slap_bv2undef_ad( &mapping->dst, + &ad, &text, SLAP_AD_PROXIED ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "%s: line %d: source attributeType '%s': %d (%s)\n", + fname, lineno, dst, + rc, text ? text : "" ); + return 1; + } } } diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index bad6c95f77..92e89d8c38 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -920,8 +920,8 @@ meta_send_entry( attr->a_desc = NULL; if ( slap_bv2ad( &mapped, &attr->a_desc, &text ) != LDAP_SUCCESS) { - if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text ) - != LDAP_SUCCESS ) + if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text, + SLAP_AD_PROXIED ) != LDAP_SUCCESS ) { char buf[ SLAP_TEXT_BUFLEN ]; diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index e7cc311f27..9dc1af8d93 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -99,8 +99,13 @@ do_compare( rs->sr_err = slap_bv2ad( &desc, &ava.aa_desc, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { - send_ldap_result( op, rs ); - goto cleanup; + rs->sr_err = slap_bv2undef_ad( &desc, &ava.aa_desc, + &rs->sr_text, + SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); + if( rs->sr_err != LDAP_SUCCESS ) { + send_ldap_result( op, rs ); + goto cleanup; + } } rs->sr_err = asserted_value_validate_normalize( ava.aa_desc, diff --git a/servers/slapd/entry.c b/servers/slapd/entry.c index 6c1d45b1c4..54f7eaf296 100644 --- a/servers/slapd/entry.c +++ b/servers/slapd/entry.c @@ -216,10 +216,10 @@ str2entry2( char *s, int checkvals ) goto fail; } - rc = slap_bv2undef_ad( type+i, &ad, &text ); + rc = slap_bv2undef_ad( type+i, &ad, &text, 0 ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, - "<= str2entry: str2undef_ad(%s): %s\n", + "<= str2entry: slap_str2undef_ad(%s): %s\n", type[i].bv_val, text, 0 ); goto fail; } @@ -743,11 +743,11 @@ int entry_decode(struct berval *bv, Entry **e) if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= entry_decode: str2ad(%s): %s\n", ptr, text, 0 ); - rc = slap_bv2undef_ad( &bv, &ad, &text ); + rc = slap_bv2undef_ad( &bv, &ad, &text, 0 ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, - "<= entry_decode: str2undef_ad(%s): %s\n", + "<= entry_decode: slap_str2undef_ad(%s): %s\n", ptr, text, 0 ); return rc; } diff --git a/servers/slapd/filter.c b/servers/slapd/filter.c index 8ea1ad2ff0..eea855a4ae 100644 --- a/servers/slapd/filter.c +++ b/servers/slapd/filter.c @@ -171,17 +171,22 @@ get_filter( err = slap_bv2ad( &type, &f.f_desc, text ); if( err != LDAP_SUCCESS ) { - /* unrecognized attribute description or other error */ - Debug( LDAP_DEBUG_ANY, - "get_filter: conn %lu unknown attribute " - "type=%s (%d)\n", - op->o_connid, type.bv_val, err ); + err = slap_bv2undef_ad( &type, &f.f_desc, text, + SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); - f.f_choice = SLAPD_FILTER_COMPUTED; - f.f_result = LDAP_COMPARE_FALSE; - err = LDAP_SUCCESS; - *text = NULL; - break; + if ( err != LDAP_SUCCESS ) { + /* unrecognized attribute description or other error */ + Debug( LDAP_DEBUG_ANY, + "get_filter: conn %lu unknown attribute " + "type=%s (%d)\n", + op->o_connid, type.bv_val, err ); + + f.f_choice = SLAPD_FILTER_COMPUTED; + f.f_result = LDAP_COMPARE_FALSE; + err = LDAP_SUCCESS; + *text = NULL; + break; + } } assert( f.f_desc != NULL ); @@ -348,17 +353,22 @@ get_ssa( rc = slap_bv2ad( &desc, &ssa.sa_desc, text ); if( rc != LDAP_SUCCESS ) { - Debug( LDAP_DEBUG_ANY, - "get_ssa: conn %lu unknown attribute type=%s (%ld)\n", - op->o_connid, desc.bv_val, (long) rc ); - - /* skip over the rest of this filter */ - for ( tag = ber_first_element( ber, &len, &last ); - tag != LBER_DEFAULT; - tag = ber_next_element( ber, &len, last ) ) { - ber_scanf( ber, "x" ); + rc = slap_bv2undef_ad( &desc, &ssa.sa_desc, text, + SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); + + if( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "get_ssa: conn %lu unknown attribute type=%s (%ld)\n", + op->o_connid, desc.bv_val, (long) rc ); + + /* skip over the rest of this filter */ + for ( tag = ber_first_element( ber, &len, &last ); + tag != LBER_DEFAULT; + tag = ber_next_element( ber, &len, last ) ) { + ber_scanf( ber, "x" ); + } + return rc; } - return rc; } rc = LDAP_PROTOCOL_ERROR; @@ -880,16 +890,21 @@ get_simple_vrFilter( err = slap_bv2ad( &type, &vrf.vrf_desc, text ); if( err != LDAP_SUCCESS ) { - /* unrecognized attribute description or other error */ - Debug( LDAP_DEBUG_ANY, - "get_simple_vrFilter: conn %lu unknown " - "attribute type=%s (%d)\n", - op->o_connid, type.bv_val, err ); - - vrf.vrf_choice = SLAPD_FILTER_COMPUTED; - vrf.vrf_result = LDAP_COMPARE_FALSE; - err = LDAP_SUCCESS; - break; + err = slap_bv2undef_ad( &type, &vrf.vrf_desc, text, + SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); + + if( err != LDAP_SUCCESS ) { + /* unrecognized attribute description or other error */ + Debug( LDAP_DEBUG_ANY, + "get_simple_vrFilter: conn %lu unknown " + "attribute type=%s (%d)\n", + op->o_connid, type.bv_val, err ); + + vrf.vrf_choice = SLAPD_FILTER_COMPUTED; + vrf.vrf_result = LDAP_COMPARE_FALSE; + err = LDAP_SUCCESS; + break; + } } } break; diff --git a/servers/slapd/mra.c b/servers/slapd/mra.c index e72298feb9..4aa85fdb4b 100644 --- a/servers/slapd/mra.c +++ b/servers/slapd/mra.c @@ -141,7 +141,12 @@ get_mra( if( type.bv_val != NULL ) { rc = slap_bv2ad( &type, &ma.ma_desc, text ); if( rc != LDAP_SUCCESS ) { - return rc; + rc = slap_bv2undef_ad( &type, &ma.ma_desc, text, + SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); + + if( rc != LDAP_SUCCESS ) { + return rc; + } } } diff --git a/servers/slapd/overlays/rwmconf.c b/servers/slapd/overlays/rwmconf.c index f0e9d46b36..077f6f8f87 100644 --- a/servers/slapd/overlays/rwmconf.c +++ b/servers/slapd/overlays/rwmconf.c @@ -175,14 +175,13 @@ rwm_map_config( fname, lineno, src ); /* - * FIXME: this should become an err - * - * FIXME: or, we should create a fake ad + * we create a fake "proxied" ad * and add it here. */ rc = slap_bv2undef_ad( &mapping[0].m_src, - &mapping[0].m_src_ad, &text ); + &mapping[0].m_src_ad, &text, + SLAP_AD_PROXIED ); if ( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: line %d: source attributeType '%s': %d (%s)\n", @@ -202,7 +201,8 @@ rwm_map_config( fname, lineno, dst ); rc = slap_bv2undef_ad( &mapping[0].m_dst, - &mapping[0].m_dst_ad, &text ); + &mapping[0].m_dst_ad, &text, + SLAP_AD_PROXIED ); if ( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: line %d: destination attributeType '%s': %d (%s)\n", diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 8881076dd8..899d13dfcc 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -159,12 +159,17 @@ LDAP_SLAPD_F (int) ad_inlist LDAP_P(( LDAP_SLAPD_F (int) slap_str2undef_ad LDAP_P(( const char *, AttributeDescription **ad, - const char **text )); + const char **text, + unsigned proxied )); LDAP_SLAPD_F (int) slap_bv2undef_ad LDAP_P(( struct berval *bv, AttributeDescription **ad, - const char **text )); + const char **text, + unsigned proxied )); + +LDAP_SLAPD_F (int) slap_ad_undef_remove LDAP_P(( + char *name )); LDAP_SLAPD_F (AttributeDescription *) ad_find_tags LDAP_P(( AttributeType *type, diff --git a/servers/slapd/schema_prep.c b/servers/slapd/schema_prep.c index 54d16095e6..a9cfd1e05b 100644 --- a/servers/slapd/schema_prep.c +++ b/servers/slapd/schema_prep.c @@ -1023,7 +1023,24 @@ static AttributeType slap_at_undefined = { NULL, /* sup */ NULL, /* subtypes */ NULL, NULL, NULL, NULL, /* matching rules routines */ - NULL, /* syntax (this may need to be defined) */ + NULL, /* syntax (will be set later to "octetString") */ + NULL, /* schema check function */ + NULL, /* oidmacro */ + SLAP_AT_ABSTRACT|SLAP_AT_FINAL, /* mask */ + { NULL }, /* next */ + NULL /* attribute description */ + /* mutex (don't know how to initialize it :) */ +}; + +static AttributeType slap_at_proxied = { + { "1.1.1", NULL, "Catchall for undefined proxied attribute types", 1, NULL, + NULL, NULL, NULL, NULL, + 0, 0, 0, 0, LDAP_SCHEMA_USER_APPLICATIONS, NULL }, /* LDAPAttributeType */ + BER_BVC("PROXIED"), /* cname */ + NULL, /* sup */ + NULL, /* subtypes */ + NULL, NULL, NULL, NULL, /* matching rules routines (will be set later) */ + NULL, /* syntax (will be set later to "octetString") */ NULL, /* schema check function */ NULL, /* oidmacro */ SLAP_AT_ABSTRACT|SLAP_AT_FINAL, /* mask */ @@ -1134,6 +1151,13 @@ slap_schema_load( void ) slap_at_undefined.sat_syntax = slap_schema.si_syn_octetString; slap_schema.si_at_undefined = &slap_at_undefined; + slap_at_proxied.sat_equality = mr_find( "octetStringMatch" ); + slap_at_proxied.sat_approx = mr_find( "octetStringMatch" ); + slap_at_proxied.sat_ordering = mr_find( "octetStringOrderingMatch" ); + slap_at_proxied.sat_substr = mr_find( "octetStringSubstringsMatch" ); + slap_at_proxied.sat_syntax = slap_schema.si_syn_octetString; + slap_schema.si_at_proxied = &slap_at_proxied; + ldap_pvt_thread_mutex_init( &ad_undef_mutex ); ldap_pvt_thread_mutex_init( &oc_undef_mutex ); diff --git a/servers/slapd/search.c b/servers/slapd/search.c index b83b2d165d..11b5f0733d 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -155,8 +155,13 @@ do_search( op->ors_attrs[i].an_desc = NULL; op->ors_attrs[i].an_oc = NULL; op->ors_attrs[i].an_oc_exclude = 0; - slap_bv2ad(&op->ors_attrs[i].an_name, - &op->ors_attrs[i].an_desc, &dummy); + if ( slap_bv2ad( &op->ors_attrs[i].an_name, + &op->ors_attrs[i].an_desc, &dummy ) != LDAP_SUCCESS ) + { + slap_bv2undef_ad( &op->ors_attrs[i].an_name, + &op->ors_attrs[i].an_desc, &dummy, + SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); + }; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 853ad6a9ec..43da098957 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -803,6 +803,13 @@ typedef struct slap_attr_desc { #define SLAP_DESC_TAG_RANGE 0x80U } AttributeDescription; +/* flags to slap_*2undef_ad to register undefined (0, the default) + * or proxied (SLAP_AD_PROXIED) AttributeDescriptions; the additional + * SLAP_AD_NOINSERT is to lookup without insert */ +#define SLAP_AD_UNDEF 0x00U +#define SLAP_AD_PROXIED 0x01U +#define SLAP_AD_NOINSERT 0x02U + typedef struct slap_attr_name { struct berval an_name; AttributeDescription *an_desc; @@ -919,6 +926,9 @@ struct slap_internal_schema { /* Undefined Attribute Type */ AttributeType *si_at_undefined; + /* "Proxied" Attribute Type */ + AttributeType *si_at_proxied; + /* Matching Rules */ MatchingRule *si_mr_distinguishedNameMatch; MatchingRule *si_mr_dnSubtreeMatch;