1 /* $NetBSD: denyop.c,v 1.3 2021/08/14 16:14:51 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-2021 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.3 2021/08/14 16:14:51 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