]> git.sur5r.net Git - openldap/blob - contrib/slapd-modules/denyop/denyop.c
Happy New Year
[openldap] / contrib / slapd-modules / denyop / denyop.c
1 /* denyop.c - Denies operations */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2004-2018 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, ConfigReply *cr
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, ConfigReply *cr
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) */