]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/dyngroup.c
happy new year
[openldap] / servers / slapd / overlays / dyngroup.c
1 /* dyngroup.c - Demonstration of overlay code */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2007 The OpenLDAP Foundation.
6  * Copyright 2003 by Howard Chu.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
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>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Howard Chu for inclusion in
19  * OpenLDAP Software.
20  */
21
22 #include "portable.h"
23
24 #ifdef SLAPD_OVER_DYNGROUP
25
26 #include <stdio.h>
27
28 #include <ac/string.h>
29 #include <ac/socket.h>
30
31 #include "slap.h"
32
33 /* This overlay extends the Compare operation to detect members of a
34  * dynamic group. It has no effect on any other operations. It must
35  * be configured with a pair of attributes to trigger on, e.g.
36  *      attrpair member memberURL
37  * will cause compares on "member" to trigger a compare on "memberURL".
38  */
39
40 typedef struct adpair {
41         struct adpair *ap_next;
42         AttributeDescription *ap_mem;
43         AttributeDescription *ap_uri;
44 } adpair;
45
46 static int
47 dyngroup_response( Operation *op, SlapReply *rs )
48 {
49         slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
50         adpair *ap = on->on_bi.bi_private;
51
52         /* If we've been configured and the current response is
53          * what we're looking for...
54          */
55         if ( ap && op->o_tag == LDAP_REQ_COMPARE &&
56                 rs->sr_err == LDAP_NO_SUCH_ATTRIBUTE ) {
57
58                 for (;ap;ap=ap->ap_next) {
59                         if ( op->oq_compare.rs_ava->aa_desc == ap->ap_mem ) {
60                                 /* This compare is for one of the attributes we're
61                                  * interested in. We'll use slapd's existing dyngroup
62                                  * evaluator to get the answer we want.
63                                  */
64                                 int cache = op->o_do_not_cache;
65                                 
66                                 op->o_do_not_cache = 1;
67                                 rs->sr_err = backend_group( op, NULL, &op->o_req_ndn,
68                                         &op->oq_compare.rs_ava->aa_value, NULL, ap->ap_uri );
69                                 op->o_do_not_cache = cache;
70                                 switch ( rs->sr_err ) {
71                                 case LDAP_SUCCESS:
72                                         rs->sr_err = LDAP_COMPARE_TRUE;
73                                         break;
74
75                                 case LDAP_NO_SUCH_OBJECT:
76                                         rs->sr_err = LDAP_COMPARE_FALSE;
77                                         break;
78                                 }
79                                 break;
80                         }
81                 }
82         }
83         /* Default is to just fall through to the normal processing */
84         return SLAP_CB_CONTINUE;
85 }
86
87 static int dyngroup_config(
88     BackendDB   *be,
89     const char  *fname,
90     int         lineno,
91     int         argc,
92     char        **argv
93 )
94 {
95         slap_overinst *on = (slap_overinst *) be->bd_info;
96         adpair ap = { NULL, NULL, NULL }, *a2;
97
98         if ( strcasecmp( argv[0], "attrpair" ) == 0 ) {
99                 const char *text;
100                 if ( argc != 3 ) {
101                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
102                                 "attribute description missing in "
103                                 "\"attrpair <member-attribute> <URL-attribute>\" line.\n",
104                                 fname, lineno, 0 );
105                 return( 1 );
106                 }
107                 if ( slap_str2ad( argv[1], &ap.ap_mem, &text ) ) {
108                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
109                                 "attribute description unknown \"attrpair\" line: %s.\n",
110                                 fname, lineno, text );
111                         return( 1 );
112                 }
113                 if ( slap_str2ad( argv[2], &ap.ap_uri, &text ) ) {
114                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
115                                 "attribute description unknown \"attrpair\" line: %s.\n",
116                                 fname, lineno, text );
117                         return( 1 );
118                 }
119                 /* The on->on_bi.bi_private pointer can be used for
120                  * anything this instance of the overlay needs.
121                  */
122
123                 a2 = ch_malloc( sizeof(adpair) );
124                 a2->ap_next = on->on_bi.bi_private;
125                 a2->ap_mem = ap.ap_mem;
126                 a2->ap_uri = ap.ap_uri;
127                 on->on_bi.bi_private = a2;
128         } else {
129                 return SLAP_CONF_UNKNOWN;
130         }
131         return 0;
132 }
133
134 static int
135 dyngroup_close(
136         BackendDB *be
137 )
138 {
139         slap_overinst *on = (slap_overinst *) be->bd_info;
140         adpair *ap, *a2;
141
142         for ( ap = on->on_bi.bi_private; ap; ap = a2 ) {
143                 a2 = ap->ap_next;
144                 ch_free( ap );
145         }
146         return 0;
147 }
148
149 static slap_overinst dyngroup;
150
151 /* This overlay is set up for dynamic loading via moduleload. For static
152  * configuration, you'll need to arrange for the slap_overinst to be
153  * initialized and registered by some other function inside slapd.
154  */
155
156 int dyngroup_initialize() {
157         dyngroup.on_bi.bi_type = "dyngroup";
158         dyngroup.on_bi.bi_db_config = dyngroup_config;
159         dyngroup.on_bi.bi_db_close = dyngroup_close;
160         dyngroup.on_response = dyngroup_response;
161
162         return overlay_register( &dyngroup );
163 }
164
165 #if SLAPD_OVER_DYNGROUP == SLAPD_MOD_DYNAMIC
166 int
167 init_module( int argc, char *argv[] )
168 {
169         return dyngroup_initialize();
170 }
171 #endif
172
173 #endif /* defined(SLAPD_OVER_DYNGROUP) */