Home | History | Annotate | Line # | Download | only in denyop
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