denyop.c revision 1.1 1 /* denyop.c - Denies operations */
2 /* $OpenLDAP: pkg/ldap/contrib/slapd-modules/denyop/denyop.c,v 1.2.2.3 2008/02/11 23:26:38 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 *
5 * Copyright 2004-2008 The OpenLDAP Foundation.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
11 *
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
15 */
16 /* ACKNOWLEDGEMENTS:
17 * This work was initially developed by Pierangelo Masarati for inclusion in
18 * OpenLDAP Software.
19 */
20
21 #include "portable.h"
22
23 #ifdef SLAPD_OVER_DENYOP
24
25 #include <stdio.h>
26
27 #include <ac/string.h>
28 #include <ac/socket.h>
29
30 #include "slap.h"
31
32 /* This overlay provides a quick'n'easy way to deny selected operations
33 * for a database whose backend implements the operations. It is intended
34 * to be less expensive than ACLs because its evaluation occurs before
35 * any backend specific operation is actually even initiated.
36 */
37
38 enum {
39 denyop_add = 0,
40 denyop_bind,
41 denyop_compare,
42 denyop_delete,
43 denyop_extended,
44 denyop_modify,
45 denyop_modrdn,
46 denyop_search,
47 denyop_unbind
48 } denyop_e;
49
50 typedef struct denyop_info {
51 int do_op[denyop_unbind + 1];
52 } denyop_info;
53
54 static int
55 denyop_func( Operation *op, SlapReply *rs )
56 {
57 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
58 denyop_info *oi = (denyop_info *)on->on_bi.bi_private;
59 int deny = 0;
60
61 switch( op->o_tag ) {
62 case LDAP_REQ_BIND:
63 deny = oi->do_op[denyop_bind];
64 break;
65
66 case LDAP_REQ_ADD:
67 deny = oi->do_op[denyop_add];
68 break;
69
70 case LDAP_REQ_DELETE:
71 deny = oi->do_op[denyop_delete];
72 break;
73
74 case LDAP_REQ_MODRDN:
75 deny = oi->do_op[denyop_modrdn];
76 break;
77
78 case LDAP_REQ_MODIFY:
79 deny = oi->do_op[denyop_modify];
80 break;
81
82 case LDAP_REQ_COMPARE:
83 deny = oi->do_op[denyop_compare];
84 break;
85
86 case LDAP_REQ_SEARCH:
87 deny = oi->do_op[denyop_search];
88 break;
89
90 case LDAP_REQ_EXTENDED:
91 deny = oi->do_op[denyop_extended];
92 break;
93
94 case LDAP_REQ_UNBIND:
95 deny = oi->do_op[denyop_unbind];
96 break;
97 }
98
99 if ( !deny ) {
100 return SLAP_CB_CONTINUE;
101 }
102
103 op->o_bd->bd_info = (BackendInfo *)on->on_info;
104 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
105 "operation not allowed within namingContext" );
106
107 return 0;
108 }
109
110 static int
111 denyop_over_init(
112 BackendDB *be
113 )
114 {
115 slap_overinst *on = (slap_overinst *) be->bd_info;
116 denyop_info *oi;
117
118 oi = (denyop_info *)ch_malloc(sizeof(denyop_info));
119 memset(oi, 0, sizeof(denyop_info));
120 on->on_bi.bi_private = oi;
121
122 return 0;
123 }
124
125 static int
126 denyop_config(
127 BackendDB *be,
128 const char *fname,
129 int lineno,
130 int argc,
131 char **argv
132 )
133 {
134 slap_overinst *on = (slap_overinst *) be->bd_info;
135 denyop_info *oi = (denyop_info *)on->on_bi.bi_private;
136
137 if ( strcasecmp( argv[0], "denyop" ) == 0 ) {
138 char *op;
139
140 if ( argc != 2 ) {
141 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
142 "operation list missing in "
143 "\"denyop <op-list>\" line.\n",
144 fname, lineno, 0 );
145 return( 1 );
146 }
147
148 /* The on->on_bi.bi_private pointer can be used for
149 * anything this instance of the overlay needs.
150 */
151
152 op = argv[1];
153 do {
154 char *next = strchr( op, ',' );
155
156 if ( next ) {
157 next[0] = '\0';
158 next++;
159 }
160
161 if ( strcmp( op, "add" ) == 0 ) {
162 oi->do_op[denyop_add] = 1;
163
164 } else if ( strcmp( op, "bind" ) == 0 ) {
165 oi->do_op[denyop_bind] = 1;
166
167 } else if ( strcmp( op, "compare" ) == 0 ) {
168 oi->do_op[denyop_compare] = 1;
169
170 } else if ( strcmp( op, "delete" ) == 0 ) {
171 oi->do_op[denyop_delete] = 1;
172
173 } else if ( strcmp( op, "extended" ) == 0 ) {
174 oi->do_op[denyop_extended] = 1;
175
176 } else if ( strcmp( op, "modify" ) == 0 ) {
177 oi->do_op[denyop_modify] = 1;
178
179 } else if ( strcmp( op, "modrdn" ) == 0 ) {
180 oi->do_op[denyop_modrdn] = 1;
181
182 } else if ( strcmp( op, "search" ) == 0 ) {
183 oi->do_op[denyop_search] = 1;
184
185 } else if ( strcmp( op, "unbind" ) == 0 ) {
186 oi->do_op[denyop_unbind] = 1;
187
188 } else {
189 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
190 "unknown operation \"%s\" at "
191 "\"denyop <op-list>\" line.\n",
192 fname, lineno, op );
193 return( 1 );
194 }
195
196 op = next;
197 } while ( op );
198
199 } else {
200 return SLAP_CONF_UNKNOWN;
201 }
202 return 0;
203 }
204
205 static int
206 denyop_destroy(
207 BackendDB *be
208 )
209 {
210 slap_overinst *on = (slap_overinst *) be->bd_info;
211 denyop_info *oi = (denyop_info *)on->on_bi.bi_private;
212
213 if ( oi ) {
214 ch_free( oi );
215 }
216
217 return 0;
218 }
219
220 /* This overlay is set up for dynamic loading via moduleload. For static
221 * configuration, you'll need to arrange for the slap_overinst to be
222 * initialized and registered by some other function inside slapd.
223 */
224
225 static slap_overinst denyop;
226
227 int
228 denyop_initialize( void )
229 {
230 memset( &denyop, 0, sizeof( slap_overinst ) );
231 denyop.on_bi.bi_type = "denyop";
232 denyop.on_bi.bi_db_init = denyop_over_init;
233 denyop.on_bi.bi_db_config = denyop_config;
234 denyop.on_bi.bi_db_destroy = denyop_destroy;
235
236 denyop.on_bi.bi_op_bind = denyop_func;
237 denyop.on_bi.bi_op_search = denyop_func;
238 denyop.on_bi.bi_op_compare = denyop_func;
239 denyop.on_bi.bi_op_modify = denyop_func;
240 denyop.on_bi.bi_op_modrdn = denyop_func;
241 denyop.on_bi.bi_op_add = denyop_func;
242 denyop.on_bi.bi_op_delete = denyop_func;
243 denyop.on_bi.bi_extended = denyop_func;
244 denyop.on_bi.bi_op_unbind = denyop_func;
245
246 denyop.on_response = NULL /* denyop_response */ ;
247
248 return overlay_register( &denyop );
249 }
250
251 #if SLAPD_OVER_DENYOP == SLAPD_MOD_DYNAMIC
252 int
253 init_module( int argc, char *argv[] )
254 {
255 return denyop_initialize();
256 }
257 #endif /* SLAPD_OVER_DENYOP == SLAPD_MOD_DYNAMIC */
258
259 #endif /* defined(SLAPD_OVER_DENYOP) */
260