Home | History | Annotate | Line # | Download | only in denyop
      1 /*	$NetBSD: denyop.c,v 1.4 2025/09/05 21:16:16 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-2024 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.4 2025/09/05 21:16:16 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
     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
    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
    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
    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
    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
    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