1/* denyop.c - Denies operations */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 2004-2011 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 38enum { 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 50typedef struct denyop_info { 51 int do_op[denyop_unbind + 1]; 52} denyop_info; 53 54static int 55denyop_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 110static int 111denyop_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 125static int 126denyop_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 205static int 206denyop_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 225static slap_overinst denyop; 226 227int 228denyop_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 252int 253init_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