From 3fa3e6ac17cbab8003ce3b3ae87928de5f5eaaf4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 3 Jun 2024 07:34:56 +0200 Subject: Adding upstream version 2.6.8+dfsg. Signed-off-by: Daniel Baumann --- servers/slapd/overlays/Makefile.in | 6 +- servers/slapd/overlays/accesslog.c | 10 +- servers/slapd/overlays/auditlog.c | 2 +- servers/slapd/overlays/autoca.c | 2 +- servers/slapd/overlays/collect.c | 2 +- servers/slapd/overlays/constraint.c | 3 +- servers/slapd/overlays/dds.c | 2 +- servers/slapd/overlays/deref.c | 2 +- servers/slapd/overlays/dyngroup.c | 4 +- servers/slapd/overlays/dynlist.c | 5 +- servers/slapd/overlays/homedir.c | 2 +- servers/slapd/overlays/memberof.c | 119 +++++ servers/slapd/overlays/nestgroup.c | 909 +++++++++++++++++++++++++++++++++++ servers/slapd/overlays/otp.c | 2 +- servers/slapd/overlays/overlays.c | 2 +- servers/slapd/overlays/pcache.c | 2 +- servers/slapd/overlays/ppolicy.c | 2 +- servers/slapd/overlays/refint.c | 3 +- servers/slapd/overlays/remoteauth.c | 2 +- servers/slapd/overlays/retcode.c | 2 +- servers/slapd/overlays/rwm.c | 2 +- servers/slapd/overlays/rwm.h | 2 +- servers/slapd/overlays/rwmconf.c | 2 +- servers/slapd/overlays/rwmdn.c | 2 +- servers/slapd/overlays/rwmmap.c | 2 +- servers/slapd/overlays/seqmod.c | 2 +- servers/slapd/overlays/sssvlv.c | 2 +- servers/slapd/overlays/syncprov.c | 10 +- servers/slapd/overlays/translucent.c | 2 +- servers/slapd/overlays/unique.c | 2 +- servers/slapd/overlays/valsort.c | 4 +- 31 files changed, 1079 insertions(+), 36 deletions(-) create mode 100644 servers/slapd/overlays/nestgroup.c (limited to 'servers/slapd/overlays') diff --git a/servers/slapd/overlays/Makefile.in b/servers/slapd/overlays/Makefile.in index e6711fe..6d886f8 100644 --- a/servers/slapd/overlays/Makefile.in +++ b/servers/slapd/overlays/Makefile.in @@ -2,7 +2,7 @@ # $OpenLDAP$ ## This work is part of OpenLDAP Software . ## -## Copyright 2003-2022 The OpenLDAP Foundation. +## Copyright 2003-2024 The OpenLDAP Foundation. ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without @@ -24,6 +24,7 @@ SRCS = overlays.c \ dynlist.c \ homedir.c \ memberof.c \ + nestgroup.c \ otp.c \ pcache.c \ collect.c \ @@ -96,6 +97,9 @@ homedir.la : homedir.lo memberof.la : memberof.lo $(LTLINK_MOD) -module -o $@ memberof.lo version.lo $(LINK_LIBS) +nestgroup.la : nestgroup.lo + $(LTLINK_MOD) -module -o $@ nestgroup.lo version.lo $(LINK_LIBS) + otp.la : otp.lo $(LTLINK_MOD) -module -o $@ otp.lo version.lo $(LINK_LIBS) diff --git a/servers/slapd/overlays/accesslog.c b/servers/slapd/overlays/accesslog.c index 182be57..19bbdbf 100644 --- a/servers/slapd/overlays/accesslog.c +++ b/servers/slapd/overlays/accesslog.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005-2022 The OpenLDAP Foundation. + * Copyright 2005-2024 The OpenLDAP Foundation. * Portions copyright 2004-2005 Symas Corporation. * All rights reserved. * @@ -1567,7 +1567,7 @@ accesslog_response(Operation *op, SlapReply *rs) lo = logops+logop+EN_OFFSET; /* can't do anything if logDB isn't open */ - if ( !SLAP_DBOPEN( li->li_db ) ) { + if ( !li->li_db || !SLAP_DBOPEN( li->li_db ) ) { goto skip; } @@ -2497,7 +2497,13 @@ accesslog_db_root( attr_merge_one( e, slap_schema.si_ad_entryCSN, &a->a_vals[0], &a->a_nvals[0] ); attr_merge( e, a->a_desc, a->a_vals, a->a_nvals ); + + /* Populate minCSN */ attr_merge( e, ad_minCSN, a->a_vals, a->a_nvals ); + ber_bvarray_dup_x( &li->li_mincsn, a->a_vals, NULL ); + li->li_numcsns = a->a_numvals; + li->li_sids = slap_parse_csn_sids( li->li_mincsn, li->li_numcsns, NULL ); + slap_sort_csn_sids( li->li_mincsn, li->li_sids, li->li_numcsns, NULL ); } be_entry_release_rw( op, e_ctx, 0 ); } diff --git a/servers/slapd/overlays/auditlog.c b/servers/slapd/overlays/auditlog.c index 9292d4a..69482e7 100644 --- a/servers/slapd/overlays/auditlog.c +++ b/servers/slapd/overlays/auditlog.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005-2022 The OpenLDAP Foundation. + * Copyright 2005-2024 The OpenLDAP Foundation. * Portions copyright 2004-2005 Symas Corporation. * All rights reserved. * diff --git a/servers/slapd/overlays/autoca.c b/servers/slapd/overlays/autoca.c index 5fcd204..692d9d5 100644 --- a/servers/slapd/overlays/autoca.c +++ b/servers/slapd/overlays/autoca.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2009-2022 The OpenLDAP Foundation. + * Copyright 2009-2024 The OpenLDAP Foundation. * Copyright 2009-2018 by Howard Chu. * All rights reserved. * diff --git a/servers/slapd/overlays/collect.c b/servers/slapd/overlays/collect.c index bbc6219..b133cd2 100644 --- a/servers/slapd/overlays/collect.c +++ b/servers/slapd/overlays/collect.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2022 The OpenLDAP Foundation. + * Copyright 2003-2024 The OpenLDAP Foundation. * Portions Copyright 2003 Howard Chu. * All rights reserved. * diff --git a/servers/slapd/overlays/constraint.c b/servers/slapd/overlays/constraint.c index f939b37..9622c29 100644 --- a/servers/slapd/overlays/constraint.c +++ b/servers/slapd/overlays/constraint.c @@ -369,6 +369,7 @@ constraint_cf_gen( ConfigArgs *c ) ap.attrs[i] = NULL; if ( slap_str2ad( ap.lud->lud_attrs[i], &ap.attrs[i], &text ) ) { ch_free( ap.attrs ); + ap.attrs = NULL; snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s\n", c->argv[0], ap.lud->lud_attrs[i], text ); rc = ARG_BAD_CONF; @@ -557,7 +558,7 @@ done:; a2->restrict_filter = ap.restrict_filter; a2->restrict_val = ap.restrict_val; - for ( app = &on->on_bi.bi_private; *app; app = &(*app)->ap_next ) + for ( app = (constraint **)&on->on_bi.bi_private; *app; app = &(*app)->ap_next ) /* Get to the end */ ; a2->ap_next = *app; diff --git a/servers/slapd/overlays/dds.c b/servers/slapd/overlays/dds.c index c19f042..422183a 100644 --- a/servers/slapd/overlays/dds.c +++ b/servers/slapd/overlays/dds.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005-2022 The OpenLDAP Foundation. + * Copyright 2005-2024 The OpenLDAP Foundation. * Portions Copyright 2005-2006 SysNet s.n.c. * All rights reserved. * diff --git a/servers/slapd/overlays/deref.c b/servers/slapd/overlays/deref.c index 93b7f69..aed4f68 100644 --- a/servers/slapd/overlays/deref.c +++ b/servers/slapd/overlays/deref.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2022 The OpenLDAP Foundation. + * Copyright 1998-2024 The OpenLDAP Foundation. * Portions Copyright 2008 Pierangelo Masarati. * All rights reserved. * diff --git a/servers/slapd/overlays/dyngroup.c b/servers/slapd/overlays/dyngroup.c index 5d890d6..2c9ba7e 100644 --- a/servers/slapd/overlays/dyngroup.c +++ b/servers/slapd/overlays/dyngroup.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2022 The OpenLDAP Foundation. + * Copyright 2003-2024 The OpenLDAP Foundation. * Copyright 2003 by Howard Chu. * All rights reserved. * @@ -111,7 +111,7 @@ static int dgroup_cf( ConfigArgs *c ) */ a2 = ch_malloc( sizeof(adpair) ); - for ( app = &on->on_bi.bi_private; *app; app = &(*app)->ap_next ) + for ( app = (adpair **)&on->on_bi.bi_private; *app; app = &(*app)->ap_next ) /* Get to the end */ ; a2->ap_mem = ap.ap_mem; diff --git a/servers/slapd/overlays/dynlist.c b/servers/slapd/overlays/dynlist.c index 5c38b64..eb3a313 100644 --- a/servers/slapd/overlays/dynlist.c +++ b/servers/slapd/overlays/dynlist.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2022 The OpenLDAP Foundation. + * Copyright 2003-2024 The OpenLDAP Foundation. * Portions Copyright 2004-2005 Pierangelo Masarati. * Portions Copyright 2008 Emmanuel Dreyfus. * All rights reserved. @@ -1648,6 +1648,9 @@ dynlist_search2resp( Operation *op, SlapReply *rs ) dynlist_name_t *dyn; int rc; + if ( op->o_abandon ) + return SLAP_CB_CONTINUE; + if ( rs->sr_type == REP_SEARCH && rs->sr_entry != NULL ) { rc = SLAP_CB_CONTINUE; /* See if this is one of our dynamic groups */ diff --git a/servers/slapd/overlays/homedir.c b/servers/slapd/overlays/homedir.c index 159090e..78e3886 100644 --- a/servers/slapd/overlays/homedir.c +++ b/servers/slapd/overlays/homedir.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2009-2022 The OpenLDAP Foundation. + * Copyright 2009-2024 The OpenLDAP Foundation. * Portions copyright 2009-2010 Symas Corporation. * All rights reserved. * 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 = ≻ + + 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; diff --git a/servers/slapd/overlays/nestgroup.c b/servers/slapd/overlays/nestgroup.c new file mode 100644 index 0000000..ca5c928 --- /dev/null +++ b/servers/slapd/overlays/nestgroup.c @@ -0,0 +1,909 @@ +/* nestgroup.c - nested group overlay */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2024 The OpenLDAP Foundation. + * Copyright 2024 by Howard Chu. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* ACKNOWLEDGEMENTS: + * This work was initially developed by Howard Chu for inclusion in + * OpenLDAP Software. + */ + +#include "portable.h" + +#ifdef SLAPD_OVER_NESTGROUP + +#include + +#include +#include + +#include "lutil.h" +#include "slap.h" +#include "slap-config.h" + +/* This overlay dynamically constructs member and memberOf attributes + * for nested groups. + */ + +#define SLAPD_MEMBEROF_ATTR "memberOf" + +#define NG_MBR_VALUES 0x01 +#define NG_MBR_FILTER 0x02 +#define NG_MOF_VALUES 0x04 +#define NG_MOF_FILTER 0x08 +#define NG_NEGATED 0x10 + +static AttributeDescription *ad_member; +static AttributeDescription *ad_memberOf; + +static slap_verbmasks nestgroup_flags[] = { + { BER_BVC("member-values"), NG_MBR_VALUES }, + { BER_BVC("member-filter"), NG_MBR_FILTER }, + { BER_BVC("memberof-values"), NG_MOF_VALUES }, + { BER_BVC("memberof-filter"), NG_MOF_FILTER }, + { BER_BVNULL, 0 } +}; + +enum { + NG_MEMBER = 1, + NG_MEMBEROF, + NG_GROUPBASE, + NG_FLAGS +}; + +typedef struct nestgroup_info_t { + AttributeDescription *ngi_member; + AttributeDescription *ngi_memberOf; + BerVarray ngi_groupBase; + BerVarray ngi_ngroupBase; + int ngi_flags; +} nestgroup_info_t; + +static int ngroup_cf( ConfigArgs *c ) +{ + slap_overinst *on = (slap_overinst *)c->bi; + nestgroup_info_t *ngi = (nestgroup_info_t *)on->on_bi.bi_private; + int rc = 1; + + if ( c->op == SLAP_CONFIG_EMIT ) { + switch( c->type ) { + case NG_MEMBER: + if ( ngi->ngi_member ) { + value_add_one( &c->rvalue_vals, &ngi->ngi_member->ad_cname ); + rc = 0; + } + break; + case NG_MEMBEROF: + if ( ngi->ngi_memberOf ) { + value_add_one( &c->rvalue_vals, &ngi->ngi_memberOf->ad_cname ); + rc = 0; + } + break; + case NG_GROUPBASE: + if ( ngi->ngi_groupBase ) { + value_add( &c->rvalue_vals, ngi->ngi_groupBase ); + value_add( &c->rvalue_nvals, ngi->ngi_ngroupBase ); + rc = 0; + } + break; + case NG_FLAGS: + return mask_to_verbs( nestgroup_flags, ngi->ngi_flags, &c->rvalue_vals ); + default: + break; + } + return rc; + } else if ( c->op == LDAP_MOD_DELETE ) { + switch( c->type ) { + case NG_MEMBER: + ngi->ngi_member = ad_member; + rc = 0; + break; + case NG_MEMBEROF: + ngi->ngi_memberOf = ad_memberOf; + rc = 0; + break; + case NG_GROUPBASE: + if ( c->valx < 0 ) { + ber_bvarray_free( ngi->ngi_groupBase ); + ber_bvarray_free( ngi->ngi_ngroupBase ); + ngi->ngi_groupBase = NULL; + ngi->ngi_ngroupBase = NULL; + } else { + int i = c->valx; + ch_free( ngi->ngi_groupBase[i].bv_val ); + ch_free( ngi->ngi_ngroupBase[i].bv_val ); + do { + ngi->ngi_groupBase[i] = ngi->ngi_groupBase[i+1]; + ngi->ngi_ngroupBase[i] = ngi->ngi_ngroupBase[i+1]; + i++; + } while ( !BER_BVISNULL( &ngi->ngi_groupBase[i] )); + } + rc = 0; + break; + case NG_FLAGS: + if ( !c->line ) { + ngi->ngi_flags = 0; + } else { + int i = verb_to_mask( c->line, nestgroup_flags ); + ngi->ngi_flags &= ~nestgroup_flags[i].mask; + } + rc = 0; + break; + default: + break; + } + return rc; + } + + switch( c->type ) { + case NG_MEMBER: + if ( !is_at_syntax( c->value_ad->ad_type, SLAPD_DN_SYNTAX ) && + !is_at_syntax( c->value_ad->ad_type, SLAPD_NAMEUID_SYNTAX )) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "member attribute=\"%s\" must use DN (%s) or NAMEUID (%s) syntax", + c->argv[1], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX ); + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg ); + return ARG_BAD_CONF; + } + ngi->ngi_member = c->value_ad; + rc = 0; + break; + case NG_MEMBEROF: + if ( !is_at_syntax( c->value_ad->ad_type, SLAPD_DN_SYNTAX ) && + !is_at_syntax( c->value_ad->ad_type, SLAPD_NAMEUID_SYNTAX )) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "memberOf attribute=\"%s\" must use DN (%s) or NAMEUID (%s) syntax", + c->argv[1], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX ); + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg ); + return ARG_BAD_CONF; + } + ngi->ngi_memberOf = c->value_ad; + rc = 0; + break; + case NG_GROUPBASE: + ber_bvarray_add( &ngi->ngi_groupBase, &c->value_dn ); + ber_bvarray_add( &ngi->ngi_ngroupBase, &c->value_ndn ); + rc = 0; + break; + case NG_FLAGS: { + slap_mask_t flags = 0; + int i; + if ( c->op != SLAP_CONFIG_ADD && c->argc > 2 ) { + /* We wouldn't know how to delete these values later */ + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "Please insert multiple names as separate %s values", + c->argv[0] ); + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg ); + rc = LDAP_INVALID_SYNTAX; + break; + } + i = verbs_to_mask( c->argc, c->argv, nestgroup_flags, &flags ); + if ( i ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown option", c->argv[0] ); + Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", + c->log, c->cr_msg, c->argv[i]); + return(1); + } + ngi->ngi_flags |= flags; + rc = 0; + break; } + default: + break; + } + + return rc; +} + +static ConfigTable ngroupcfg[] = { + { "nestgroup-member", "member-ad", 2, 2, 0, + ARG_MAGIC|ARG_ATDESC|NG_MEMBER, ngroup_cf, + "( OLcfgOvAt:25.1 NAME 'olcNestGroupMember' " + "EQUALITY caseIgnoreMatch " + "DESC 'Member attribute' " + "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, + { "nestgroup-memberof", "memberOf-ad", 2, 2, 0, + ARG_MAGIC|ARG_ATDESC|NG_MEMBEROF, ngroup_cf, + "( OLcfgOvAt:25.2 NAME 'olcNestGroupMemberOf' " + "EQUALITY caseIgnoreMatch " + "DESC 'MemberOf attribute' " + "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, + { "nestgroup-base", "dn", 2, 2, 0, + ARG_DN|ARG_QUOTE|ARG_MAGIC|NG_GROUPBASE, ngroup_cf, + "( OLcfgOvAt:25.3 NAME 'olcNestGroupBase' " + "EQUALITY distinguishedNameMatch " + "DESC 'Base[s] of group subtree[s]' " + "SYNTAX OMsDN )", NULL, NULL }, + { "nestgroup-flags", "options", 2, 0, 0, + ARG_MAGIC|NG_FLAGS, ngroup_cf, + "( OLcfgOvAt:25.4 NAME 'olcNestGroupFlags' " + "EQUALITY caseIgnoreMatch " + "DESC 'Features to use' " + "SYNTAX OMsDirectoryString )", NULL, NULL }, + { NULL, NULL, 0, 0, 0, ARG_IGNORED } +}; + +static ConfigOCs ngroupocs[] = { + { "( OLcfgOvOc:25.1 " + "NAME 'olcNestGroupConfig' " + "DESC 'Nested Group configuration' " + "SUP olcOverlayConfig " + "MAY ( olcNestGroupMember $ olcNestGroupMemberOf $ " + " olcNestGroupBase $ olcNestGroupFlags ) ) ", + Cft_Overlay, ngroupcfg }, + { NULL, 0, NULL } +}; + +typedef struct nestgroup_filterinst_t { + Filter *nf_f; + Filter *nf_new; + Entry *nf_e; +} nestgroup_filterinst_t; + +/* Record occurrences of ad in filter. Ignore in negated filters. */ +static void +nestgroup_filter_instances( Operation *op, AttributeDescription *ad, Filter *f, int not, + int *nfn, nestgroup_filterinst_t **nfp, int *negated ) +{ + if ( !f ) + return; + + switch( f->f_choice & SLAPD_FILTER_MASK ) { + case LDAP_FILTER_EQUALITY: + if ( f->f_av_desc == ad ) { + if ( not ) { + *negated = 1; + } else { + nestgroup_filterinst_t *nf = *nfp; + int n = *nfn; + nf = op->o_tmprealloc( nf, (n + 1) * sizeof(nestgroup_filterinst_t), op->o_tmpmemctx ); + nf[n].nf_f = f; + nf[n].nf_new = NULL; + nf[n++].nf_e = NULL; + *nfp = nf; + *nfn = n; + } + } + break; + case SLAPD_FILTER_COMPUTED: + case LDAP_FILTER_PRESENT: + case LDAP_FILTER_GE: + case LDAP_FILTER_LE: + case LDAP_FILTER_APPROX: + case LDAP_FILTER_SUBSTRINGS: + case LDAP_FILTER_EXT: + break; + case LDAP_FILTER_NOT: not ^= 1; + /* FALLTHRU */ + case LDAP_FILTER_AND: + case LDAP_FILTER_OR: + for ( f = f->f_list; f; f = f->f_next ) + nestgroup_filter_instances( op, ad, f, not, nfn, nfp, negated ); + } +} + +static int +nestgroup_check_needed( Operation *op, int attrflags, AttributeDescription *ad ) +{ + if ( is_at_operational( ad->ad_type )) { + if ( SLAP_OPATTRS( attrflags )) + return 1; + } else { + if ( SLAP_USERATTRS( attrflags )) + return 1; + } + return ( ad_inlist( ad, op->ors_attrs )); +} + +typedef struct DNpair { + struct berval dp_ndn; + struct berval dp_dn; + struct DNpair *dp_next; + int dp_flag; +} DNpair; + +typedef struct gdn_info { + TAvlnode *gi_DNs; + DNpair *gi_DNlist; + nestgroup_info_t *gi_ngi; + int gi_numDNs; + int gi_saveDN; + Attribute *gi_merge; +} gdn_info; + +static int +nestgroup_dncmp( const void *v1, const void *v2 ) +{ + return ber_bvcmp((const struct berval *)v1, (const struct berval *)v2); +} + +static int +nestgroup_gotDNresp( Operation *op, SlapReply *rs ) +{ + if ( rs->sr_type == REP_SEARCH ) { + gdn_info *gi = (gdn_info *)(op->o_callback+1); + DNpair *dp = op->o_tmpalloc( sizeof(DNpair), op->o_tmpmemctx ); + dp->dp_ndn = rs->sr_entry->e_nname; + if ( ldap_tavl_insert( &gi->gi_DNs, dp, nestgroup_dncmp, ldap_avl_dup_error )) { + op->o_tmpfree( dp, op->o_tmpmemctx ); + } else { + ber_dupbv_x( &dp->dp_ndn, &rs->sr_entry->e_nname, op->o_tmpmemctx ); + if ( gi->gi_saveDN ) + ber_dupbv_x( &dp->dp_dn, &rs->sr_entry->e_name, op->o_tmpmemctx ); + gi->gi_numDNs++; + dp->dp_next = gi->gi_DNlist; + dp->dp_flag = 0; + gi->gi_DNlist = dp; + } + } + return 0; +} + +static void +nestgroup_get_parentDNs( Operation *op, struct berval *ndn ) +{ + SlapReply r = { REP_SEARCH }; + gdn_info *gi = (gdn_info *)(op->o_callback+1); + nestgroup_info_t *ngi = gi->gi_ngi; + int i; + + op->ors_filter->f_av_value = *ndn; + for ( i=0; !BER_BVISEMPTY( &ngi->ngi_ngroupBase[i] ); i++ ) { + op->o_req_dn = ngi->ngi_groupBase[i]; + op->o_req_ndn = ngi->ngi_ngroupBase[i]; + op->o_bd->be_search( op, &r ); + } + gi->gi_numDNs = 0; /* ignore first count, that's just the original member= result set */ + + while ( gi->gi_DNlist ) { + int prevnum; + DNpair *dp = gi->gi_DNlist; + gi->gi_DNlist = NULL; + for ( ; dp; dp=dp->dp_next ) { + op->ors_filter->f_av_value = dp->dp_ndn; + prevnum = gi->gi_numDNs; + for ( i=0; !BER_BVISEMPTY( &ngi->ngi_ngroupBase[i] ); i++ ) { + op->o_req_dn = ngi->ngi_groupBase[i]; + op->o_req_ndn = ngi->ngi_ngroupBase[i]; + op->o_bd->be_search( op, &r ); + } + if ( gi->gi_numDNs > prevnum ) + dp->dp_flag = 1; /* this group had a parent */ + } + } +} + +static void +nestgroup_memberFilter( Operation *op, int mbr_nf, nestgroup_filterinst_t *mbr_f ) +{ + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + nestgroup_info_t *ngi = on->on_bi.bi_private; + AttributeDescription *ad = mbr_f[0].nf_f->f_av_desc; + slap_callback *sc; + gdn_info *gi; + Filter mf; + AttributeAssertion mava; + Operation o = *op; + int i; + + o.o_managedsait = SLAP_CONTROL_CRITICAL; + sc = op->o_tmpcalloc( 1, sizeof(slap_callback) + sizeof(gdn_info), op->o_tmpmemctx); + gi = (gdn_info *)(sc+1); + gi->gi_ngi = ngi; + o.o_callback = sc; + sc->sc_response = nestgroup_gotDNresp; + o.ors_attrs = slap_anlist_no_attrs; + + mf.f_choice = LDAP_FILTER_EQUALITY; + mf.f_ava = &mava; + mf.f_av_desc = ad; + mf.f_next = NULL; + + o.ors_scope = LDAP_SCOPE_SUBTREE; + o.ors_deref = LDAP_DEREF_NEVER; + o.ors_limit = NULL; + o.ors_tlimit = SLAP_NO_LIMIT; + o.ors_slimit = SLAP_NO_LIMIT; + o.ors_filter = &mf; + o.o_bd->bd_info = (BackendInfo *)on->on_info; + + for ( i=0; igi_DNs = NULL; + gi->gi_numDNs = 0; + nestgroup_get_parentDNs( &o, &mbr_f[i].nf_f->f_av_value ); + if ( gi->gi_numDNs ) { + int j; + Filter *f, *nf; + TAvlnode *t; + DNpair *dp; + + f = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx ); + f->f_next = NULL; + t = ldap_tavl_end( gi->gi_DNs, TAVL_DIR_RIGHT ); + do { + dp = t->avl_data; + if ( dp->dp_flag ) { + nf = f; + nf->f_ava = op->o_tmpcalloc( 1, sizeof( AttributeAssertion ), op->o_tmpmemctx ); + nf->f_choice = LDAP_FILTER_EQUALITY; + nf->f_av_desc = ad; + nf->f_av_value = dp->dp_ndn; + f = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx ); + f->f_next = nf; + } + t = ldap_tavl_next( t, TAVL_DIR_LEFT ); + op->o_tmpfree( dp, op->o_tmpmemctx ); + } while ( t ); + ldap_tavl_free( gi->gi_DNs, NULL ); + f->f_choice = LDAP_FILTER_EQUALITY; + f->f_ava = mbr_f[i].nf_f->f_ava; + mbr_f[i].nf_new = f; + } + } + o.o_bd->bd_info = (BackendInfo *)on->on_info; + op->o_tmpfree( sc, op->o_tmpmemctx ); +} + +static void +nestgroup_addUnique( Operation *op, Attribute *old, Attribute *new ) +{ + /* strip out any duplicates from new before adding */ + struct berval *bv, *nbv; + int i, j, flags; + + bv = op->o_tmpalloc( (new->a_numvals + 1) * 2 * sizeof(struct berval), op->o_tmpmemctx ); + nbv = bv + new->a_numvals+1; + + flags = SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH|SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH; + for (i=0,j=0; ia_numvals; i++) { + int rc = attr_valfind( old, flags, &new->a_nvals[i], NULL, NULL ); + if ( rc ) { + bv[j] = new->a_vals[i]; + nbv[j++] = new->a_nvals[i]; + } + } + BER_BVZERO( &bv[j] ); + BER_BVZERO( &nbv[j] ); + attr_valadd( old, bv, nbv, j ); + op->o_tmpfree( bv, op->o_tmpmemctx ); +} + +static void +nestgroup_get_childDNs( Operation *op, slap_overinst *on, gdn_info *gi, struct berval *ndn ) +{ + nestgroup_info_t *ngi = on->on_bi.bi_private; + Entry *e; + Attribute *a; + + if ( overlay_entry_get_ov( op, ndn, NULL, NULL, 0, &e, on ) != LDAP_SUCCESS || e == NULL ) + return; + + a = attr_find( e->e_attrs, ngi->ngi_member ); + if ( a ) { + int i, j; + for (i = 0; ia_numvals; i++ ) { + /* record all group entries */ + for (j = 0; !BER_BVISEMPTY( &ngi->ngi_groupBase[j] ); j++) { + if ( dnIsSuffix( &a->a_nvals[i], &ngi->ngi_ngroupBase[j] )) { + DNpair *dp = op->o_tmpalloc( sizeof(DNpair), op->o_tmpmemctx ); + dp->dp_ndn = a->a_nvals[i]; + if ( ldap_tavl_insert( &gi->gi_DNs, dp, nestgroup_dncmp, ldap_avl_dup_error )) { + op->o_tmpfree( dp, op->o_tmpmemctx ); + } else { + ber_dupbv_x( &dp->dp_ndn, &a->a_nvals[i], op->o_tmpmemctx ); + gi->gi_numDNs++; + dp->dp_next = gi->gi_DNlist; + gi->gi_DNlist = dp; + } + break; + } + } + } + if ( gi->gi_merge ) { + nestgroup_addUnique( op, gi->gi_merge, a ); + } + } + overlay_entry_release_ov( op, e, 0, on ); +} + +static void +nestgroup_memberOfFilter( Operation *op, int mof_nf, nestgroup_filterinst_t *mof_f ) +{ + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + AttributeDescription *ad = mof_f[0].nf_f->f_av_desc; + gdn_info gi = {0}; + int i; + + for ( i=0; if_av_value ); + + while ( gi.gi_DNlist ) { + DNpair *dp = gi.gi_DNlist; + gi.gi_DNlist = NULL; + for ( ; dp; dp=dp->dp_next ) { + nestgroup_get_childDNs( op, on, &gi, &dp->dp_ndn ); + } + } + + if ( gi.gi_numDNs ) { + int j; + Filter *f, *nf; + TAvlnode *t; + DNpair *dp; + + f = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx ); + f->f_next = NULL; + t = ldap_tavl_end( gi.gi_DNs, TAVL_DIR_RIGHT ); + do { + dp = t->avl_data; + nf = f; + nf->f_ava = op->o_tmpcalloc( 1, sizeof( AttributeAssertion ), op->o_tmpmemctx ); + nf->f_choice = LDAP_FILTER_EQUALITY; + nf->f_av_desc = ad; + nf->f_av_value = dp->dp_ndn; + f = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx ); + f->f_next = nf; + t = ldap_tavl_next( t, TAVL_DIR_LEFT ); + op->o_tmpfree( dp, op->o_tmpmemctx ); + } while ( t ); + ldap_tavl_free( gi.gi_DNs, NULL ); + f->f_choice = LDAP_FILTER_EQUALITY; + f->f_ava = mof_f[i].nf_f->f_ava; + mof_f[i].nf_new = f; + } + } +} + +static void +nestgroup_memberOfVals( Operation *op, slap_overinst *on, Attribute *a ) +{ + nestgroup_info_t *ngi = on->on_bi.bi_private; + Operation o = *op; + slap_callback *sc; + gdn_info *gi; + Filter mf; + AttributeAssertion mava; + int i; + + o.o_managedsait = SLAP_CONTROL_CRITICAL; + sc = op->o_tmpcalloc( 1, sizeof(slap_callback) + sizeof(gdn_info), op->o_tmpmemctx); + gi = (gdn_info *)(sc+1); + gi->gi_ngi = ngi; + o.o_callback = sc; + sc->sc_response = nestgroup_gotDNresp; + o.ors_attrs = slap_anlist_no_attrs; + + mf.f_choice = LDAP_FILTER_EQUALITY; + mf.f_ava = &mava; + mf.f_av_desc = ngi->ngi_member; + mf.f_next = NULL; + + o.ors_filter = &mf; + o.ors_scope = LDAP_SCOPE_SUBTREE; + o.ors_deref = LDAP_DEREF_NEVER; + o.ors_limit = NULL; + o.ors_tlimit = SLAP_NO_LIMIT; + o.ors_slimit = SLAP_NO_LIMIT; + o.o_bd->bd_info = (BackendInfo *)on->on_info; + gi->gi_saveDN = 1; + + for ( i=0; ia_numvals; i++ ) { + nestgroup_get_parentDNs( &o, &a->a_nvals[i] ); + + while ( gi->gi_DNlist ) { + DNpair *dp = gi->gi_DNlist; + gi->gi_DNlist = NULL; + for ( ; dp; dp=dp->dp_next ) { + nestgroup_get_parentDNs( &o, &dp->dp_ndn ); + } + } + } + if ( gi->gi_DNs ) { + TAvlnode *p = ldap_tavl_end( gi->gi_DNs, TAVL_DIR_LEFT ); + int flags = SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH|SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH; + do { + DNpair *dp = p->avl_data; + int rc = attr_valfind( a, flags, &dp->dp_ndn, NULL, NULL ); + if ( rc ) + attr_valadd( a, &dp->dp_dn, &dp->dp_ndn, 1 ); + op->o_tmpfree( dp->dp_dn.bv_val, op->o_tmpmemctx ); + op->o_tmpfree( dp->dp_ndn.bv_val, op->o_tmpmemctx ); + op->o_tmpfree( dp, op->o_tmpmemctx ); + p = ldap_tavl_next( p, TAVL_DIR_RIGHT ); + } while ( p ); + ldap_tavl_free( gi->gi_DNs, NULL ); + } + o.o_bd->bd_info = (BackendInfo *)on->on_info; + op->o_tmpfree( sc, op->o_tmpmemctx ); +} + +typedef struct nestgroup_cbinfo { + slap_overinst *nc_on; + int nc_needed; +} nestgroup_cbinfo; + +static int +nestgroup_searchresp( Operation *op, SlapReply *rs ) +{ + if (rs->sr_type == REP_SEARCH ) { + nestgroup_cbinfo *nc = op->o_callback->sc_private; + slap_overinst *on = nc->nc_on; + nestgroup_info_t *ngi = on->on_bi.bi_private; + Attribute *a; + + if ( nc->nc_needed & NG_MBR_VALUES ) { + a = attr_find( rs->sr_entry->e_attrs, ngi->ngi_member ); + if ( a ) { + gdn_info gi = {0}; + int i, j; + if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) { + Entry *e = entry_dup( rs->sr_entry ); + rs_replace_entry( op, rs, on, e ); + rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; + a = attr_find( e->e_attrs, ngi->ngi_member ); + } + gi.gi_merge = a; + + for ( i=0; ia_numvals; i++ ) { + for ( j=0; !BER_BVISEMPTY( &ngi->ngi_ngroupBase[j] ); j++ ) { + if ( dnIsSuffix( &a->a_nvals[i], &ngi->ngi_ngroupBase[j] )) { + nestgroup_get_childDNs( op, on, &gi, &a->a_nvals[i] ); + + while ( gi.gi_DNlist ) { + DNpair *dp = gi.gi_DNlist; + gi.gi_DNlist = NULL; + for ( ; dp; dp=dp->dp_next ) { + nestgroup_get_childDNs( op, on, &gi, &dp->dp_ndn ); + } + } + break; + } + } + } + if ( gi.gi_numDNs ) { + TAvlnode *p = ldap_tavl_end( gi.gi_DNs, TAVL_DIR_LEFT ); + do { + DNpair *dp = p->avl_data; + op->o_tmpfree( dp->dp_ndn.bv_val, op->o_tmpmemctx ); + op->o_tmpfree( dp, op->o_tmpmemctx ); + p = ldap_tavl_next( p, TAVL_DIR_RIGHT ); + } while ( p ); + ldap_tavl_free( gi.gi_DNs, NULL ); + } + } + } + + if ( nc->nc_needed & NG_MOF_VALUES ) { + a = attr_find( rs->sr_entry->e_attrs, ngi->ngi_memberOf ); + if ( a ) { + if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) { + Entry *e = entry_dup( rs->sr_entry ); + rs_replace_entry( op, rs, on, e ); + rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; + a = attr_find( e->e_attrs, ngi->ngi_memberOf ); + } + nestgroup_memberOfVals( op, on, a ); + } + } + if (( nc->nc_needed & NG_NEGATED ) && + test_filter( op, rs->sr_entry, op->ors_filter ) != LDAP_COMPARE_TRUE ) + return 0; + } + return SLAP_CB_CONTINUE; +} + +static int +nestgroup_op_search( Operation *op, SlapReply *rs ) +{ + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + nestgroup_info_t *ngi = on->on_bi.bi_private; + int mbr_nf = 0, mof_nf = 0, negated = 0; + nestgroup_filterinst_t *mbr_f = NULL, *mof_f = NULL; + + if ( get_manageDSAit( op )) + return SLAP_CB_CONTINUE; + + /* groupBase must be explicitly configured */ + if ( !ngi->ngi_ngroupBase ) + return SLAP_CB_CONTINUE; + + /* handle attrs in filter */ + if ( ngi->ngi_flags & NG_MBR_FILTER ) { + nestgroup_filter_instances( op, ngi->ngi_member, op->ors_filter, 0, &mbr_nf, &mbr_f, &negated ); + if ( mbr_nf ) { + /* find member=(parent groups) */ + nestgroup_memberFilter( op, mbr_nf, mbr_f ); + } + } + if ( ngi->ngi_flags & NG_MOF_FILTER ) { + nestgroup_filter_instances( op, ngi->ngi_memberOf, op->ors_filter, 0, &mof_nf, &mof_f, &negated ); + if ( mof_nf ) { + /* find memberOf=(child groups) */ + nestgroup_memberOfFilter( op, mof_nf, mof_f ); + } + } + if ( mbr_nf ) { + int i; + for ( i=0; if_choice = LDAP_FILTER_OR; + mbr_f[i].nf_f->f_list = mbr_f[i].nf_new; + } + } + op->o_tmpfree( mbr_f, op->o_tmpmemctx ); + } + if ( mof_nf ) { + int i; + for ( i=0; if_choice = LDAP_FILTER_OR; + mof_f[i].nf_f->f_list = mof_f[i].nf_new; + } + } + op->o_tmpfree( mof_f, op->o_tmpmemctx ); + } + + if ( ngi->ngi_flags & ( NG_MBR_VALUES|NG_MOF_VALUES )) { + /* check for attrs in attrlist */ + int attrflags = slap_attr_flags( op->ors_attrs ); + int needed = 0; + if (( ngi->ngi_flags & NG_MBR_VALUES ) && + nestgroup_check_needed( op, attrflags, ngi->ngi_member )) { + /* collect all members from child groups */ + needed |= NG_MBR_VALUES; + } + if (( ngi->ngi_flags & NG_MOF_VALUES ) && + nestgroup_check_needed( op, attrflags, ngi->ngi_memberOf )) { + /* collect DNs of all parent groups */ + needed |= NG_MOF_VALUES; + } + if ( needed ) { + nestgroup_cbinfo *nc; + slap_callback *sc = op->o_tmpcalloc( 1, sizeof(slap_callback)+sizeof(nestgroup_cbinfo), op->o_tmpmemctx ); + nc = (nestgroup_cbinfo *)(sc+1); + sc->sc_private = nc; + nc->nc_needed = needed; + nc->nc_on = on; + sc->sc_response = nestgroup_searchresp; + sc->sc_next = op->o_callback; + op->o_callback = sc; + if ( negated ) nc->nc_needed |= NG_NEGATED; + } + } + return SLAP_CB_CONTINUE; +} + +static int +nestgroup_db_init( + BackendDB *be, + ConfigReply *cr) +{ + slap_overinst *on = (slap_overinst *)be->bd_info; + nestgroup_info_t *ngi; + int rc; + const char *text = NULL; + + ngi = (nestgroup_info_t *)ch_calloc( 1, sizeof( *ngi )); + on->on_bi.bi_private = ngi; + + if ( !ad_memberOf ) { + rc = slap_str2ad( SLAPD_MEMBEROF_ATTR, &ad_memberOf, &text ); + if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, "nestgroup_db_init: " + "unable to find attribute=\"%s\": %s (%d)\n", + SLAPD_MEMBEROF_ATTR, text, rc ); + return rc; + } + } + + if ( !ad_member ) { + rc = slap_str2ad( SLAPD_GROUP_ATTR, &ad_member, &text ); + if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, "nestgroup_db_init: " + "unable to find attribute=\"%s\": %s (%d)\n", + SLAPD_GROUP_ATTR, text, rc ); + return rc; + } + } + + return 0; +} + +static int +nestgroup_db_open( + BackendDB *be, + ConfigReply *cr) +{ + slap_overinst *on = (slap_overinst *)be->bd_info; + nestgroup_info_t *ngi = on->on_bi.bi_private; + + if ( !ngi->ngi_member ) + ngi->ngi_member = ad_member; + + if ( !ngi->ngi_memberOf ) + ngi->ngi_memberOf = ad_memberOf; + + return 0; +} + +static int +nestgroup_db_destroy( + BackendDB *be, + ConfigReply *cr +) +{ + slap_overinst *on = (slap_overinst *) be->bd_info; + nestgroup_info_t *ngi = on->on_bi.bi_private; + + ber_bvarray_free( ngi->ngi_groupBase ); + ber_bvarray_free( ngi->ngi_ngroupBase ); + ch_free( ngi ); + + return 0; +} + +static slap_overinst nestgroup; + +/* This overlay is set up for dynamic loading via moduleload. For static + * configuration, you'll need to arrange for the slap_overinst to be + * initialized and registered by some other function inside slapd. + */ + +int nestgroup_initialize() { + int code; + + code = register_at( + "( 1.2.840.113556.1.2.102 " + "NAME 'memberOf' " + "DESC 'Group that the entry belongs to' " + "SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' " + "EQUALITY distinguishedNameMatch " /* added */ + "USAGE dSAOperation " /* added; questioned */ + "NO-USER-MODIFICATION " /* added */ + "X-ORIGIN 'iPlanet Delegated Administrator' )", + &ad_memberOf, 0 ); + if ( code && code != SLAP_SCHERR_ATTR_DUP ) { + Debug( LDAP_DEBUG_ANY, + "nestgroup_initialize: register_at (memberOf) failed\n" ); + return code; + } + + nestgroup.on_bi.bi_type = "nestgroup"; + nestgroup.on_bi.bi_db_init = nestgroup_db_init; + nestgroup.on_bi.bi_db_open = nestgroup_db_open; + nestgroup.on_bi.bi_db_destroy = nestgroup_db_destroy; + + nestgroup.on_bi.bi_op_search = nestgroup_op_search; +/* nestgroup.on_bi.bi_op_compare = nestgroup_op_compare; */ + + nestgroup.on_bi.bi_cf_ocs = ngroupocs; + code = config_register_schema( ngroupcfg, ngroupocs ); + if ( code ) return code; + + return overlay_register( &nestgroup ); +} + +#if SLAPD_OVER_NESTGROUP == SLAPD_MOD_DYNAMIC +int +init_module( int argc, char *argv[] ) +{ + return nestgroup_initialize(); +} +#endif + +#endif /* defined(SLAPD_OVER_NESTGROUP) */ diff --git a/servers/slapd/overlays/otp.c b/servers/slapd/overlays/otp.c index 590ee50..b39c186 100644 --- a/servers/slapd/overlays/otp.c +++ b/servers/slapd/overlays/otp.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2015-2022 The OpenLDAP Foundation. + * Copyright 2015-2024 The OpenLDAP Foundation. * Portions Copyright 2015 by Howard Chu, Symas Corp. * Portions Copyright 2016-2017 by Michael Ströder * Portions Copyright 2018 by Ondřej Kuzník, Symas Corp. diff --git a/servers/slapd/overlays/overlays.c b/servers/slapd/overlays/overlays.c index 8290200..6ee4395 100644 --- a/servers/slapd/overlays/overlays.c +++ b/servers/slapd/overlays/overlays.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2022 The OpenLDAP Foundation. + * Copyright 2003-2024 The OpenLDAP Foundation. * Copyright 2003 by Howard Chu. * All rights reserved. * diff --git a/servers/slapd/overlays/pcache.c b/servers/slapd/overlays/pcache.c index 2b947e4..3a1e18a 100644 --- a/servers/slapd/overlays/pcache.c +++ b/servers/slapd/overlays/pcache.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2022 The OpenLDAP Foundation. + * Copyright 2003-2024 The OpenLDAP Foundation. * Portions Copyright 2003 IBM Corporation. * Portions Copyright 2003-2009 Symas Corporation. * All rights reserved. diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c index 29a77c8..0cdba70 100644 --- a/servers/slapd/overlays/ppolicy.c +++ b/servers/slapd/overlays/ppolicy.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2022 The OpenLDAP Foundation. + * Copyright 2004-2024 The OpenLDAP Foundation. * Portions Copyright 2004-2005 Howard Chu, Symas Corporation. * Portions Copyright 2004 Hewlett-Packard Company. * All rights reserved. diff --git a/servers/slapd/overlays/refint.c b/servers/slapd/overlays/refint.c index 201803b..77935a7 100644 --- a/servers/slapd/overlays/refint.c +++ b/servers/slapd/overlays/refint.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2022 The OpenLDAP Foundation. + * Copyright 2004-2024 The OpenLDAP Foundation. * Portions Copyright 2004 Symas Corporation. * All rights reserved. * @@ -603,6 +603,7 @@ refint_repair( op->o_ndn = op->o_bd->be_rootndn; cache = op->o_do_not_cache; op->o_do_not_cache = 1; + op->o_abandon = 0; /* search */ rc = op->o_bd->be_search( op, &rs ); diff --git a/servers/slapd/overlays/remoteauth.c b/servers/slapd/overlays/remoteauth.c index 1d60af0..63f784e 100644 --- a/servers/slapd/overlays/remoteauth.c +++ b/servers/slapd/overlays/remoteauth.c @@ -2,7 +2,7 @@ /* remoteauth.c - Overlay to delegate bind processing to a remote server */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2022 The OpenLDAP Foundation. + * Copyright 2004-2024 The OpenLDAP Foundation. * Portions Copyright 2017-2021 Ondřej Kuzník, Symas Corporation. * Portions Copyright 2004-2017 Howard Chu, Symas Corporation. * Portions Copyright 2004 Hewlett-Packard Company. diff --git a/servers/slapd/overlays/retcode.c b/servers/slapd/overlays/retcode.c index 15052e0..85b8f74 100644 --- a/servers/slapd/overlays/retcode.c +++ b/servers/slapd/overlays/retcode.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005-2022 The OpenLDAP Foundation. + * Copyright 2005-2024 The OpenLDAP Foundation. * Portions Copyright 2005 Pierangelo Masarati * All rights reserved. * diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c index af10f6d..d12d7b3 100644 --- a/servers/slapd/overlays/rwm.c +++ b/servers/slapd/overlays/rwm.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2022 The OpenLDAP Foundation. + * Copyright 2003-2024 The OpenLDAP Foundation. * Portions Copyright 2003 Pierangelo Masarati. * All rights reserved. * diff --git a/servers/slapd/overlays/rwm.h b/servers/slapd/overlays/rwm.h index 6753737..1504699 100644 --- a/servers/slapd/overlays/rwm.h +++ b/servers/slapd/overlays/rwm.h @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1999-2022 The OpenLDAP Foundation. + * Copyright 1999-2024 The OpenLDAP Foundation. * Portions Copyright 1999-2003 Howard Chu. * Portions Copyright 2000-2003 Pierangelo Masarati. * All rights reserved. diff --git a/servers/slapd/overlays/rwmconf.c b/servers/slapd/overlays/rwmconf.c index a1a9f36..4b3c690 100644 --- a/servers/slapd/overlays/rwmconf.c +++ b/servers/slapd/overlays/rwmconf.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1999-2022 The OpenLDAP Foundation. + * Copyright 1999-2024 The OpenLDAP Foundation. * Portions Copyright 1999-2003 Howard Chu. * Portions Copyright 2000-2003 Pierangelo Masarati. * All rights reserved. diff --git a/servers/slapd/overlays/rwmdn.c b/servers/slapd/overlays/rwmdn.c index c67e3cf..fd53002 100644 --- a/servers/slapd/overlays/rwmdn.c +++ b/servers/slapd/overlays/rwmdn.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1999-2022 The OpenLDAP Foundation. + * Copyright 1999-2024 The OpenLDAP Foundation. * Portions Copyright 1999-2003 Howard Chu. * Portions Copyright 2000-2003 Pierangelo Masarati. * All rights reserved. diff --git a/servers/slapd/overlays/rwmmap.c b/servers/slapd/overlays/rwmmap.c index 74ffd05..90a800c 100644 --- a/servers/slapd/overlays/rwmmap.c +++ b/servers/slapd/overlays/rwmmap.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1999-2022 The OpenLDAP Foundation. + * Copyright 1999-2024 The OpenLDAP Foundation. * Portions Copyright 1999-2003 Howard Chu. * Portions Copyright 2000-2003 Pierangelo Masarati. * All rights reserved. diff --git a/servers/slapd/overlays/seqmod.c b/servers/slapd/overlays/seqmod.c index 503d6a6..64c1c33 100644 --- a/servers/slapd/overlays/seqmod.c +++ b/servers/slapd/overlays/seqmod.c @@ -1,7 +1,7 @@ /* seqmod.c - sequenced modifies */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2022 The OpenLDAP Foundation. + * Copyright 2004-2024 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/servers/slapd/overlays/sssvlv.c b/servers/slapd/overlays/sssvlv.c index 828782a..95803d9 100644 --- a/servers/slapd/overlays/sssvlv.c +++ b/servers/slapd/overlays/sssvlv.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2009-2022 The OpenLDAP Foundation. + * Copyright 2009-2024 The OpenLDAP Foundation. * Portions copyright 2009 Symas Corporation. * All rights reserved. * diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c index f208846..6739e24 100644 --- a/servers/slapd/overlays/syncprov.c +++ b/servers/slapd/overlays/syncprov.c @@ -2,7 +2,7 @@ /* syncprov.c - syncrepl provider */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2022 The OpenLDAP Foundation. + * Copyright 2004-2024 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -3878,14 +3878,14 @@ sp_cf_gen(ConfigArgs *c) break; case SP_NOPRES: si->si_nopres = c->value_int; - break; - case SP_USEHINT: - si->si_usehint = c->value_int; - if ( si->si_usehint ) { + if ( si->si_nopres ) { /* Consider we might be a delta provider, but it's ok if not */ (void)syncprov_setup_accesslog(); } break; + case SP_USEHINT: + si->si_usehint = c->value_int; + break; case SP_LOGDB: if ( si->si_logs ) { Debug( LDAP_DEBUG_ANY, "syncprov_config: while configuring " diff --git a/servers/slapd/overlays/translucent.c b/servers/slapd/overlays/translucent.c index 09b12dc..0b2fa4c 100644 --- a/servers/slapd/overlays/translucent.c +++ b/servers/slapd/overlays/translucent.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2022 The OpenLDAP Foundation. + * Copyright 2004-2024 The OpenLDAP Foundation. * Portions Copyright 2005 Symas Corporation. * All rights reserved. * diff --git a/servers/slapd/overlays/unique.c b/servers/slapd/overlays/unique.c index 561d86d..c3913af 100644 --- a/servers/slapd/overlays/unique.c +++ b/servers/slapd/overlays/unique.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2022 The OpenLDAP Foundation. + * Copyright 2004-2024 The OpenLDAP Foundation. * Portions Copyright 2004,2006-2007 Symas Corporation. * All rights reserved. * diff --git a/servers/slapd/overlays/valsort.c b/servers/slapd/overlays/valsort.c index 3d998e2..6cc95f7 100644 --- a/servers/slapd/overlays/valsort.c +++ b/servers/slapd/overlays/valsort.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005-2022 The OpenLDAP Foundation. + * Copyright 2005-2024 The OpenLDAP Foundation. * Portions copyright 2005 Symas Corporation. * All rights reserved. * @@ -201,7 +201,7 @@ valsort_cf_func(ConfigArgs *c) { return(1); } - for ( vip = &on->on_bi.bi_private; *vip; vip = &(*vip)->vi_next ) + for ( vip = (valsort_info **)&on->on_bi.bi_private; *vip; vip = &(*vip)->vi_next ) /* Get to the end */ ; vi = ch_malloc( sizeof(valsort_info) ); -- cgit v1.2.3