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 ) ) {
/* 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)
)
{
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;
*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);
}
} 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;
int bound;
};
+struct ldapmap {
+ int drop_missing;
+
+ Avlnode *map;
+ Avlnode *remap;
+};
+
+struct ldapmapping {
+ char *src;
+ char *dst;
+};
+
struct ldapinfo {
char *url;
#if 0 /* unused! */
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,
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
err = avl_insert( &li->conntree, (caddr_t)lc,
conn_cmp, conn_dup );
-#if 1
+#if 0
myprint( li->conntree );
#endif
{
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 ) ) {
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 );
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 );
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} {<source> | *} [<dest> | *]\"\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} {<source> | *} [<dest> | *]\"\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,
}
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);
+}
+
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];
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 ) ) {
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)
)
{
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;
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
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 );
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 ) ) {
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 );
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 ) {
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 */
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);
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 );
}
)
{
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 );
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)