From 6e6118c6cc2866ccc208c279c27f4c8fac282b7a Mon Sep 17 00:00:00 2001 From: Mark Valence Date: Mon, 19 Feb 2001 19:14:12 +0000 Subject: [PATCH] attribute & objectclass mapping rules --- servers/slapd/back-ldap/add.c | 21 ++- servers/slapd/back-ldap/attribute.c | 35 +++- servers/slapd/back-ldap/back-ldap.h | 24 ++- servers/slapd/back-ldap/bind.c | 2 +- servers/slapd/back-ldap/compare.c | 12 +- servers/slapd/back-ldap/config.c | 245 +++++++++++++++++++++++++++- servers/slapd/back-ldap/group.c | 12 +- servers/slapd/back-ldap/init.c | 27 +++ servers/slapd/back-ldap/modify.c | 22 +-- servers/slapd/back-ldap/search.c | 99 ++++++++--- 10 files changed, 442 insertions(+), 57 deletions(-) diff --git a/servers/slapd/back-ldap/add.c b/servers/slapd/back-ldap/add.c index f282ee0f90..de1b4c1a97 100644 --- a/servers/slapd/back-ldap/add.c +++ b/servers/slapd/back-ldap/add.c @@ -58,8 +58,7 @@ ldap_back_add( int i; Attribute *a; LDAPMod **attrs; - - char *mdn; + char *mdn, *mapped; lc = ldap_back_getconn(li, conn, op); if ( !lc || !ldap_back_dobind( lc, op ) ) { @@ -77,14 +76,20 @@ ldap_back_add( /* Create array of LDAPMods for ldap_add() */ attrs = (LDAPMod **)ch_malloc(sizeof(LDAPMod *)*i); - attrs[i-1] = 0; - for (i=0, a=e->e_attrs; a; i++, a=a->a_next) { - attrs[i] = (LDAPMod *)ch_malloc(sizeof(LDAPMod)); - attrs[i]->mod_op = LDAP_MOD_BVALUES; - attrs[i]->mod_type = a->a_desc->ad_cname->bv_val; - attrs[i]->mod_vals.modv_bvals = a->a_vals; + for (i=0, a=e->e_attrs; a; a=a->a_next) { + mapped = ldap_back_map(&li->at_map, a->a_desc->ad_cname->bv_val, 0); + if (mapped != NULL) { + attrs[i] = (LDAPMod *)ch_malloc(sizeof(LDAPMod)); + if (attrs[i] != NULL) { + attrs[i]->mod_op = LDAP_MOD_BVALUES; + attrs[i]->mod_type = mapped; + attrs[i]->mod_vals.modv_bvals = a->a_vals; + i++; + } + } } + attrs[i] = NULL; ldap_add_s(lc->ld, mdn, attrs); for (--i; i>= 0; --i) diff --git a/servers/slapd/back-ldap/attribute.c b/servers/slapd/back-ldap/attribute.c index df465f6619..e8b49e052a 100644 --- a/servers/slapd/back-ldap/attribute.c +++ b/servers/slapd/back-ldap/attribute.c @@ -31,10 +31,10 @@ ldap_back_attribute( ) { struct ldapinfo *li = (struct ldapinfo *) be->be_private; - int rc = 1, i, j, count; + int rc = 1, i, j, count, is_oc; Attribute *attr; struct berval **abv, **v; - char **vs; + char **vs, *mapped; LDAPMessage *result, *e; char *gattr[2]; LDAP *ld; @@ -42,6 +42,7 @@ ldap_back_attribute( *vals = NULL; if (target != NULL && strcmp(target->e_ndn, e_ndn) == 0) { /* we already have a copy of the entry */ + /* attribute and objectclass mapping has already been done */ if ((attr = attr_find(target->e_attrs, entry_at)) == NULL) return(1); @@ -61,31 +62,49 @@ ldap_back_attribute( } } else { + mapped = ldap_back_map(&li->at_map, entry_at->ad_cname->bv_val, 0); + if (mapped == NULL) + return(1); + if (ldap_initialize(&ld, li->url) != LDAP_SUCCESS) { return(1); } if (ldap_bind_s(ld, li->binddn, li->bindpw, LDAP_AUTH_SIMPLE) == LDAP_SUCCESS) { - gattr[0] = entry_at->ad_cname->bv_val; + gattr[0] = mapped; gattr[1] = NULL; if (ldap_search_ext_s(ld, e_ndn, LDAP_SCOPE_BASE, "(objectclass=*)", gattr, 0, NULL, NULL, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result) == LDAP_SUCCESS) { if ((e = ldap_first_entry(ld, result)) != NULL) { - vs = ldap_get_values(ld, e, entry_at->ad_cname->bv_val); + vs = ldap_get_values(ld, e, mapped); if (vs != NULL) { for ( count = 0; vs[count] != NULL; count++ ) { } v = (struct berval **) ch_calloc( (count + 1), sizeof(struct berval *) ); if (v == NULL) { ldap_value_free(vs); } else { + is_oc = (strcasecmp("objectclass", mapped) == 0); for ( i = 0, j = 0; i < count; i++) { - v[j] = ber_bvstr( vs[i] ); - if( v[j] == NULL ) + if (!is_oc) { + v[j] = ber_bvstr( vs[i] ); + if( v[j] == NULL ) + ch_free(vs[i]); + else + j++; + } else { + mapped = ldap_back_map(&li->oc_map, vs[i], 1); + if (mapped) { + mapped = ch_strdup( mapped ); + if (mapped) { + v[j] = ber_bvstr( mapped ); + if (v[j]) + j++; + } + } ch_free(vs[i]); - else - j++; + } } v[j] = NULL; *vals = v; diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index fdbe1a2d9c..aafb09f794 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -52,6 +52,18 @@ struct ldapconn { int bound; }; +struct ldapmap { + int drop_missing; + + Avlnode *map; + Avlnode *remap; +}; + +struct ldapmapping { + char *src; + char *dst; +}; + struct ldapinfo { char *url; #if 0 /* unused! */ @@ -62,6 +74,9 @@ struct ldapinfo { char *bindpw; ldap_pvt_thread_mutex_t conn_mutex; Avlnode *conntree; + + struct ldapmap oc_map; + struct ldapmap at_map; }; struct ldapconn *ldap_back_getconn(struct ldapinfo *li, struct slap_conn *conn, @@ -76,7 +91,14 @@ char *ldap_back_dn_restore(struct ldapinfo *li, char *dn, int normalized); int conn_cmp(const void *, const void *); int conn_dup(void *, void *); - + +int mapping_cmp (const void *, const void *); +int mapping_dup (void *, void *); + +char *ldap_back_map ( struct ldapmap *map, char *s, int remap ); +char *ldap_back_map_filter ( struct ldapinfo *li, char *f, int remap ); +char **ldap_back_map_attrs ( struct ldapinfo *li, char **a, int remap ); + LDAP_END_DECL #endif diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index 6fa83775b1..89ef3f517b 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -199,7 +199,7 @@ ldap_back_getconn(struct ldapinfo *li, Connection *conn, Operation *op) err = avl_insert( &li->conntree, (caddr_t)lc, conn_cmp, conn_dup ); -#if 1 +#if 0 myprint( li->conntree ); #endif diff --git a/servers/slapd/back-ldap/compare.c b/servers/slapd/back-ldap/compare.c index e5db2342a7..4221d6fbcd 100644 --- a/servers/slapd/back-ldap/compare.c +++ b/servers/slapd/back-ldap/compare.c @@ -57,7 +57,7 @@ ldap_back_compare( { struct ldapinfo *li = (struct ldapinfo *) be->be_private; struct ldapconn *lc; - char *mdn; + char *mdn, *mapped_oc, *mapped_at; lc = ldap_back_getconn(li, conn, op); if (!lc || !ldap_back_dobind( lc, op ) ) { @@ -69,7 +69,15 @@ ldap_back_compare( return -1; } - ldap_compare_s( lc->ld, mdn, ava->aa_desc->ad_cname->bv_val, ava->aa_value->bv_val ); + mapped_oc = ldap_back_map(&li->oc_map, ava->aa_desc->ad_cname->bv_val, 0); + if (mapped_oc == NULL) + return( -1 ); + + mapped_at = ldap_back_map(&li->at_map, ava->aa_value->bv_val, 0); + if (mapped_oc == NULL) + return( -1 ); + + ldap_compare_s( lc->ld, mdn, mapped_oc, mapped_at ); free( mdn ); diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index 5113ed617d..5fb1f3a6c1 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -141,7 +141,7 @@ ldap_back_db_config( return( 1 ); } - dn = ch_strdup( argv[1] ); + dn = ch_strdup( argv[1] ); charray_add( &li->suffix_massage, dn ); (void) dn_normalize( dn ); charray_add( &li->suffix_massage, dn ); @@ -154,6 +154,92 @@ ldap_back_db_config( free( dn ); free( massaged_dn ); + /* objectclass/attribute mapping */ + } else if ( strcasecmp( argv[0], "map" ) == 0 ) { + struct ldapmap *map; + struct ldapmapping *mapping; + char *src, *dst; + + if ( argc < 3 || argc > 4 ) { + fprintf( stderr, + "%s: line %d: syntax is \"map {objectclass | attribute} { | *} [ | *]\"\n", + fname, lineno ); + return( 1 ); + } + + if ( strcasecmp( argv[1], "objectclass" ) == 0 ) { + map = &li->oc_map; + } else if ( strcasecmp( argv[1], "attribute" ) == 0 ) { + map = &li->at_map; + } else { + fprintf( stderr, + "%s: line %d: syntax is \"map {objectclass | attribute} { | *} [ | *]\"\n", + fname, lineno ); + return( 1 ); + } + + if ( strcasecmp( argv[2], "*" ) != 0 ) { + src = argv[2]; + if ( argc < 4 ) + dst = ""; + else if ( strcasecmp( argv[3], "*" ) == 0 ) + dst = src; + else + dst = argv[3]; + } else { + if ( argc < 4 ) { + map->drop_missing = 1; + return 0; + } + if ( strcasecmp( argv[3], "*" ) == 0 ) { + map->drop_missing = 0; + return 0; + } + + src = argv[3]; + dst = src; + } + + if ( ( map == &li->at_map ) + && ( strcasecmp( src, "objectclass" ) == 0 + || strcasecmp( dst, "objectclass" ) == 0 ) ) + { + fprintf( stderr, + "%s: line %d: objectclass attribute cannot be mapped\n", + fname, lineno ); + } + + mapping = (struct ldapmapping *)ch_calloc( 2, sizeof(struct ldapmapping) ); + if ( mapping == NULL ) { + fprintf( stderr, + "%s: line %d: out of memory\n", + fname, lineno ); + return( 1 ); + } + mapping->src = ch_strdup(src); + mapping->dst = ch_strdup(dst); + if ( *dst != 0 ) { + mapping[1].src = mapping->dst; + mapping[1].dst = mapping->src; + } else { + mapping[1].src = mapping->src; + mapping[1].dst = mapping->dst; + } + + if ( avl_find( map->map, (caddr_t)mapping, mapping_cmp ) != NULL + || avl_find( map->remap, (caddr_t)&mapping[1], mapping_cmp ) != NULL) + { + fprintf( stderr, + "%s: line %d: duplicate mapping found (ignored)\n", + fname, lineno ); + return 0; + } + + avl_insert( &map->map, (caddr_t)mapping, + mapping_cmp, mapping_dup ); + avl_insert( &map->remap, (caddr_t)&mapping[1], + mapping_cmp, mapping_dup ); + /* anything else */ } else { fprintf( stderr, @@ -162,3 +248,160 @@ ldap_back_db_config( } return 0; } + +int +mapping_cmp ( const void *c1, const void *c2 ) +{ + struct ldapmapping *map1 = (struct ldapmapping *)c1; + struct ldapmapping *map2 = (struct ldapmapping *)c2; + + return ( strcasecmp(map1->src, map2->src) ); +} + +int +mapping_dup ( void *c1, void *c2 ) +{ + struct ldapmapping *map1 = (struct ldapmapping *)c1; + struct ldapmapping *map2 = (struct ldapmapping *)c2; + + return( ( strcasecmp(map1->src, map2->src) == 0 ) ? -1 : 0 ); +} + +char * +ldap_back_map ( struct ldapmap *map, char *s, int remap ) +{ + Avlnode *tree; + struct ldapmapping *mapping, fmapping; + + if (remap) + tree = map->remap; + else + tree = map->map; + + fmapping.src = s; + mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp ); + if (mapping != NULL) { + if ( *mapping->dst == 0 ) + return(NULL); + return(mapping->dst); + } + + if (map->drop_missing) + return(NULL); + + return(s); +} + +char * +ldap_back_map_filter ( struct ldapinfo *li, char *f, int remap ) +{ + char *nf, *m, *p, *q, *s, c; + int len, extra, plen, in_quote; + + if (f == NULL) + return(NULL); + + len = strlen(f); + extra = len; + len *= 2; + nf = ch_malloc( len + 1 ); + if (nf == NULL) + return(NULL); + + /* this loop assumes the filter ends with one + * of the delimiter chars -- probably ')'. + */ + + s = nf; + q = NULL; + in_quote = 0; + for (p = f; c = *p; p++) { + if (c == '"') { + in_quote = !in_quote; + if (q != NULL) { + plen = p - q; + memcpy(s, q, plen); + s += plen; + q = NULL; + } + *s++ = c; + } else if (in_quote) { + /* ignore everything in quotes -- + * what about attrs in DNs? + */ + *s++ = c; + } else if (c != '(' && c != ')' + && c != '=' && c != '>' && c != '<' + && c != '|' && c != '&') + { + if (q == NULL) + q = p; + } else { + if (q != NULL) { + *p = 0; + m = ldap_back_map(&li->at_map, q, remap); + if (m == NULL) + m = ldap_back_map(&li->oc_map, q, remap); + if (m == NULL) { + m = q; + } + extra += p - q; + plen = strlen(m); + extra -= plen; + if (extra < 0) { + while (extra < 0) { + extra += len; + len *= 2; + } + s -= (long)nf; + nf = ch_realloc(nf, len + 1); + if (nf == NULL) { + free(nf); + return(NULL); + } + s += (long)nf; + } + memcpy(s, m, plen); + s += plen; + *p = c; + q = NULL; + } + *s++ = c; + } + } + *s = 0; + return(nf); +} + +char ** +ldap_back_map_attrs ( struct ldapinfo *li, char **a, int remap ) +{ + int i, j, count; + char **na, *mapped; + + if (a == NULL) + return(NULL); + + for (count = 0; a[count] != NULL; count++) { + /* */ + } + + na = (char **)ch_calloc( count + 1, sizeof(char *) ); + if (na == NULL) + return(NULL); + + for (i = 0, j = 0; i < count; i++) { + mapped = ldap_back_map(&li->at_map, a[i], remap); + if (mapped != NULL) { + mapped = ch_strdup(mapped); + if (mapped == NULL) { + charray_free(na); + return(NULL); + } + na[j] = mapped; + j++; + } + } + return(na); +} + diff --git a/servers/slapd/back-ldap/group.c b/servers/slapd/back-ldap/group.c index 94ec953ba0..52d10b3164 100644 --- a/servers/slapd/back-ldap/group.c +++ b/servers/slapd/back-ldap/group.c @@ -43,8 +43,8 @@ ldap_back_group( LDAP *ld; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; - const char *group_oc_name = NULL; - const char *group_at_name = group_at->ad_cname->bv_val; + char *group_oc_name = NULL; + char *group_at_name = group_at->ad_cname->bv_val; if( group_oc->soc_names && group_oc->soc_names[0] ) { group_oc_name = group_oc->soc_names[0]; @@ -54,6 +54,7 @@ ldap_back_group( if (target != NULL && strcmp(target->e_ndn, gr_ndn) == 0) { /* we already have a copy of the entry */ + /* attribute and objectclass mapping has already been done */ e = target; if( is_entry_objectclass( e, group_oc ) ) { @@ -69,6 +70,13 @@ ldap_back_group( return(1); } else { + group_oc_name = ldap_back_map(&li->oc_map, group_oc_name, 0); + if (group_oc_name == NULL) + return(1); + group_at_name = ldap_back_map(&li->at_map, group_at_name, 0); + if (group_at_name == NULL) + return(1); + filter = ch_malloc(sizeof("(&(objectclass=)(=))") + strlen(group_oc_name) + strlen(group_at_name) diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index 9d49b424a0..96e1acbd79 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -103,10 +103,24 @@ ldap_back_db_init( ) { struct ldapinfo *li; + struct ldapmapping *mapping; li = (struct ldapinfo *) ch_calloc( 1, sizeof(struct ldapinfo) ); ldap_pvt_thread_mutex_init( &li->conn_mutex ); + mapping = (struct ldapmapping *)ch_calloc( 2, sizeof(struct ldapmapping) ); + if ( mapping != NULL ) { + mapping->src = ch_strdup("objectclass"); + mapping->dst = ch_strdup("objectclass"); + mapping[1].src = mapping->src; + mapping[1].dst = mapping->dst; + + avl_insert( &li->at_map.map, (caddr_t)mapping, + mapping_cmp, mapping_dup ); + avl_insert( &li->at_map.remap, (caddr_t)&mapping[1], + mapping_cmp, mapping_dup ); + } + be->be_private = li; return li == NULL; @@ -122,6 +136,14 @@ conn_free( free( lc ); } +static void +mapping_free ( struct ldapmapping *mapping ) +{ + ch_free( mapping->src ); + ch_free( mapping->dst ); + ch_free( mapping ); +} + int ldap_back_db_destroy( Backend *be @@ -153,6 +175,11 @@ ldap_back_db_destroy( if (li->conntree) { avl_free( li->conntree, (AVL_FREE) conn_free ); } + + avl_free( li->oc_map.remap, NULL ); + avl_free( li->oc_map.map, (AVL_FREE) mapping_free ); + avl_free( li->at_map.remap, NULL ); + avl_free( li->at_map.map, (AVL_FREE) mapping_free ); ldap_pvt_thread_mutex_unlock( &li->conn_mutex ); ldap_pvt_thread_mutex_destroy( &li->conn_mutex ); diff --git a/servers/slapd/back-ldap/modify.c b/servers/slapd/back-ldap/modify.c index 9b11c27b57..fb7bfc6699 100644 --- a/servers/slapd/back-ldap/modify.c +++ b/servers/slapd/back-ldap/modify.c @@ -61,8 +61,7 @@ ldap_back_modify( LDAPMod *mods; Modifications *ml; int i; - - char *mdn; + char *mdn, *mapped; lc = ldap_back_getconn(li, conn, op); if ( !lc || !ldap_back_dobind( lc, op ) ) { @@ -86,16 +85,17 @@ ldap_back_modify( return( -1 ); } - modv[i] = 0; - - for (i=0, ml=modlist; ml; i++, ml=ml->sml_next) { - modv[i] = &mods[i]; - mods[i].mod_op = ml->sml_op | LDAP_MOD_BVALUES; - mods[i].mod_type = ml->sml_desc->ad_cname->bv_val; - mods[i].mod_bvalues = ml->sml_bvalues; + for (i=0, ml=modlist; ml; ml=ml->sml_next) { + mapped = ldap_back_map(&li->at_map, ml->sml_desc->ad_cname->bv_val, 0); + if (mapped != NULL) { + modv[i] = &mods[i]; + mods[i].mod_op = ml->sml_op | LDAP_MOD_BVALUES; + mods[i].mod_type = mapped; + mods[i].mod_bvalues = ml->sml_bvalues; + i++; + } } - - + modv[i] = 0; ldap_modify_s( lc->ld, mdn, modv ); free( mdn ); diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 240a85736b..441ad98c8e 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -70,10 +70,9 @@ ldap_back_search( struct ldapconn *lc; struct timeval tv; LDAPMessage *res, *e; - int i, rc, msgid, sres = LDAP_SUCCESS; + int count, rc, msgid, sres = LDAP_SUCCESS; char *match = NULL, *err = NULL; - - char *mbase; + char *mbase, *mapped_filter, **mapped_attrs; lc = ldap_back_getconn(li, conn, op); if ( !lc ) { @@ -96,17 +95,41 @@ ldap_back_search( return -1; } - if ((msgid = ldap_search(lc->ld, mbase, scope, filterstr, attrs, + mapped_filter = ldap_back_map_filter(li, (char *)filterstr, 0); + if ( mapped_filter == NULL ) { + mapped_filter = (char *)filterstr; + } + + mapped_attrs = ldap_back_map_attrs(li, attrs, 0); + if ( mapped_attrs == NULL ) { + mapped_attrs = attrs; + } + + if ((msgid = ldap_search(lc->ld, mbase, scope, mapped_filter, mapped_attrs, attrsonly)) == -1) -fail: return( ldap_back_op_result(lc, op) ); + { +fail: + if (match) + free(match); + if (err) + free(err); + if (mapped_attrs != attrs) + charray_free(mapped_attrs); + if (mapped_filter != filterstr) + free(mapped_filter); + free(mbase); + return( ldap_back_op_result(lc, op) ); + } /* We pull apart the ber result, stuff it into a slapd entry, and * let send_search_entry stuff it back into ber format. Slow & ugly, * but this is necessary for version matching, and for ACL processing. */ - for (i=0, rc=0; rc != -1; - rc = ldap_result(lc->ld, LDAP_RES_ANY, 0, &tv, &res)) { + for ( count=0, rc=0; + rc != -1; + rc = ldap_result(lc->ld, LDAP_RES_ANY, 0, &tv, &res)) + { int ab; /* check for abandon */ @@ -116,15 +139,16 @@ fail: return( ldap_back_op_result(lc, op) ); if (ab) { ldap_abandon(lc->ld, msgid); - } else if (rc == 0) { + goto finish; + } + if (rc == 0) { tv.tv_sec = 0; tv.tv_usec = 100000; ldap_pvt_thread_yield(); - continue; } else if (rc == LDAP_RES_SEARCH_ENTRY) { e = ldap_first_entry(lc->ld,res); - ldap_send_entry(be, op, lc, e, attrs, attrsonly); - i++; + ldap_send_entry(be, op, lc, e, mapped_attrs, attrsonly); + count++; ldap_msgfree(res); } else { sres = ldap_result2error(lc->ld, res, 1); @@ -132,24 +156,26 @@ fail: return( ldap_back_op_result(lc, op) ); ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &err); ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match); rc = 0; - } - if (ab) - return (0); - else if (rc == 0) break; + } } if (rc == -1) goto fail; send_search_result( conn, op, sres, - match, err, NULL, NULL, i ); + match, err, NULL, NULL, count ); + +finish: if (match) free(match); if (err) free(err); - if (mbase) - free(mbase); + if (mapped_attrs != attrs) + charray_free(mapped_attrs); + if (mapped_filter != filterstr) + free(mapped_filter); + free(mbase); return( 0 ); } @@ -164,11 +190,12 @@ ldap_send_entry( ) { struct ldapinfo *li = (struct ldapinfo *) be->be_private; - char *a; + char *a, *mapped; Entry ent; BerElement *ber = NULL; Attribute *attr, **attrp; struct berval *dummy = NULL; + struct berval *bv; const char *text; ent.e_dn = ldap_back_dn_restore( li, ldap_get_dn(lc->ld, e), 0 ); @@ -183,21 +210,47 @@ ldap_send_entry( a != NULL; a = ldap_next_attribute(lc->ld, e, ber)) { + mapped = ldap_back_map(&li->at_map, a, 1); + if (mapped == NULL) + continue; attr = (Attribute *)ch_malloc( sizeof(Attribute) ); if (attr == NULL) continue; attr->a_next = 0; attr->a_desc = NULL; - slap_str2ad(a, &attr->a_desc, &text); + if (slap_str2ad(mapped, &attr->a_desc, &text) != LDAP_SUCCESS) { + ch_free(attr); + continue; + } attr->a_vals = ldap_get_values_len(lc->ld, e, a); - if (!attr->a_vals) + if (!attr->a_vals) { attr->a_vals = &dummy; + } else if ( strcasecmp( mapped, "objectclass" ) == 0 ) { + int i, last; + for ( last = 0; attr->a_vals[last]; last++ ) ; + for ( i = 0; bv = attr->a_vals[i]; i++ ) { + mapped = ldap_back_map(&li->oc_map, bv->bv_val, 1); + if (mapped == NULL) { + ber_bvfree(attr->a_vals[i]); + attr->a_vals[i] = NULL; + if (--last < 0) + break; + attr->a_vals[i] = attr->a_vals[last]; + attr->a_vals[last] = NULL; + i--; + } else if ( mapped != bv->bv_val ) { + ch_free(bv->bv_val); + bv->bv_val = ch_strdup( mapped ); + bv->bv_len = strlen( mapped ); + } + } + } *attrp = attr; attrp = &attr->a_next; } send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, NULL ); - for (;ent.e_attrs;) { - attr=ent.e_attrs; + while (ent.e_attrs) { + attr = ent.e_attrs; ent.e_attrs = attr->a_next; ad_free(attr->a_desc, 1); if (attr->a_vals != &dummy) -- 2.39.5