1 /* dynlist.c - dynamic list overlay */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/overlays/dynlist.c,v 1.20.2.17 2008/07/10 00:43:03 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2008 The OpenLDAP Foundation.
6 * Portions Copyright 2004-2005 Pierangelo Masarati.
7 * Portions Copyright 2008 Emmanuel Dreyfus.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
19 * This work was initially developed by Pierangelo Masarati
20 * for SysNet s.n.c., for inclusion in OpenLDAP Software.
25 #ifdef SLAPD_OVER_DYNLIST
27 #if LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR > 3
28 #if SLAPD_OVER_DYNGROUP != SLAPD_MOD_STATIC
29 #define TAKEOVER_DYNGROUP
32 #if LDAP_VENDOR_VERSION_MINOR < 3
39 #include <ac/string.h>
47 /* FIXME: the code differs if SLAP_OPATTRS is defined or not;
48 * SLAP_OPATTRS is not defined in 2.2 yet, while this overlay
49 * expects HEAD code at least later than August 6, 2004. */
50 /* FIXME: slap_anlist_no_attrs was introduced in 2.3; here it
51 * is anticipated to allow using this overlay with 2.2. */
54 static AttributeName anlist_no_attrs
[] = {
55 { BER_BVC( LDAP_NO_ATTRS
), NULL
, 0, NULL
},
56 { BER_BVNULL
, NULL
, 0, NULL
}
59 static AttributeName
*slap_anlist_no_attrs
= anlist_no_attrs
;
62 static AttributeDescription
*ad_dgIdentity
, *ad_dgAuthz
;
64 typedef struct dynlist_map_t
{
65 AttributeDescription
*dlm_member_ad
;
66 AttributeDescription
*dlm_mapped_ad
;
67 struct dynlist_map_t
*dlm_next
;
70 typedef struct dynlist_info_t
{
72 AttributeDescription
*dli_ad
;
73 struct dynlist_map_t
*dli_dlm
;
74 struct berval dli_default_filter
;
75 struct dynlist_info_t
*dli_next
;
78 #define DYNLIST_USAGE \
79 "\"dynlist-attrset <oc> <URL-ad> [[<mapped-ad>:]<member-ad> ...]\": "
81 static dynlist_info_t
*
82 dynlist_is_dynlist_next( Operation
*op
, SlapReply
*rs
, dynlist_info_t
*old_dli
)
84 slap_overinst
*on
= (slap_overinst
*)op
->o_bd
->bd_info
;
89 if ( old_dli
== NULL
) {
90 dli
= (dynlist_info_t
*)on
->on_bi
.bi_private
;
93 dli
= old_dli
->dli_next
;
96 a
= attrs_find( rs
->sr_entry
->e_attrs
, slap_schema
.si_ad_objectClass
);
98 /* FIXME: objectClass must be present; for non-storage
99 * backends, like back-ldap, it needs to be added
100 * to the requested attributes */
104 for ( ; dli
; dli
= dli
->dli_next
) {
105 if ( attr_valfind( a
,
106 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH
|
107 SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
,
108 &dli
->dli_oc
->soc_cname
, NULL
,
109 op
->o_tmpmemctx
) == 0 )
119 dynlist_make_filter( Operation
*op
, struct berval
*oldf
, struct berval
*newf
)
121 slap_overinst
*on
= (slap_overinst
*)op
->o_bd
->bd_info
;
122 dynlist_info_t
*dli
= (dynlist_info_t
*)on
->on_bi
.bi_private
;
126 assert( oldf
!= NULL
);
127 assert( newf
!= NULL
);
128 assert( !BER_BVISNULL( oldf
) );
129 assert( !BER_BVISEMPTY( oldf
) );
131 newf
->bv_len
= STRLENOF( "(&(!(objectClass=" "))" ")" )
132 + dli
->dli_oc
->soc_cname
.bv_len
+ oldf
->bv_len
;
133 newf
->bv_val
= op
->o_tmpalloc( newf
->bv_len
+ 1, op
->o_tmpmemctx
);
134 if ( newf
->bv_val
== NULL
) {
137 ptr
= lutil_strcopy( newf
->bv_val
, "(&(!(objectClass=" );
138 ptr
= lutil_strcopy( ptr
, dli
->dli_oc
->soc_cname
.bv_val
);
139 ptr
= lutil_strcopy( ptr
, "))" );
140 ptr
= lutil_strcopy( ptr
, oldf
->bv_val
);
141 ptr
= lutil_strcopy( ptr
, ")" );
142 newf
->bv_len
= ptr
- newf
->bv_val
;
147 typedef struct dynlist_sc_t
{
148 dynlist_info_t
*dlc_dli
;
153 dynlist_sc_update( Operation
*op
, SlapReply
*rs
)
159 AccessControlState acl_state
= ACL_STATE_INIT
;
164 if ( rs
->sr_type
!= REP_SEARCH
) {
168 dlc
= (dynlist_sc_t
*)op
->o_callback
->sc_private
;
172 assert( rs
->sr_entry
!= NULL
);
174 /* test access to entry */
175 if ( !access_allowed( op
, rs
->sr_entry
, slap_schema
.si_ad_entry
,
176 NULL
, ACL_READ
, NULL
) )
181 /* if there is only one member_ad, and it's not mapped,
182 * consider it as old-style member listing */
183 dlm
= dlc
->dlc_dli
->dli_dlm
;
184 if ( dlm
&& dlm
->dlm_mapped_ad
== NULL
&& dlm
->dlm_next
== NULL
) {
185 /* if access allowed, try to add values, emulating permissive
186 * control to silently ignore duplicates */
187 if ( access_allowed( op
, rs
->sr_entry
, slap_schema
.si_ad_entry
,
188 NULL
, ACL_READ
, NULL
) )
191 const char *text
= NULL
;
193 struct berval vals
[ 2 ], nvals
[ 2 ];
195 vals
[ 0 ] = rs
->sr_entry
->e_name
;
196 BER_BVZERO( &vals
[ 1 ] );
197 nvals
[ 0 ] = rs
->sr_entry
->e_nname
;
198 BER_BVZERO( &nvals
[ 1 ] );
200 mod
.sm_op
= LDAP_MOD_ADD
;
201 mod
.sm_desc
= dlm
->dlm_member_ad
;
202 mod
.sm_type
= dlm
->dlm_member_ad
->ad_cname
;
203 mod
.sm_values
= vals
;
204 mod
.sm_nvalues
= nvals
;
207 (void)modify_add_values( e
, &mod
, /* permissive */ 1,
208 &text
, textbuf
, sizeof( textbuf
) );
215 opattrs
= ( rs
->sr_attrs
== NULL
) ? 0 : an_find( rs
->sr_attrs
, &AllOper
);
216 userattrs
= ( rs
->sr_attrs
== NULL
) ? 1 : an_find( rs
->sr_attrs
, &AllUser
);
217 #else /* SLAP_OPATTRS */
218 opattrs
= SLAP_OPATTRS( rs
->sr_attr_flags
);
219 userattrs
= SLAP_USERATTRS( rs
->sr_attr_flags
);
220 #endif /* SLAP_OPATTRS */
222 for ( a
= rs
->sr_entry
->e_attrs
; a
!= NULL
; a
= a
->a_next
) {
223 BerVarray vals
, nvals
= NULL
;
225 is_oc
= a
->a_desc
== slap_schema
.si_ad_objectClass
;
227 /* if attribute is not requested, skip it */
228 if ( rs
->sr_attrs
== NULL
) {
229 if ( is_at_operational( a
->a_desc
->ad_type
) ) {
234 if ( is_at_operational( a
->a_desc
->ad_type
) ) {
235 if ( !opattrs
&& !ad_inlist( a
->a_desc
, rs
->sr_attrs
) )
241 if ( !userattrs
&& !ad_inlist( a
->a_desc
, rs
->sr_attrs
) )
248 /* test access to attribute */
249 if ( op
->ors_attrsonly
) {
250 if ( !access_allowed( op
, rs
->sr_entry
, a
->a_desc
, NULL
,
251 ACL_READ
, &acl_state
) )
257 /* single-value check: keep first only */
258 if ( is_at_single_value( a
->a_desc
->ad_type
) ) {
259 if ( attr_find( e
->e_attrs
, a
->a_desc
) != NULL
) {
264 /* test access to attribute */
267 vals
= op
->o_tmpalloc( ( i
+ 1 ) * sizeof( struct berval
), op
->o_tmpmemctx
);
268 if ( a
->a_nvals
!= a
->a_vals
) {
269 nvals
= op
->o_tmpalloc( ( i
+ 1 ) * sizeof( struct berval
), op
->o_tmpmemctx
);
272 for ( i
= 0, j
= 0; !BER_BVISNULL( &a
->a_vals
[i
] ); i
++ ) {
274 ObjectClass
*soc
= oc_bvfind( &a
->a_vals
[i
] );
276 if ( soc
->soc_kind
== LDAP_SCHEMA_STRUCTURAL
) {
281 if ( access_allowed( op
, rs
->sr_entry
, a
->a_desc
,
282 &a
->a_nvals
[i
], ACL_READ
, &acl_state
) )
284 vals
[j
] = a
->a_vals
[i
];
286 nvals
[j
] = a
->a_nvals
[i
];
292 /* if access allowed, try to add values, emulating permissive
293 * control to silently ignore duplicates */
296 const char *text
= NULL
;
299 AttributeDescription
*ad
;
301 BER_BVZERO( &vals
[j
] );
303 BER_BVZERO( &nvals
[j
] );
307 for ( dlm
= dlc
->dlc_dli
->dli_dlm
; dlm
; dlm
= dlm
->dlm_next
) {
308 if ( dlm
->dlm_member_ad
== a
->a_desc
) {
309 ad
= dlm
->dlm_mapped_ad
;
314 mod
.sm_op
= LDAP_MOD_ADD
;
316 mod
.sm_type
= ad
->ad_cname
;
317 mod
.sm_values
= vals
;
318 mod
.sm_nvalues
= nvals
;
321 (void)modify_add_values( e
, &mod
, /* permissive */ 1,
322 &text
, textbuf
, sizeof( textbuf
) );
325 op
->o_tmpfree( vals
, op
->o_tmpmemctx
);
327 op
->o_tmpfree( nvals
, op
->o_tmpmemctx
);
332 if ( rs
->sr_flags
& REP_ENTRY_MUSTBEFREED
) {
333 entry_free( rs
->sr_entry
);
335 rs
->sr_flags
^= REP_ENTRY_MUSTBEFREED
;
342 dynlist_prepare_entry( Operation
*op
, SlapReply
*rs
, dynlist_info_t
*dli
)
344 Attribute
*a
, *id
= NULL
;
347 SlapReply r
= { REP_SEARCH
};
353 dynlist_sc_t dlc
= { 0 };
356 a
= attrs_find( rs
->sr_entry
->e_attrs
, dli
->dli_ad
);
359 return SLAP_CB_CONTINUE
;
363 opattrs
= ( rs
->sr_attrs
== NULL
) ? 0 : an_find( rs
->sr_attrs
, &AllOper
);
364 userattrs
= ( rs
->sr_attrs
== NULL
) ? 1 : an_find( rs
->sr_attrs
, &AllUser
);
365 #else /* SLAP_OPATTRS */
366 opattrs
= SLAP_OPATTRS( rs
->sr_attr_flags
);
367 userattrs
= SLAP_USERATTRS( rs
->sr_attr_flags
);
368 #endif /* SLAP_OPATTRS */
370 /* Don't generate member list if it wasn't requested */
371 for ( dlm
= dli
->dli_dlm
; dlm
; dlm
= dlm
->dlm_next
) {
373 ad_inlist( dlm
->dlm_member_ad
, rs
->sr_attrs
) )
376 if ( dli
->dli_dlm
&& !dlm
)
377 return SLAP_CB_CONTINUE
;
379 if ( ad_dgIdentity
&& ( id
= attrs_find( rs
->sr_entry
->e_attrs
, ad_dgIdentity
))) {
380 Attribute
*authz
= NULL
;
382 /* if not rootdn and dgAuthz is present,
383 * check if user can be authorized as dgIdentity */
384 if ( ad_dgAuthz
&& !BER_BVISEMPTY( &id
->a_nvals
[0] ) && !be_isroot( op
)
385 && ( authz
= attrs_find( rs
->sr_entry
->e_attrs
, ad_dgAuthz
) ) )
387 if ( slap_sasl_matches( op
, authz
->a_nvals
,
388 &o
.o_ndn
, &o
.o_ndn
) != LDAP_SUCCESS
)
390 return SLAP_CB_CONTINUE
;
394 o
.o_dn
= id
->a_vals
[0];
395 o
.o_ndn
= id
->a_nvals
[0];
399 if ( !( rs
->sr_flags
& REP_ENTRY_MODIFIABLE
) ) {
400 e
= entry_dup( rs
->sr_entry
);
404 e_flags
= rs
->sr_flags
| ( REP_ENTRY_MODIFIABLE
| REP_ENTRY_MUSTBEFREED
);
408 cb
.sc_private
= &dlc
;
409 cb
.sc_response
= dynlist_sc_update
;
410 cb
.sc_cleanup
= NULL
;
414 o
.ors_deref
= LDAP_DEREF_NEVER
;
416 o
.ors_tlimit
= SLAP_NO_LIMIT
;
417 o
.ors_slimit
= SLAP_NO_LIMIT
;
419 for ( url
= a
->a_nvals
; !BER_BVISNULL( url
); url
++ ) {
420 LDAPURLDesc
*lud
= NULL
;
426 BER_BVZERO( &o
.o_req_dn
);
427 BER_BVZERO( &o
.o_req_ndn
);
430 BER_BVZERO( &o
.ors_filterstr
);
432 if ( ldap_url_parse( url
->bv_val
, &lud
) != LDAP_URL_SUCCESS
) {
437 if ( lud
->lud_host
!= NULL
) {
438 /* FIXME: host not allowed; reject as illegal? */
439 Debug( LDAP_DEBUG_ANY
, "dynlist_prepare_entry(\"%s\"): "
440 "illegal URI \"%s\"\n",
441 e
->e_name
.bv_val
, url
->bv_val
, 0 );
445 if ( lud
->lud_dn
== NULL
) {
446 /* note that an empty base is not honored in terms
447 * of defaultSearchBase, because select_backend()
448 * is not aware of the defaultSearchBase option;
449 * this can be useful in case of a database serving
450 * the empty suffix */
451 BER_BVSTR( &dn
, "" );
454 ber_str2bv( lud
->lud_dn
, 0, 0, &dn
);
456 rc
= dnPrettyNormal( NULL
, &dn
, &o
.o_req_dn
, &o
.o_req_ndn
, op
->o_tmpmemctx
);
457 if ( rc
!= LDAP_SUCCESS
) {
461 o
.ors_scope
= lud
->lud_scope
;
463 for ( dlm
= dli
->dli_dlm
; dlm
; dlm
= dlm
->dlm_next
) {
464 if ( dlm
->dlm_mapped_ad
!= NULL
) {
469 if ( dli
->dli_dlm
&& !dlm
) {
470 /* if ( lud->lud_attrs != NULL ),
471 * the URL should be ignored */
472 o
.ors_attrs
= slap_anlist_no_attrs
;
474 } else if ( lud
->lud_attrs
== NULL
) {
475 o
.ors_attrs
= rs
->sr_attrs
;
478 for ( i
= 0; lud
->lud_attrs
[i
]; i
++)
481 o
.ors_attrs
= op
->o_tmpcalloc( i
+ 1, sizeof( AttributeName
), op
->o_tmpmemctx
);
482 for ( i
= 0, j
= 0; lud
->lud_attrs
[i
]; i
++) {
483 const char *text
= NULL
;
485 ber_str2bv( lud
->lud_attrs
[i
], 0, 0, &o
.ors_attrs
[j
].an_name
);
486 o
.ors_attrs
[j
].an_desc
= NULL
;
487 (void)slap_bv2ad( &o
.ors_attrs
[j
].an_name
, &o
.ors_attrs
[j
].an_desc
, &text
);
488 /* FIXME: ignore errors... */
490 if ( rs
->sr_attrs
== NULL
) {
491 if ( o
.ors_attrs
[j
].an_desc
!= NULL
&&
492 is_at_operational( o
.ors_attrs
[j
].an_desc
->ad_type
) )
498 if ( o
.ors_attrs
[j
].an_desc
!= NULL
&&
499 is_at_operational( o
.ors_attrs
[j
].an_desc
->ad_type
) )
501 if ( !opattrs
&& !ad_inlist( o
.ors_attrs
[j
].an_desc
, rs
->sr_attrs
) )
508 o
.ors_attrs
[j
].an_desc
!= NULL
&&
509 !ad_inlist( o
.ors_attrs
[j
].an_desc
, rs
->sr_attrs
) )
523 BER_BVZERO( &o
.ors_attrs
[j
].an_name
);
526 if ( lud
->lud_filter
== NULL
) {
527 ber_dupbv_x( &o
.ors_filterstr
,
528 &dli
->dli_default_filter
, op
->o_tmpmemctx
);
532 ber_str2bv( lud
->lud_filter
, 0, 0, &flt
);
533 if ( dynlist_make_filter( op
, &flt
, &o
.ors_filterstr
) ) {
538 o
.ors_filter
= str2filter_x( op
, o
.ors_filterstr
.bv_val
);
539 if ( o
.ors_filter
== NULL
) {
543 o
.o_bd
= select_backend( &o
.o_req_ndn
, 1 );
544 if ( o
.o_bd
&& o
.o_bd
->be_search
) {
546 r
.sr_attr_flags
= slap_attr_flags( o
.ors_attrs
);
547 #endif /* SLAP_OPATTRS */
548 (void)o
.o_bd
->be_search( &o
, &r
);
553 slap_op_groups_free( &o
);
555 if ( o
.ors_filter
) {
556 filter_free_x( &o
, o
.ors_filter
);
558 if ( o
.ors_attrs
&& o
.ors_attrs
!= rs
->sr_attrs
559 && o
.ors_attrs
!= slap_anlist_no_attrs
)
561 op
->o_tmpfree( o
.ors_attrs
, op
->o_tmpmemctx
);
563 if ( !BER_BVISNULL( &o
.o_req_dn
) ) {
564 op
->o_tmpfree( o
.o_req_dn
.bv_val
, op
->o_tmpmemctx
);
566 if ( !BER_BVISNULL( &o
.o_req_ndn
) ) {
567 op
->o_tmpfree( o
.o_req_ndn
.bv_val
, op
->o_tmpmemctx
);
569 assert( BER_BVISNULL( &o
.ors_filterstr
)
570 || o
.ors_filterstr
.bv_val
!= lud
->lud_filter
);
571 op
->o_tmpfree( o
.ors_filterstr
.bv_val
, op
->o_tmpmemctx
);
572 ldap_free_urldesc( lud
);
576 rs
->sr_flags
= e_flags
;
578 return SLAP_CB_CONTINUE
;
582 dynlist_sc_save_entry( Operation
*op
, SlapReply
*rs
)
584 /* save the entry in the private field of the callback,
585 * so it doesn't get freed (it's temporary!) */
586 if ( rs
->sr_entry
!= NULL
) {
587 dynlist_sc_t
*dlc
= (dynlist_sc_t
*)op
->o_callback
->sc_private
;
588 dlc
->dlc_e
= rs
->sr_entry
;
596 dynlist_compare( Operation
*op
, SlapReply
*rs
)
598 slap_overinst
*on
= (slap_overinst
*)op
->o_bd
->bd_info
;
599 dynlist_info_t
*dli
= (dynlist_info_t
*)on
->on_bi
.bi_private
;
604 for ( ; dli
!= NULL
; dli
= dli
->dli_next
) {
605 for ( dlm
= dli
->dli_dlm
; dlm
; dlm
= dlm
->dlm_next
)
606 if ( op
->oq_compare
.rs_ava
->aa_desc
== dlm
->dlm_member_ad
)
609 if ( dli
->dli_dlm
&& dlm
) {
610 /* This compare is for one of the attributes we're
611 * interested in. We'll use slapd's existing dyngroup
612 * evaluator to get the answer we want.
614 BerVarray id
= NULL
, authz
= NULL
;
616 o
.o_do_not_cache
= 1;
618 if ( ad_dgIdentity
&& backend_attribute( &o
, NULL
, &o
.o_req_ndn
,
619 ad_dgIdentity
, &id
, ACL_READ
) == LDAP_SUCCESS
)
621 /* if not rootdn and dgAuthz is present,
622 * check if user can be authorized as dgIdentity */
623 if ( ad_dgAuthz
&& !BER_BVISEMPTY( id
) && !be_isroot( op
)
624 && backend_attribute( &o
, NULL
, &o
.o_req_ndn
,
625 ad_dgAuthz
, &authz
, ACL_READ
) == LDAP_SUCCESS
)
628 rs
->sr_err
= slap_sasl_matches( op
, authz
,
629 &o
.o_ndn
, &o
.o_ndn
);
630 ber_bvarray_free_x( authz
, op
->o_tmpmemctx
);
631 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
638 o
.o_groups
= NULL
; /* authz changed, invalidate cached groups */
641 rs
->sr_err
= backend_group( &o
, NULL
, &o
.o_req_ndn
,
642 &o
.oq_compare
.rs_ava
->aa_value
, dli
->dli_oc
, dli
->dli_ad
);
643 switch ( rs
->sr_err
) {
645 rs
->sr_err
= LDAP_COMPARE_TRUE
;
648 case LDAP_NO_SUCH_OBJECT
:
649 /* NOTE: backend_group() returns noSuchObject
650 * if op_ndn does not exist; however, since
651 * dynamic list expansion means that the
652 * member attribute is virtually present, the
653 * non-existence of the asserted value implies
654 * the assertion is FALSE rather than
656 rs
->sr_err
= LDAP_COMPARE_FALSE
;
661 if ( id
) ber_bvarray_free_x( id
, o
.o_tmpmemctx
);
663 return SLAP_CB_CONTINUE
;
667 if ( overlay_entry_get_ov( &o
, &o
.o_req_ndn
, NULL
, NULL
, 0, &e
, on
) !=
668 LDAP_SUCCESS
|| e
== NULL
)
670 return SLAP_CB_CONTINUE
;
673 if ( ad_dgIdentity
) {
674 Attribute
*id
= attrs_find( e
->e_attrs
, ad_dgIdentity
);
678 /* if not rootdn and dgAuthz is present,
679 * check if user can be authorized as dgIdentity */
680 if ( ad_dgAuthz
&& !BER_BVISEMPTY( &id
->a_nvals
[0] ) && !be_isroot( op
)
681 && ( authz
= attrs_find( e
->e_attrs
, ad_dgAuthz
) ) )
683 if ( slap_sasl_matches( op
, authz
->a_nvals
,
684 &o
.o_ndn
, &o
.o_ndn
) != LDAP_SUCCESS
)
690 o
.o_dn
= id
->a_vals
[0];
691 o
.o_ndn
= id
->a_nvals
[0];
696 dli
= (dynlist_info_t
*)on
->on_bi
.bi_private
;
697 for ( ; dli
!= NULL
&& rs
->sr_err
!= LDAP_COMPARE_TRUE
; dli
= dli
->dli_next
) {
700 SlapReply r
= { REP_SEARCH
};
703 dynlist_sc_t dlc
= { 0 };
705 if ( !is_entry_objectclass_or_sub( e
, dli
->dli_oc
))
708 /* if the entry has the right objectClass, generate
709 * the dynamic list and compare */
711 cb
.sc_private
= &dlc
;
712 cb
.sc_response
= dynlist_sc_save_entry
;
713 cb
.sc_cleanup
= NULL
;
717 o
.o_tag
= LDAP_REQ_SEARCH
;
719 o
.ors_tlimit
= SLAP_NO_LIMIT
;
720 o
.ors_slimit
= SLAP_NO_LIMIT
;
722 o
.o_bd
= select_backend( &o
.o_req_ndn
, 1 );
723 if ( !o
.o_bd
|| !o
.o_bd
->be_search
) {
727 o
.ors_filterstr
= *slap_filterstr_objectClass_pres
;
728 o
.ors_filter
= (Filter
*) slap_filter_objectClass_pres
;
730 o
.ors_scope
= LDAP_SCOPE_BASE
;
731 o
.ors_deref
= LDAP_DEREF_NEVER
;
732 an
[0].an_name
= op
->orc_ava
->aa_desc
->ad_cname
;
733 an
[0].an_desc
= op
->orc_ava
->aa_desc
;
734 BER_BVZERO( &an
[1].an_name
);
738 o
.o_acl_priv
= ACL_COMPARE
;
740 rc
= o
.o_bd
->be_search( &o
, &r
);
742 if ( o
.o_dn
.bv_val
!= op
->o_dn
.bv_val
) {
743 slap_op_groups_free( &o
);
750 if ( dlc
.dlc_e
!= NULL
) {
751 r
.sr_entry
= dlc
.dlc_e
;
754 if ( r
.sr_err
!= LDAP_SUCCESS
|| r
.sr_entry
== NULL
) {
759 for ( a
= attrs_find( r
.sr_entry
->e_attrs
, op
->orc_ava
->aa_desc
);
761 a
= attrs_find( a
->a_next
, op
->orc_ava
->aa_desc
) )
763 /* if we're here, we got a match... */
764 rs
->sr_err
= LDAP_COMPARE_FALSE
;
766 if ( attr_valfind( a
,
767 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH
|
768 SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
,
769 &op
->orc_ava
->aa_value
, NULL
, op
->o_tmpmemctx
) == 0 )
771 rs
->sr_err
= LDAP_COMPARE_TRUE
;
776 if ( r
.sr_flags
& REP_ENTRY_MUSTBEFREED
) {
777 entry_free( r
.sr_entry
);
783 overlay_entry_release_ov( op
, e
, 0, on
);
786 return SLAP_CB_CONTINUE
;
790 dynlist_response( Operation
*op
, SlapReply
*rs
)
794 switch ( op
->o_tag
) {
795 case LDAP_REQ_SEARCH
:
796 if ( rs
->sr_type
== REP_SEARCH
&& !get_manageDSAit( op
) )
800 for ( dli
= dynlist_is_dynlist_next( op
, rs
, NULL
);
802 dli
= dynlist_is_dynlist_next( op
, rs
, dli
) )
804 rc
= dynlist_prepare_entry( op
, rs
, dli
);
807 if ( rc
!= LDAP_OTHER
) {
813 case LDAP_REQ_COMPARE
:
814 switch ( rs
->sr_err
) {
815 /* NOTE: we waste a few cycles running the dynamic list
816 * also when the result is FALSE, which occurs if the
817 * dynamic entry itself contains the AVA attribute */
818 /* FIXME: this approach is less than optimal; a dedicated
819 * compare op should be implemented, that fetches the
820 * entry, checks if it has the appropriate objectClass
821 * and, in case, runs a compare thru all the URIs,
822 * stopping at the first positive occurrence; see ITS#3756 */
823 case LDAP_COMPARE_FALSE
:
824 case LDAP_NO_SUCH_ATTRIBUTE
:
825 return dynlist_compare( op
, rs
);
833 return SLAP_CB_CONTINUE
;
837 dynlist_build_def_filter( dynlist_info_t
*dli
)
841 dli
->dli_default_filter
.bv_len
= STRLENOF( "(!(objectClass=" "))" )
842 + dli
->dli_oc
->soc_cname
.bv_len
;
843 dli
->dli_default_filter
.bv_val
= ch_malloc( dli
->dli_default_filter
.bv_len
+ 1 );
844 if ( dli
->dli_default_filter
.bv_val
== NULL
) {
845 Debug( LDAP_DEBUG_ANY
, "dynlist_db_open: malloc failed.\n",
850 ptr
= lutil_strcopy( dli
->dli_default_filter
.bv_val
, "(!(objectClass=" );
851 ptr
= lutil_strcopy( ptr
, dli
->dli_oc
->soc_cname
.bv_val
);
852 ptr
= lutil_strcopy( ptr
, "))" );
854 assert( dli
->dli_default_filter
.bv_len
== ptr
- dli
->dli_default_filter
.bv_val
);
868 slap_overinst
*on
= (slap_overinst
*)be
->bd_info
;
872 if ( strcasecmp( argv
[0], "dynlist-attrset" ) == 0 ) {
873 dynlist_info_t
**dlip
;
875 AttributeDescription
*ad
= NULL
,
877 dynlist_map_t
*dlm
= NULL
;
881 Debug( LDAP_DEBUG_ANY
, "%s: line %d: " DYNLIST_USAGE
882 "invalid arg number #%d.\n",
883 fname
, lineno
, argc
);
887 oc
= oc_find( argv
[1] );
889 Debug( LDAP_DEBUG_ANY
, "%s: line %d: " DYNLIST_USAGE
890 "unable to find ObjectClass \"%s\"\n",
891 fname
, lineno
, argv
[ 1 ] );
895 rc
= slap_str2ad( argv
[2], &ad
, &text
);
896 if ( rc
!= LDAP_SUCCESS
) {
897 Debug( LDAP_DEBUG_ANY
, "%s: line %d: " DYNLIST_USAGE
898 "unable to find AttributeDescription \"%s\"\n",
899 fname
, lineno
, argv
[2] );
903 if ( !is_at_subtype( ad
->ad_type
, slap_schema
.si_ad_labeledURI
->ad_type
) ) {
904 Debug( LDAP_DEBUG_ANY
, "%s: line %d: " DYNLIST_USAGE
905 "AttributeDescription \"%s\" "
906 "must be a subtype of \"labeledURI\"\n",
907 fname
, lineno
, argv
[2] );
911 for ( i
= 3; i
< argc
; i
++ ) {
914 AttributeDescription
*member_ad
= NULL
;
915 AttributeDescription
*mapped_ad
= NULL
;
921 * If no mapped attribute is given, dn is used
922 * for backward compatibility.
925 if ( cp
= strchr( arg
, (int)':' ) != NULL
) {
927 ber_str2bv( arg
, cp
- arg
, 0, &bv
);
928 rc
= slap_bv2ad( &bv
, &mapped_ad
, &text
);
929 if ( rc
!= LDAP_SUCCESS
) {
930 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
932 "unable to find mapped AttributeDescription \"%s\"\n",
933 fname
, lineno
, arg
);
940 rc
= slap_str2ad( arg
, &member_ad
, &text
);
941 if ( rc
!= LDAP_SUCCESS
) {
942 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
944 "unable to find AttributeDescription \"%s\"\n",
945 fname
, lineno
, arg
);
949 dlmp
= (dynlist_map_t
*)ch_calloc( 1, sizeof( dynlist_map_t
) );
954 dlmp
->dlm_member_ad
= member_ad
;
955 dlmp
->dlm_mapped_ad
= mapped_ad
;
956 dlmp
->dlm_next
= NULL
;
959 dlml
->dlm_next
= dlmp
;
963 for ( dlip
= (dynlist_info_t
**)&on
->on_bi
.bi_private
;
964 *dlip
; dlip
= &(*dlip
)->dli_next
)
967 * The same URL attribute / member attribute pair
968 * cannot be repeated, but we enforce this only
969 * when the member attribute is unique. Performing
970 * the check for multiple values would require
971 * sorting and comparing the lists, which is left
972 * as a future improvement
974 if ( (*dlip
)->dli_ad
== ad
&&
975 (*dlip
)->dli_dlm
->dlm_next
== NULL
&&
976 dlm
->dlm_next
== NULL
&&
977 dlm
->dlm_member_ad
== (*dlip
)->dli_dlm
->dlm_member_ad
&&
978 dlm
->dlm_mapped_ad
== (*dlip
)->dli_dlm
->dlm_mapped_ad
) {
979 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
981 "URL attributeDescription \"%s\" already mapped.\n",
982 fname
, lineno
, ad
->ad_cname
.bv_val
);
984 /* make it a warning... */
990 *dlip
= (dynlist_info_t
*)ch_calloc( 1, sizeof( dynlist_info_t
) );
991 (*dlip
)->dli_oc
= oc
;
992 (*dlip
)->dli_ad
= ad
;
993 (*dlip
)->dli_dlm
= dlm
;
995 if ( dynlist_build_def_filter( *dlip
) ) {
996 dynlist_map_t
*dlm
= (*dlip
)->ldi_dlm
;
997 dynlist_map_t
*dlm_next
;
999 while ( dlm
!= NULL
) {
1000 dlm_next
= dlm
->dlm_next
;
1010 /* allow dyngroup syntax */
1011 } else if ( strcasecmp( argv
[0], "dynlist-attrpair" ) == 0 ) {
1012 dynlist_info_t
**dlip
;
1014 AttributeDescription
*ad
= NULL
,
1019 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
1020 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1021 "invalid arg number #%d.\n",
1022 fname
, lineno
, argc
);
1026 oc
= oc_find( "groupOfURLs" );
1028 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
1029 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1030 "unable to find default ObjectClass \"groupOfURLs\"\n",
1035 rc
= slap_str2ad( argv
[1], &member_ad
, &text
);
1036 if ( rc
!= LDAP_SUCCESS
) {
1037 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
1038 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1039 "unable to find AttributeDescription \"%s\"\n",
1040 fname
, lineno
, argv
[1] );
1044 rc
= slap_str2ad( argv
[2], &ad
, &text
);
1045 if ( rc
!= LDAP_SUCCESS
) {
1046 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
1047 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1048 "unable to find AttributeDescription \"%s\"\n",
1049 fname
, lineno
, argv
[2] );
1053 if ( !is_at_subtype( ad
->ad_type
, slap_schema
.si_ad_labeledURI
->ad_type
) ) {
1054 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
1055 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1056 "AttributeDescription \"%s\" "
1057 "must be a subtype of \"labeledURI\"\n",
1058 fname
, lineno
, argv
[2] );
1062 for ( dlip
= (dynlist_info_t
**)&on
->on_bi
.bi_private
;
1063 *dlip
; dlip
= &(*dlip
)->dli_next
)
1066 * The same URL attribute / member attribute pair
1067 * cannot be repeated, but we enforce this only
1068 * when the member attribute is unique. Performing
1069 * the check for multiple values would require
1070 * sorting and comparing the lists, which is left
1071 * as a future improvement
1073 if ( (*dlip
)->dli_ad
== ad
&&
1074 (*dlip
)->dli_dlm
->dlm_next
== NULL
&&
1075 member_ad
== (*dlip
)->dli_dlm
->dlm_member_ad
) {
1076 Debug( LDAP_DEBUG_ANY
, "%s: line %d: "
1077 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1078 "URL attributeDescription \"%s\" already mapped.\n",
1079 fname
, lineno
, ad
->ad_cname
.bv_val
);
1081 /* make it a warning... */
1087 *dlip
= (dynlist_info_t
*)ch_calloc( 1, sizeof( dynlist_info_t
) );
1088 (*dlip
)->dli_oc
= oc
;
1089 (*dlip
)->dli_ad
= ad
;
1090 (*dlip
)->dli_dlm
= (dynlist_map_t
*)ch_calloc( 1, sizeof( dynlist_map_t
) );
1091 (*dlip
)->dli_dlm
->dlm_member_ad
= member_ad
;
1092 (*dlip
)->dli_dlm
->dlm_mapped_ad
= NULL
;
1094 if ( dynlist_build_def_filter( *dlip
) ) {
1095 ch_free( (*dlip
)->dli_dlm
);
1102 rc
= SLAP_CONF_UNKNOWN
;
1116 static ConfigDriver dl_cfgen
;
1118 /* XXXmanu 255 is the maximum arguments we allow. Can we go beyond? */
1119 static ConfigTable dlcfg
[] = {
1120 { "dynlist-attrset", "group-oc> <URL-ad> <member-ad",
1121 3, 255, 0, ARG_MAGIC
|DL_ATTRSET
, dl_cfgen
,
1122 "( OLcfgOvAt:8.1 NAME 'olcDLattrSet' "
1123 "DESC 'Dynamic list: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
1124 "EQUALITY caseIgnoreMatch "
1125 "SYNTAX OMsDirectoryString "
1126 "X-ORDERED 'VALUES' )",
1128 { "dynlist-attrpair", "member-ad> <URL-ad",
1129 3, 3, 0, ARG_MAGIC
|DL_ATTRPAIR
, dl_cfgen
,
1131 #ifdef TAKEOVER_DYNGROUP
1132 { "attrpair", "member-ad> <URL-ad",
1133 3, 3, 0, ARG_MAGIC
|DL_ATTRPAIR_COMPAT
, dl_cfgen
,
1136 { NULL
, NULL
, 0, 0, 0, ARG_IGNORED
}
1139 static ConfigOCs dlocs
[] = {
1140 { "( OLcfgOvOc:8.1 "
1141 "NAME 'olcDynamicList' "
1142 "DESC 'Dynamic list configuration' "
1143 "SUP olcOverlayConfig "
1144 "MAY olcDLattrSet )",
1145 Cft_Overlay
, dlcfg
, NULL
, NULL
},
1150 dl_cfgen( ConfigArgs
*c
)
1152 slap_overinst
*on
= (slap_overinst
*)c
->bi
;
1153 dynlist_info_t
*dli
= (dynlist_info_t
*)on
->on_bi
.bi_private
;
1157 if ( c
->op
== SLAP_CONFIG_EMIT
) {
1160 for ( i
= 0; dli
; i
++, dli
= dli
->dli_next
) {
1162 char *ptr
= c
->cr_msg
;
1165 assert( dli
->dli_oc
!= NULL
);
1166 assert( dli
->dli_ad
!= NULL
);
1168 ptr
+= snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1169 SLAP_X_ORDERED_FMT
"%s %s", i
,
1170 dli
->dli_oc
->soc_cname
.bv_val
,
1171 dli
->dli_ad
->ad_cname
.bv_val
);
1173 for ( dlm
= dli
->dli_dlm
; dlm
; dlm
= dlm
->dlm_next
) {
1176 if ( dlm
->dlm_mapped_ad
) {
1177 ptr
= lutil_strcopy( ptr
, dlm
->dlm_mapped_ad
->ad_cname
.bv_val
);
1182 ptr
= lutil_strcopy( ptr
, dlm
->dlm_member_ad
->ad_cname
.bv_val
);
1185 bv
.bv_val
= c
->cr_msg
;
1186 bv
.bv_len
= ptr
- bv
.bv_val
;
1187 value_add_one( &c
->rvalue_vals
, &bv
);
1191 case DL_ATTRPAIR_COMPAT
:
1203 } else if ( c
->op
== LDAP_MOD_DELETE
) {
1206 if ( c
->valx
< 0 ) {
1207 dynlist_info_t
*dli_next
;
1209 for ( dli_next
= dli
; dli_next
; dli
= dli_next
) {
1210 dynlist_map_t
*dlm
= dli
->dli_dlm
;
1211 dynlist_map_t
*dlm_next
;
1213 dli_next
= dli
->dli_next
;
1215 ch_free( dli
->dli_default_filter
.bv_val
);
1217 while ( dlm
!= NULL
) {
1218 dlm_next
= dlm
->dlm_next
;
1225 on
->on_bi
.bi_private
= NULL
;
1228 dynlist_info_t
**dlip
;
1230 dynlist_map_t
*dlm_next
;
1232 for ( i
= 0, dlip
= (dynlist_info_t
**)&on
->on_bi
.bi_private
;
1235 if ( *dlip
== NULL
) {
1238 dlip
= &(*dlip
)->dli_next
;
1242 *dlip
= dli
->dli_next
;
1243 ch_free( dli
->dli_default_filter
.bv_val
);
1246 while ( dlm
!= NULL
) {
1247 dlm_next
= dlm
->dlm_next
;
1253 dli
= (dynlist_info_t
*)on
->on_bi
.bi_private
;
1257 case DL_ATTRPAIR_COMPAT
:
1272 dynlist_info_t
**dlip
,
1274 ObjectClass
*oc
= NULL
;
1275 AttributeDescription
*ad
= NULL
;
1276 dynlist_map_t
*dlm
= NULL
;
1279 oc
= oc_find( c
->argv
[ 1 ] );
1281 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), DYNLIST_USAGE
1282 "unable to find ObjectClass \"%s\"",
1284 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1285 c
->log
, c
->cr_msg
, 0 );
1289 rc
= slap_str2ad( c
->argv
[ 2 ], &ad
, &text
);
1290 if ( rc
!= LDAP_SUCCESS
) {
1291 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), DYNLIST_USAGE
1292 "unable to find AttributeDescription \"%s\"",
1294 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1295 c
->log
, c
->cr_msg
, 0 );
1299 if ( !is_at_subtype( ad
->ad_type
, slap_schema
.si_ad_labeledURI
->ad_type
) ) {
1300 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), DYNLIST_USAGE
1301 "AttributeDescription \"%s\" "
1302 "must be a subtype of \"labeledURI\"",
1304 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1305 c
->log
, c
->cr_msg
, 0 );
1309 for ( i
= 3; i
< c
->argc
; i
++ ) {
1312 AttributeDescription
*member_ad
= NULL
;
1313 AttributeDescription
*mapped_ad
= NULL
;
1314 dynlist_map_t
*dlmp
;
1315 dynlist_map_t
*dlml
;
1319 * If no mapped attribute is given, dn is used
1320 * for backward compatibility.
1323 if ( ( cp
= strchr( arg
, ':' ) ) != NULL
) {
1325 ber_str2bv( arg
, cp
- arg
, 0, &bv
);
1326 rc
= slap_bv2ad( &bv
, &mapped_ad
, &text
);
1327 if ( rc
!= LDAP_SUCCESS
) {
1328 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1330 "unable to find mapped AttributeDescription #%d \"%s\"\n",
1331 i
- 3, c
->argv
[ i
] );
1332 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1333 c
->log
, c
->cr_msg
, 0 );
1339 rc
= slap_str2ad( arg
, &member_ad
, &text
);
1340 if ( rc
!= LDAP_SUCCESS
) {
1341 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1343 "unable to find AttributeDescription #%d \"%s\"\n",
1344 i
- 3, c
->argv
[ i
] );
1345 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1346 c
->log
, c
->cr_msg
, 0 );
1350 dlmp
= (dynlist_map_t
*)ch_calloc( 1, sizeof( dynlist_map_t
) );
1351 if ( dlm
== NULL
) {
1355 dlmp
->dlm_member_ad
= member_ad
;
1356 dlmp
->dlm_mapped_ad
= mapped_ad
;
1357 dlmp
->dlm_next
= NULL
;
1360 dlml
->dlm_next
= dlmp
;
1364 if ( c
->valx
> 0 ) {
1367 for ( i
= 0, dlip
= (dynlist_info_t
**)&on
->on_bi
.bi_private
;
1370 if ( *dlip
== NULL
) {
1371 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1373 "invalid index {%d}\n",
1375 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1376 c
->log
, c
->cr_msg
, 0 );
1379 dlip
= &(*dlip
)->dli_next
;
1384 for ( dlip
= (dynlist_info_t
**)&on
->on_bi
.bi_private
;
1385 *dlip
; dlip
= &(*dlip
)->dli_next
)
1389 *dlip
= (dynlist_info_t
*)ch_calloc( 1, sizeof( dynlist_info_t
) );
1391 (*dlip
)->dli_oc
= oc
;
1392 (*dlip
)->dli_ad
= ad
;
1393 (*dlip
)->dli_dlm
= dlm
;
1394 (*dlip
)->dli_next
= dli_next
;
1396 rc
= dynlist_build_def_filter( *dlip
);
1400 case DL_ATTRPAIR_COMPAT
:
1401 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1402 "warning: \"attrpair\" only supported for limited "
1403 "backward compatibility with overlay \"dyngroup\"" );
1404 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n", c
->log
, c
->cr_msg
, 0 );
1408 dynlist_info_t
**dlip
;
1409 ObjectClass
*oc
= NULL
;
1410 AttributeDescription
*ad
= NULL
,
1414 oc
= oc_find( "groupOfURLs" );
1416 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1417 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1418 "unable to find default ObjectClass \"groupOfURLs\"" );
1419 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1420 c
->log
, c
->cr_msg
, 0 );
1424 rc
= slap_str2ad( c
->argv
[ 1 ], &member_ad
, &text
);
1425 if ( rc
!= LDAP_SUCCESS
) {
1426 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1427 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1428 "unable to find AttributeDescription \"%s\"",
1430 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1431 c
->log
, c
->cr_msg
, 0 );
1435 rc
= slap_str2ad( c
->argv
[ 2 ], &ad
, &text
);
1436 if ( rc
!= LDAP_SUCCESS
) {
1437 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1438 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1439 "unable to find AttributeDescription \"%s\"\n",
1441 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1442 c
->log
, c
->cr_msg
, 0 );
1446 if ( !is_at_subtype( ad
->ad_type
, slap_schema
.si_ad_labeledURI
->ad_type
) ) {
1447 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1449 "AttributeDescription \"%s\" "
1450 "must be a subtype of \"labeledURI\"",
1452 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1453 c
->log
, c
->cr_msg
, 0 );
1457 for ( dlip
= (dynlist_info_t
**)&on
->on_bi
.bi_private
;
1458 *dlip
; dlip
= &(*dlip
)->dli_next
)
1461 * The same URL attribute / member attribute pair
1462 * cannot be repeated, but we enforce this only
1463 * when the member attribute is unique. Performing
1464 * the check for multiple values would require
1465 * sorting and comparing the lists, which is left
1466 * as a future improvement
1468 if ( (*dlip
)->dli_ad
== ad
&&
1469 (*dlip
)->dli_dlm
->dlm_next
== NULL
&&
1470 member_ad
== (*dlip
)->dli_dlm
->dlm_member_ad
) {
1471 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1472 "\"dynlist-attrpair <member-ad> <URL-ad>\": "
1473 "URL attributeDescription \"%s\" already mapped.\n",
1474 ad
->ad_cname
.bv_val
);
1475 Debug( LDAP_DEBUG_ANY
, "%s: %s.\n",
1476 c
->log
, c
->cr_msg
, 0 );
1478 /* make it a warning... */
1484 *dlip
= (dynlist_info_t
*)ch_calloc( 1, sizeof( dynlist_info_t
) );
1486 (*dlip
)->dli_oc
= oc
;
1487 (*dlip
)->dli_ad
= ad
;
1488 (*dlip
)->dli_dlm
= (dynlist_map_t
*)ch_calloc( 1, sizeof( dynlist_map_t
) );
1489 (*dlip
)->dli_dlm
->dlm_member_ad
= member_ad
;
1490 (*dlip
)->dli_dlm
->dlm_mapped_ad
= NULL
;
1492 rc
= dynlist_build_def_filter( *dlip
);
1510 slap_overinst
*on
= (slap_overinst
*) be
->bd_info
;
1511 dynlist_info_t
*dli
= (dynlist_info_t
*)on
->on_bi
.bi_private
;
1512 ObjectClass
*oc
= NULL
;
1513 AttributeDescription
*ad
= NULL
;
1517 if ( dli
== NULL
) {
1518 dli
= ch_calloc( 1, sizeof( dynlist_info_t
) );
1519 on
->on_bi
.bi_private
= (void *)dli
;
1522 for ( ; dli
; dli
= dli
->dli_next
) {
1523 if ( dli
->dli_oc
== NULL
) {
1525 oc
= oc_find( "groupOfURLs" );
1527 snprintf( cr
->msg
, sizeof( cr
->msg
),
1528 "unable to fetch objectClass \"groupOfURLs\"" );
1529 Debug( LDAP_DEBUG_ANY
, "dynlist_db_open: %s.\n", cr
->msg
, 0, 0 );
1537 if ( dli
->dli_ad
== NULL
) {
1539 rc
= slap_str2ad( "memberURL", &ad
, &text
);
1540 if ( rc
!= LDAP_SUCCESS
) {
1541 snprintf( cr
->msg
, sizeof( cr
->msg
),
1542 "unable to fetch attributeDescription \"memberURL\": %d (%s)",
1544 Debug( LDAP_DEBUG_ANY
, "dynlist_db_open: %s.\n", cr
->msg
, 0, 0 );
1552 if ( BER_BVISNULL( &dli
->dli_default_filter
) ) {
1553 rc
= dynlist_build_def_filter( dli
);
1560 if ( ad_dgIdentity
== NULL
) {
1561 rc
= slap_str2ad( "dgIdentity", &ad_dgIdentity
, &text
);
1562 if ( rc
!= LDAP_SUCCESS
) {
1563 snprintf( cr
->msg
, sizeof( cr
->msg
),
1564 "unable to fetch attributeDescription \"dgIdentity\": %d (%s)",
1566 Debug( LDAP_DEBUG_ANY
, "dynlist_db_open: %s\n", cr
->msg
, 0, 0 );
1567 /* Just a warning */
1571 if ( ad_dgAuthz
== NULL
) {
1572 rc
= slap_str2ad( "dgAuthz", &ad_dgAuthz
, &text
);
1573 if ( rc
!= LDAP_SUCCESS
) {
1574 snprintf( cr
->msg
, sizeof( cr
->msg
),
1575 "unable to fetch attributeDescription \"dgAuthz\": %d (%s)",
1577 Debug( LDAP_DEBUG_ANY
, "dynlist_db_open: %s\n", cr
->msg
, 0, 0 );
1578 /* Just a warning */
1590 slap_overinst
*on
= (slap_overinst
*) be
->bd_info
;
1592 if ( on
->on_bi
.bi_private
) {
1593 dynlist_info_t
*dli
= (dynlist_info_t
*)on
->on_bi
.bi_private
,
1596 for ( dli_next
= dli
; dli_next
; dli
= dli_next
) {
1598 dynlist_map_t
*dlm_next
;
1600 dli_next
= dli
->dli_next
;
1602 ch_free( dli
->dli_default_filter
.bv_val
);
1604 while ( dlm
!= NULL
) {
1605 dlm_next
= dlm
->dlm_next
;
1616 static slap_overinst dynlist
= { { NULL
} };
1617 #ifdef TAKEOVER_DYNGROUP
1618 static char *obsolete_names
[] = {
1624 #if SLAPD_OVER_DYNLIST == SLAPD_MOD_DYNAMIC
1626 #endif /* SLAPD_OVER_DYNLIST == SLAPD_MOD_DYNAMIC */
1628 dynlist_initialize(void)
1630 #ifndef OL_2_2_COMPAT
1634 dynlist
.on_bi
.bi_type
= "dynlist";
1636 #ifdef TAKEOVER_DYNGROUP
1637 /* makes dynlist incompatible with dyngroup */
1638 dynlist
.on_bi
.bi_obsolete_names
= obsolete_names
;
1641 #ifdef OL_2_2_COMPAT
1642 dynlist
.on_bi
.bi_db_config
= dynlist_db_config
;
1644 dynlist
.on_bi
.bi_db_config
= config_generic_wrapper
;
1646 dynlist
.on_bi
.bi_db_open
= dynlist_db_open
;
1647 dynlist
.on_bi
.bi_db_destroy
= dynlist_db_destroy
;
1649 dynlist
.on_response
= dynlist_response
;
1651 #ifndef OL_2_2_COMPAT
1652 dynlist
.on_bi
.bi_cf_ocs
= dlocs
;
1654 rc
= config_register_schema( dlcfg
, dlocs
);
1660 return overlay_register( &dynlist
);
1663 #if SLAPD_OVER_DYNLIST == SLAPD_MOD_DYNAMIC
1665 init_module( int argc
, char *argv
[] )
1667 return dynlist_initialize();
1671 #endif /* SLAPD_OVER_DYNLIST */