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