attribute & objectclass mapping rules

This commit is contained in:
Mark Valence 2001-02-19 19:14:12 +00:00
parent f9a76ce1ab
commit 6e6118c6cc
10 changed files with 442 additions and 57 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 );

View File

@ -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} {<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,
@ -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);
}

View File

@ -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)

View File

@ -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 );

View File

@ -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 );

View File

@ -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)