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