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