summaryrefslogtreecommitdiffstats
path: root/servers/slapd/overlays/memberof.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 05:34:56 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 05:34:56 +0000
commit3fa3e6ac17cbab8003ce3b3ae87928de5f5eaaf4 (patch)
tree1fa47166862724850b871e1900513bf04d3c1cc2 /servers/slapd/overlays/memberof.c
parentAdding upstream version 2.6.7+dfsg. (diff)
downloadopenldap-upstream.tar.xz
openldap-upstream.zip
Adding upstream version 2.6.8+dfsg.upstream/2.6.8+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'servers/slapd/overlays/memberof.c')
-rw-r--r--servers/slapd/overlays/memberof.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/servers/slapd/overlays/memberof.c b/servers/slapd/overlays/memberof.c
index 5affbbf..351aa56 100644
--- a/servers/slapd/overlays/memberof.c
+++ b/servers/slapd/overlays/memberof.c
@@ -159,6 +159,7 @@ typedef struct memberof_t {
#define MEMBEROF_FDANGLING_MASK (MEMBEROF_FDANGLING_DROP|MEMBEROF_FDANGLING_ERROR)
#define MEMBEROF_FREFINT 0x04U
#define MEMBEROF_FREVERSE 0x08U
+#define MEMBEROF_FADDCHECK 0x10U
ber_int_t mo_dangling_err;
@@ -174,6 +175,8 @@ typedef struct memberof_t {
MEMBEROF_CHK((mo),MEMBEROF_FREFINT)
#define MEMBEROF_REVERSE(mo) \
MEMBEROF_CHK((mo),MEMBEROF_FREVERSE)
+#define MEMBEROF_ADDCHECK(mo) \
+ MEMBEROF_CHK((mo),MEMBEROF_FADDCHECK)
} memberof_t;
typedef enum memberof_is_t {
@@ -385,6 +388,10 @@ memberof_value_modify(
op2.orm_no_opattrs = 1;
op2.o_dont_replicate = 1;
+ /* main op has already completed if we got here, so even
+ * if its abandon flag was set we must complete as well. */
+ op2.o_abandon = 0;
+
if ( !BER_BVISNULL( &mo->mo_ndn ) ) {
ml = &mod[ mcnt ];
ml->sml_numvals = 1;
@@ -521,6 +528,87 @@ static int memberof_res_delete( Operation *op, SlapReply *rs );
static int memberof_res_modify( Operation *op, SlapReply *rs );
static int memberof_res_modrdn( Operation *op, SlapReply *rs );
+typedef struct mo_addcheck_t {
+ memberof_t *ma_mo;
+ Entry *ma_e;
+ Attribute *ma_a;
+} mo_addcheck_t;
+
+static int memberof_res_addcheck( Operation *op, SlapReply *rs )
+{
+ mo_addcheck_t *ma = op->o_callback->sc_private;
+ if ( rs->sr_type == REP_SEARCH ) {
+ if ( !ma->ma_a ) {
+ attr_merge_one( ma->ma_e, ma->ma_mo->mo_ad_memberof,
+ &rs->sr_entry->e_name, &rs->sr_entry->e_nname );
+ ma->ma_a = attr_find( ma->ma_e->e_attrs, ma->ma_mo->mo_ad_memberof );
+ } else {
+ if ( attr_valfind( ma->ma_a, SLAP_MR_EQUALITY | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
+ SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, &rs->sr_entry->e_nname, NULL, NULL )) {
+ attr_valadd( ma->ma_a, &rs->sr_entry->e_name, &rs->sr_entry->e_nname, 1 );
+ }
+ }
+ }
+ return 0;
+}
+
+/* Check if an entry being added is already a member of existing groups;
+ * add those groups to the entry's memberof if any.
+ */
+static void
+memberof_addcheck( Operation *op )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ memberof_t *mo = (memberof_t *)on->on_bi.bi_private;
+ Operation o = *op;
+ Filter mf;
+ AttributeAssertion mava;
+ slap_callback sc = {0};
+ mo_addcheck_t ma;
+ SlapReply rs = {REP_SEARCH};
+
+ o.o_dn = op->o_bd->be_rootdn;
+ o.o_ndn = op->o_bd->be_rootndn;
+ o.o_bd->bd_info = (BackendInfo *)on->on_info;
+ o.o_tag = LDAP_REQ_SEARCH;
+ o.o_req_dn = op->o_bd->be_suffix[0];
+ o.o_req_ndn = op->o_bd->be_nsuffix[0];
+ o.o_do_not_cache = 1;
+ o.ors_scope = LDAP_SCOPE_SUBTREE;
+ o.ors_slimit = SLAP_NO_LIMIT;
+ o.ors_tlimit = SLAP_NO_LIMIT;
+ o.ors_limit = NULL;
+ o.ors_attrsonly = 1;
+ o.ors_attrs = slap_anlist_no_attrs;
+ mf.f_choice = LDAP_FILTER_EQUALITY;
+ mf.f_ava = &mava;
+ mf.f_next = NULL;
+ mf.f_av_desc = mo->mo_ad_member;
+ mf.f_av_value = op->o_req_ndn;
+ o.ors_filter = &mf;
+ o.ors_filterstr.bv_val = op->o_tmpalloc( mo->mo_ad_member->ad_cname.bv_len + 2
+ + op->o_req_ndn.bv_len + 2, op->o_tmpmemctx );
+ {
+ char *ptr = o.ors_filterstr.bv_val;
+ *ptr++ = '(';
+ ptr = lutil_strcopy( ptr, mo->mo_ad_member->ad_cname.bv_val );
+ *ptr++ = '=';
+ ptr = lutil_strcopy( ptr, op->o_req_ndn.bv_val );
+ *ptr++ = ')';
+ *ptr = '\0';
+ }
+ sc.sc_private = &ma;
+ sc.sc_response = memberof_res_addcheck;
+ ma.ma_mo = mo;
+ ma.ma_e = op->ora_e;
+ ma.ma_a = attr_find( op->ora_e->e_attrs, mo->mo_ad_memberof );
+ o.o_callback = &sc;
+
+ o.o_bd->be_search( &o, &rs );
+ o.o_bd->bd_info = (BackendInfo *)on;
+ op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
+}
+
static int
memberof_op_add( Operation *op, SlapReply *rs )
{
@@ -549,6 +637,10 @@ memberof_op_add( Operation *op, SlapReply *rs )
return SLAP_CB_CONTINUE;
}
+ if ( MEMBEROF_ADDCHECK( mo )) {
+ memberof_addcheck( op );
+ }
+
if ( MEMBEROF_REVERSE( mo ) ) {
for ( ap = &op->ora_e->e_attrs; *ap; ap = &(*ap)->a_next ) {
Attribute *a = *ap;
@@ -1649,6 +1741,7 @@ enum {
#endif
MO_DANGLING_ERROR,
+ MO_ADDCHECK,
MO_LAST
};
@@ -1730,6 +1823,14 @@ static ConfigTable mo_cfg[] = {
"SYNTAX OMsDirectoryString SINGLE-VALUE )",
NULL, NULL },
+ { "memberof-addcheck", "true|FALSE",
+ 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|MO_ADDCHECK, mo_cf_gen,
+ "( OLcfgOvAt:18.8 NAME 'olcMemberOfAddCheck' "
+ "DESC 'Check for memberships on added entries' "
+ "EQUALITY booleanMatch "
+ "SYNTAX OMsBoolean SINGLE-VALUE )",
+ NULL, NULL },
+
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};
@@ -1749,6 +1850,7 @@ static ConfigOCs mo_ocs[] = {
#if 0
"$ olcMemberOfReverse "
#endif
+ "$ olcMemberOfAddCheck "
") "
")",
Cft_Overlay, mo_cfg, NULL, NULL },
@@ -1887,6 +1989,10 @@ mo_cf_gen( ConfigArgs *c )
c->value_ad = mo->mo_ad_memberof;
break;
+ case MO_ADDCHECK:
+ c->value_int = MEMBEROF_ADDCHECK( mo );
+ break;
+
default:
assert( 0 );
return 1;
@@ -1937,6 +2043,10 @@ mo_cf_gen( ConfigArgs *c )
memberof_make_member_filter( mo );
break;
+ case MO_ADDCHECK:
+ mo->mo_flags &= ~MEMBEROF_FADDCHECK;
+ break;
+
default:
assert( 0 );
return 1;
@@ -2046,6 +2156,15 @@ mo_cf_gen( ConfigArgs *c )
memberof_make_member_filter( mo );
} break;
+ case MO_ADDCHECK:
+ if ( c->value_int ) {
+ mo->mo_flags |= MEMBEROF_FADDCHECK;
+
+ } else {
+ mo->mo_flags &= ~MEMBEROF_FADDCHECK;
+ }
+ break;
+
default:
assert( 0 );
return 1;