]> git.sur5r.net Git - openldap/commitdiff
Add filter remapping
authorHoward Chu <hyc@openldap.org>
Sat, 25 Jul 2015 21:23:46 +0000 (22:23 +0100)
committerHoward Chu <hyc@openldap.org>
Sat, 25 Jul 2015 21:23:46 +0000 (22:23 +0100)
contrib/slapd-modules/adremap/adremap.c
contrib/slapd-modules/adremap/slapo-adremap.5

index 38c95aafcef560aaaf5f1a5155789b67c0231a23..df1169459776b79d9e4224da7ab447f5b1b79f4e 100644 (file)
@@ -39,6 +39,10 @@ typedef struct adremap_dnv {
        AttributeDescription *ad_dnattr;        /* DN-valued attr to deref */
        AttributeDescription *ad_deref;         /* target attr's value to retrieve */
        AttributeDescription *ad_newattr;       /* New attr to collect new values */
        AttributeDescription *ad_dnattr;        /* DN-valued attr to deref */
        AttributeDescription *ad_deref;         /* target attr's value to retrieve */
        AttributeDescription *ad_newattr;       /* New attr to collect new values */
+       ObjectClass *ad_group;          /* group objectclass on target */
+       ObjectClass *ad_mapgrp;         /* group objectclass to map */
+       ObjectClass *ad_refgrp;         /* objectclass of target DN */
+       struct berval ad_refbase;       /* base DN of target entries */
 } adremap_dnv;
 /* example: member uid memberUid */
 
 } adremap_dnv;
 /* example: member uid memberUid */
 
@@ -69,11 +73,12 @@ static ConfigTable adremapcfg[] = {
          "NAME 'olcADremapDowncase' "
          "DESC 'List of attributes to casefold to lower case' "
          "SYNTAX OMsDirectoryString )", NULL, NULL },
          "NAME 'olcADremapDowncase' "
          "DESC 'List of attributes to casefold to lower case' "
          "SYNTAX OMsDirectoryString )", NULL, NULL },
-       { "adremap-dnmap", "dnattr simpleattr newattr", 4, 4, 0,
+       { "adremap-dnmap", "dnattr targetattr newattr remoteOC localOC targetOC baseDN", 8, 8, 0,
          ARG_MAGIC|ADREMAP_DNV, adremap_cf_dnv,
          "( OLcfgCtAt:6.2 "
          "NAME 'olcADremapDNmap' "
          ARG_MAGIC|ADREMAP_DNV, adremap_cf_dnv,
          "( OLcfgCtAt:6.2 "
          "NAME 'olcADremapDNmap' "
-         "DESC 'DN attr to map, attr from target to use, attr to generate' "
+         "DESC 'DN attr to map, attr from target to use, attr to generate, objectclass of remote"
+          " group, objectclass mapped group, objectclass of target entry, base DN of target entry' "
          "SYNTAX OMsDirectoryString )", NULL, NULL },
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
          "SYNTAX OMsDirectoryString )", NULL, NULL },
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
@@ -151,12 +156,25 @@ adremap_cf_dnv(ConfigArgs *c)
                        char *ptr;
                        struct berval bv;
                        bv.bv_len = ad->ad_dnattr->ad_cname.bv_len + ad->ad_deref->ad_cname.bv_len + ad->ad_newattr->ad_cname.bv_len + 2;
                        char *ptr;
                        struct berval bv;
                        bv.bv_len = ad->ad_dnattr->ad_cname.bv_len + ad->ad_deref->ad_cname.bv_len + ad->ad_newattr->ad_cname.bv_len + 2;
+                       bv.bv_len += ad->ad_group->soc_cname.bv_len + ad->ad_mapgrp->soc_cname.bv_len + ad->ad_refgrp->soc_cname.bv_len + 3;
+                       bv.bv_len += ad->ad_refbase.bv_len + 3;
                        bv.bv_val = ch_malloc(bv.bv_len + 1);
                        ptr = lutil_strcopy(bv.bv_val, ad->ad_dnattr->ad_cname.bv_val);
                        *ptr++ = ' ';
                        ptr = lutil_strcopy(ptr, ad->ad_deref->ad_cname.bv_val);
                        *ptr++ = ' ';
                        bv.bv_val = ch_malloc(bv.bv_len + 1);
                        ptr = lutil_strcopy(bv.bv_val, ad->ad_dnattr->ad_cname.bv_val);
                        *ptr++ = ' ';
                        ptr = lutil_strcopy(ptr, ad->ad_deref->ad_cname.bv_val);
                        *ptr++ = ' ';
