1 /* dyngroup.c - Demonstration of overlay code */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/overlays/dyngroup.c,v 1.10.2.3 2008/02/11 23:26:48 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2008 The OpenLDAP Foundation.
6 * Copyright 2003 by Howard Chu.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 * This work was initially developed by Howard Chu for inclusion in
24 #ifdef SLAPD_OVER_DYNGROUP
28 #include <ac/string.h>
29 #include <ac/socket.h>
35 /* This overlay extends the Compare operation to detect members of a
36 * dynamic group. It has no effect on any other operations. It must
37 * be configured with a pair of attributes to trigger on, e.g.
38 * attrpair member memberURL
39 * will cause compares on "member" to trigger a compare on "memberURL".
42 typedef struct adpair
{
43 struct adpair
*ap_next
;
44 AttributeDescription
*ap_mem
;
45 AttributeDescription
*ap_uri
;
48 static int dgroup_cf( ConfigArgs
*c
)
50 slap_overinst
*on
= (slap_overinst
*)c
->bi
;
54 case SLAP_CONFIG_EMIT
:
57 for ( ap
= on
->on_bi
.bi_private
; ap
; ap
= ap
->ap_next
) {
60 bv
.bv_len
= ap
->ap_mem
->ad_cname
.bv_len
+ 1 +
61 ap
->ap_uri
->ad_cname
.bv_len
;
62 bv
.bv_val
= ch_malloc( bv
.bv_len
+ 1 );
63 ptr
= lutil_strcopy( bv
.bv_val
, ap
->ap_mem
->ad_cname
.bv_val
);
65 strcpy( ptr
, ap
->ap_uri
->ad_cname
.bv_val
);
66 ber_bvarray_add( &c
->rvalue_vals
, &bv
);
72 if ( c
->valx
== -1 ) {
74 while (( ap
= on
->on_bi
.bi_private
)) {
75 on
->on_bi
.bi_private
= ap
->ap_next
;
81 app
= (adpair
**)&on
->on_bi
.bi_private
;
82 for (i
=0; i
<=c
->valx
; i
++, app
= &ap
->ap_next
) {
93 adpair ap
= { NULL
, NULL
, NULL
}, *a2
;
95 if ( slap_str2ad( c
->argv
[1], &ap
.ap_mem
, &text
) ) {
96 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "%s attribute description unknown: \"%s\"",
97 c
->argv
[0], c
->argv
[1] );
98 Debug( LDAP_DEBUG_CONFIG
|LDAP_DEBUG_NONE
,
99 "%s: %s\n", c
->log
, c
->cr_msg
, 0 );
102 if ( slap_str2ad( c
->argv
[2], &ap
.ap_uri
, &text
) ) {
103 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "%s attribute description unknown: \"%s\"",
104 c
->argv
[0], c
->argv
[2] );
105 Debug( LDAP_DEBUG_CONFIG
|LDAP_DEBUG_NONE
,
106 "%s: %s\n", c
->log
, c
->cr_msg
, 0 );
109 /* The on->on_bi.bi_private pointer can be used for
110 * anything this instance of the overlay needs.
112 a2
= ch_malloc( sizeof(adpair
) );
113 a2
->ap_next
= on
->on_bi
.bi_private
;
114 a2
->ap_mem
= ap
.ap_mem
;
115 a2
->ap_uri
= ap
.ap_uri
;
116 on
->on_bi
.bi_private
= a2
;
123 static ConfigTable dgroupcfg
[] = {
124 { "attrpair", "member-attribute> <URL-attribute", 3, 3, 0,
125 ARG_MAGIC
, dgroup_cf
,
126 "( OLcfgOvAt:17.1 NAME 'olcDGAttrPair' "
127 "DESC 'Member and MemberURL attribute pair' "
128 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
129 { NULL
, NULL
, 0, 0, 0, ARG_IGNORED
}
132 static ConfigOCs dgroupocs
[] = {
133 { "( OLcfgOvOc:17.1 "
134 "NAME 'olcDGConfig' "
135 "DESC 'Dynamic Group configuration' "
136 "SUP olcOverlayConfig "
137 "MAY olcDGAttrPair )",
138 Cft_Overlay
, dgroupcfg
},
143 dyngroup_response( Operation
*op
, SlapReply
*rs
)
145 slap_overinst
*on
= (slap_overinst
*) op
->o_bd
->bd_info
;
146 adpair
*ap
= on
->on_bi
.bi_private
;
148 /* If we've been configured and the current response is
149 * what we're looking for...
151 if ( ap
&& op
->o_tag
== LDAP_REQ_COMPARE
&&
152 rs
->sr_err
== LDAP_NO_SUCH_ATTRIBUTE
) {
154 for (;ap
;ap
=ap
->ap_next
) {
155 if ( op
->oq_compare
.rs_ava
->aa_desc
== ap
->ap_mem
) {
156 /* This compare is for one of the attributes we're
157 * interested in. We'll use slapd's existing dyngroup
158 * evaluator to get the answer we want.
160 int cache
= op
->o_do_not_cache
;
162 op
->o_do_not_cache
= 1;
163 rs
->sr_err
= backend_group( op
, NULL
, &op
->o_req_ndn
,
164 &op
->oq_compare
.rs_ava
->aa_value
, NULL
, ap
->ap_uri
);
165 op
->o_do_not_cache
= cache
;
166 switch ( rs
->sr_err
) {
168 rs
->sr_err
= LDAP_COMPARE_TRUE
;
171 case LDAP_NO_SUCH_OBJECT
:
172 rs
->sr_err
= LDAP_COMPARE_FALSE
;
179 /* Default is to just fall through to the normal processing */
180 return SLAP_CB_CONTINUE
;
189 slap_overinst
*on
= (slap_overinst
*) be
->bd_info
;
192 for ( ap
= on
->on_bi
.bi_private
; ap
; ap
= a2
) {
199 static slap_overinst dyngroup
;
201 /* This overlay is set up for dynamic loading via moduleload. For static
202 * configuration, you'll need to arrange for the slap_overinst to be
203 * initialized and registered by some other function inside slapd.
206 int dyngroup_initialize() {
209 dyngroup
.on_bi
.bi_type
= "dyngroup";
210 dyngroup
.on_bi
.bi_db_close
= dyngroup_close
;
211 dyngroup
.on_response
= dyngroup_response
;
213 dyngroup
.on_bi
.bi_cf_ocs
= dgroupocs
;
214 code
= config_register_schema( dgroupcfg
, dgroupocs
);
215 if ( code
) return code
;
217 return overlay_register( &dyngroup
);
220 #if SLAPD_OVER_DYNGROUP == SLAPD_MOD_DYNAMIC
222 init_module( int argc
, char *argv
[] )
224 return dyngroup_initialize();
228 #endif /* defined(SLAPD_OVER_DYNGROUP) */