-                       strcpy(ptr, ad->ad_newattr->ad_cname.bv_val);
+                       ptr = lutil_strcopy(ptr, ad->ad_newattr->ad_cname.bv_val);
+                       *ptr++ = ' ';
+                       ptr = lutil_strcopy(ptr, ad->ad_group->soc_cname.bv_val);
+                       *ptr++ = ' ';
+                       ptr = lutil_strcopy(ptr, ad->ad_mapgrp->soc_cname.bv_val);
+                       *ptr++ = ' ';
+                       ptr = lutil_strcopy(ptr, ad->ad_refgrp->soc_cname.bv_val);
+                       *ptr++ = ' ';
+                       *ptr++ = '"';
+                       ptr = lutil_strcopy(ptr, ad->ad_refbase.bv_val);
+                       *ptr++ = '"';
+                       *ptr = '\0';
                        ber_bvarray_add(&c->rvalue_vals, &bv);
                }
                if (ai->ai_dnv) rc = 0;
                        ber_bvarray_add(&c->rvalue_vals, &bv);
                }
                if (ai->ai_dnv) rc = 0;
@@ -179,6 +197,7 @@ adremap_cf_dnv(ConfigArgs *c)
        default: {
                const char *text;
                adremap_dnv av = {0};
        default: {
                const char *text;
                adremap_dnv av = {0};
+               struct berval dn;
                rc = slap_str2ad(c->argv[1], &av.ad_dnattr, &text);
                if (rc) break;
                if (av.ad_dnattr->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName) {
                rc = slap_str2ad(c->argv[1], &av.ad_dnattr, &text);
                if (rc) break;
                if (av.ad_dnattr->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName) {
@@ -192,6 +211,24 @@ adremap_cf_dnv(ConfigArgs *c)
                if (rc) break;
                rc = slap_str2ad(c->argv[3], &av.ad_newattr, &text);
                if (rc) break;
                if (rc) break;
                rc = slap_str2ad(c->argv[3], &av.ad_newattr, &text);
                if (rc) break;
+               av.ad_group = oc_find(c->argv[4]);
+               if (!av.ad_group) {
+                       rc = 1;
+                       break;
+               }
+               av.ad_mapgrp = oc_find(c->argv[5]);
+               if (!av.ad_mapgrp) {
+                       rc = 1;
+                       break;
+               }
+               av.ad_refgrp = oc_find(c->argv[6]);
+               if (!av.ad_refgrp) {
+                       rc = 1;
+                       break;
+               }
+               ber_str2bv(c->argv[7], 0, 0, &dn);
+               rc = dnNormalize(0, NULL, NULL, &dn, &av.ad_refbase, NULL);
+               if (rc) break;
 
                for (a2 = &ai->ai_dnv; *a2; a2 = &(*a2)->ad_next);
                ad = ch_malloc(sizeof(adremap_dnv));
 
                for (a2 = &ai->ai_dnv; *a2; a2 = &(*a2)->ad_next);
                ad = ch_malloc(sizeof(adremap_dnv));
@@ -199,6 +236,10 @@ adremap_cf_dnv(ConfigArgs *c)
                ad->ad_dnattr = av.ad_dnattr;
                ad->ad_deref = av.ad_deref;
                ad->ad_newattr = av.ad_newattr;
                ad->ad_dnattr = av.ad_dnattr;
                ad->ad_deref = av.ad_deref;
                ad->ad_newattr = av.ad_newattr;
+               ad->ad_group = av.ad_group;
+               ad->ad_mapgrp = av.ad_mapgrp;
+               ad->ad_refgrp = av.ad_refgrp;
+               ad->ad_refbase = av.ad_refbase;
                *a2 = ad;
                break;
                }
                *a2 = ad;
                break;
                }
@@ -268,6 +309,123 @@ adremap_search_resp(
        return SLAP_CB_CONTINUE;
 }
 
        return SLAP_CB_CONTINUE;
 }
 
+static int adremap_refsearch(
+       Operation *op,
+       SlapReply *rs
+)
+{
+       if (rs->sr_type == REP_SEARCH) {
+               slap_callback *sc = op->o_callback;
+               struct berval *dn = sc->sc_private;
+               ber_dupbv_x(dn, &rs->sr_entry->e_nname, op->o_tmpmemctx);
+       }
+       return LDAP_SUCCESS;
+}
+
+static int adremap_filter(
+       Operation *op,
+       adremap_info *ai
+)
+{
+       slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+       Filter *f = op->ors_filter;
+       adremap_dnv *ad;
+
+       /* Do we need to munge the filter? First see if it's of
+        * the form (&(objectClass=<mapgrp>)...)
+        */
+       if (f->f_choice == LDAP_FILTER_AND && f->f_and &&
+               f->f_and->f_choice == LDAP_FILTER_EQUALITY &&
+               f->f_and->f_av_desc == slap_schema.si_ad_objectClass) {
+               struct berval bv = f->f_and->f_av_value;
+               for (ad = ai->ai_dnv; ad; ad = ad->ad_next) {
+                       if (!ber_bvstrcasecmp( &bv, &ad->ad_mapgrp->soc_cname )) {
+                       /* Now check to see if next element is (<newattr>=foo) */
+                               Filter *fn = f->f_and->f_next;
+                               if (fn && fn->f_choice == LDAP_FILTER_EQUALITY &&
+                                       fn->f_av_desc == ad->ad_newattr) {
+                                       Filter fr[3], *fnew;
+                                       AttributeAssertion aa[2];
+                                       Operation op2;
+                                       slap_callback cb = {0};
+                                       SlapReply rs = {REP_RESULT};
+                                       struct berval dn = BER_BVNULL;
+
+                                       /* It's a match, setup a search with filter
+                                        * (&(objectclass=<refgrp>)(<deref>=foo))
+                                        */
+                                       fr[0].f_choice = LDAP_FILTER_AND;
+                                       fr[0].f_and = &fr[1];
+
+                                       fr[1].f_choice = LDAP_FILTER_EQUALITY;
+                                       fr[1].f_ava = &aa[0];
+                                       fr[1].f_av_desc = slap_schema.si_ad_objectClass;
+                                       fr[1].f_av_value = ad->ad_refgrp->soc_cname;
+                                       fr[1].f_next = &fr[2];
+
+                                       fr[2].f_choice = LDAP_FILTER_EQUALITY;
+                                       fr[2].f_ava = &aa[1];
+                                       fr[2].f_av_desc = ad->ad_deref;
+                                       fr[2].f_av_value = fn->f_av_value;
+                                       fr[2].f_next = NULL;
+
+                                       /* Search with this filter to retrieve target DN */
+                                       op2 = *op;
+                                       op2.o_callback = &cb;
+                                       cb.sc_response = adremap_refsearch;
+                                       cb.sc_private = &dn;
+                                       op2.o_req_dn = ad->ad_refbase;
+                                       op2.o_req_ndn = ad->ad_refbase;
+                                       op2.ors_filter = fr;
+                                       filter2bv_x(op, fr, &op2.ors_filterstr);
+                                       op2.ors_deref = LDAP_DEREF_NEVER;
+                                       op2.ors_slimit = 1;
+                                       op2.ors_tlimit = SLAP_NO_LIMIT;
+                                       op2.ors_attrs = slap_anlist_no_attrs;
+                                       op2.ors_attrsonly = 1;
+                                       op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+                                       op2.o_bd->be_search(&op2, &rs);
+                                       op2.o_bd->bd_info = (BackendInfo *)on;
+                                       op->o_tmpfree(op2.ors_filterstr.bv_val, op->o_tmpmemctx);
+
+                                       if (!dn.bv_len) /* no match was found */
+                                               return 0;
+
+                                       /* Build a new filter of form
+                                        * (&(objectclass=<group>)(<dnattr>=foo-DN)...)
+                                        */
+                                       f = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
+                                       f->f_choice = LDAP_FILTER_AND;
+                                       fnew = f;
+
+                                       f->f_and = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
+                                       f = f->f_and;
+                                       f->f_choice = LDAP_FILTER_EQUALITY;
+                                       f->f_ava = op->o_tmpalloc(sizeof(AttributeAssertion), op->o_tmpmemctx);
+                                       f->f_av_desc = slap_schema.si_ad_objectClass;
+                                       ber_dupbv_x(&f->f_av_value, &ad->ad_group->soc_cname, op->o_tmpmemctx);
+
+                                       f->f_next = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
+                                       f = f->f_next;
+                                       f->f_choice = LDAP_FILTER_EQUALITY;
+                                       f->f_ava = op->o_tmpalloc(sizeof(AttributeAssertion), op->o_tmpmemctx);
+                                       f->f_av_desc = ad->ad_dnattr;
+                                       f->f_av_value = dn;
+                                       f->f_next = fn->f_next;
+
+                                       fn->f_next = NULL;
+                                       filter_free_x(op, op->ors_filter, 1);
+                                       op->o_tmpfree(op->ors_filterstr.bv_val, op->o_tmpmemctx);
+                                       op->ors_filter = fnew;
+                                       filter2bv_x(op, op->ors_filter, &op->ors_filterstr);
+                                       return 1;
+                               }
+                       }
+               }
+       }
+       return 0;       /* didn't match anything */
+}
+
 static int
 adremap_search(
        Operation *op,
 static int
 adremap_search(
        Operation *op,
@@ -275,13 +433,20 @@ adremap_search(
 )
 {
        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
 )
 {
        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+       adremap_info *ai = (adremap_info *) on->on_bi.bi_private;
        slap_callback *cb;
 
        slap_callback *cb;
 
+       if (ai->ai_dnv) {
+               /* check for filter match, fallthru if none */
+               if (!adremap_filter(op, ai))
+                       return SLAP_CB_CONTINUE;
+       }
        cb = op->o_tmpcalloc(1, sizeof(slap_callback), op->o_tmpmemctx);
        cb->sc_response = adremap_search_resp;
        cb->sc_private = on;
        cb->sc_next = op->o_callback;
        op->o_callback = cb;
        cb = op->o_tmpcalloc(1, sizeof(slap_callback), op->o_tmpmemctx);
        cb->sc_response = adremap_search_resp;
        cb->sc_private = on;
        cb->sc_next = op->o_callback;
        op->o_callback = cb;
+
        return SLAP_CB_CONTINUE;
 }
 
        return SLAP_CB_CONTINUE;
 }
 
index bf382241d8b10ddac0a65450c0bd622ee97580c3..8b1fa458651801311d716f451371e61891cb220a 100644 (file)
@@ -45,12 +45,19 @@ directive. They can each be specified multiple times:
 Specify an attributeType whose values will all be mapped to lowercase
 when returned in search responses.
 .TP
 Specify an attributeType whose values will all be mapped to lowercase
 when returned in search responses.
 .TP
-.B adremap-dnmap <dnattr> <derefattr> <newattr>
+.B adremap-dnmap <dnattr> <targetattr> <newattr> <remoteOC> <localOC> <targetOC> <baseDN>
 Specify a DN-valued attributeType whose values will be dereferenced. The
 Specify a DN-valued attributeType whose values will be dereferenced. The
-.B <derefattr>
+.B <targetattr>
 of the target entry will be retrieved and its value will be added to the
 .B <newattr>
 of the target entry will be retrieved and its value will be added to the
 .B <newattr>
-in the entry.
+in the entry. In addition, searches using a filter of the form
+.B (&(objectClass=<localOC>)(<newattr>=xxx))
+will be rewritten into the form
+.BR (&(objectClass=<remoteOC>)(<dnattr>=xxx-DN)) .
+This rewrite will accomplished by performing an additional internal search,
+with subtree scope, using the specified baseDN and a filter of the form
+.BR (&(objectClass=<targetOC>)(<targetattr>=xxx)) .
+
 
 .SH EXAMPLE
 This example configures the
 
 .SH EXAMPLE
 This example configures the
@@ -59,7 +66,10 @@ overlay to map all
 .B uid
 attributes to lowercase, and create
 .B memberUid
 .B uid
 attributes to lowercase, and create
 .B memberUid
-values for group entries.
+values for group entries. The mapping will turn requests for posixGroup
+entries into requests for groupOfNames entries, and the internal search
+will use inetOrgPerson entries under the ou=People,dc=example,dc=com subtree.
+
 Add the following to
 .BR slapd.conf (5):
 
 Add the following to
 .BR slapd.conf (5):
 
@@ -70,7 +80,7 @@ Add the following to
 
     overlay adremap
     adremap-downcase uid
 
     overlay adremap
     adremap-downcase uid
-    adremap-dnmap member uid memberUid
+    adremap-dnmap member uid memberUid groupOfNames posixGroup inetOrgPerson ou=people,dc=example,dc=com
 .fi
 .LP
 .B slapd
 .fi
 .LP
 .B slapd