diff options
Diffstat (limited to 'contrib/slapd-modules/denyop/denyop.c')
-rw-r--r-- | contrib/slapd-modules/denyop/denyop.c | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/contrib/slapd-modules/denyop/denyop.c b/contrib/slapd-modules/denyop/denyop.c new file mode 100644 index 0000000..dd3e13c --- /dev/null +++ b/contrib/slapd-modules/denyop/denyop.c @@ -0,0 +1,260 @@ +/* denyop.c - Denies operations */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 2004-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ +/* ACKNOWLEDGEMENTS: + * This work was initially developed by Pierangelo Masarati for inclusion in + * OpenLDAP Software. + */ + +#include "portable.h" + +#ifdef SLAPD_OVER_DENYOP + +#include <stdio.h> + +#include <ac/string.h> +#include <ac/socket.h> + +#include "slap.h" + +/* This overlay provides a quick'n'easy way to deny selected operations + * for a database whose backend implements the operations. It is intended + * to be less expensive than ACLs because its evaluation occurs before + * any backend specific operation is actually even initiated. + */ + +enum { + denyop_add = 0, + denyop_bind, + denyop_compare, + denyop_delete, + denyop_extended, + denyop_modify, + denyop_modrdn, + denyop_search, + denyop_unbind +} denyop_e; + +typedef struct denyop_info { + int do_op[denyop_unbind + 1]; +} denyop_info; + +static int +denyop_func( Operation *op, SlapReply *rs ) +{ + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + denyop_info *oi = (denyop_info *)on->on_bi.bi_private; + int deny = 0; + + switch( op->o_tag ) { + case LDAP_REQ_BIND: + deny = oi->do_op[denyop_bind]; + break; + + case LDAP_REQ_ADD: + deny = oi->do_op[denyop_add]; + break; + + case LDAP_REQ_DELETE: + deny = oi->do_op[denyop_delete]; + break; + + case LDAP_REQ_MODRDN: + deny = oi->do_op[denyop_modrdn]; + break; + + case LDAP_REQ_MODIFY: + deny = oi->do_op[denyop_modify]; + break; + + case LDAP_REQ_COMPARE: + deny = oi->do_op[denyop_compare]; + break; + + case LDAP_REQ_SEARCH: + deny = oi->do_op[denyop_search]; + break; + + case LDAP_REQ_EXTENDED: + deny = oi->do_op[denyop_extended]; + break; + + case LDAP_REQ_UNBIND: + deny = oi->do_op[denyop_unbind]; + break; + } + + if ( !deny ) { + return SLAP_CB_CONTINUE; + } + + op->o_bd->bd_info = (BackendInfo *)on->on_info; + send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, + "operation not allowed within namingContext" ); + + return 0; +} + +static int +denyop_over_init( + BackendDB *be, ConfigReply *cr +) +{ + slap_overinst *on = (slap_overinst *) be->bd_info; + denyop_info *oi; + + oi = (denyop_info *)ch_malloc(sizeof(denyop_info)); + memset(oi, 0, sizeof(denyop_info)); + on->on_bi.bi_private = oi; + + return 0; +} + +static int +denyop_config( + BackendDB *be, + const char *fname, + int lineno, + int argc, + char **argv +) +{ + slap_overinst *on = (slap_overinst *) be->bd_info; + denyop_info *oi = (denyop_info *)on->on_bi.bi_private; + + if ( strcasecmp( argv[0], "denyop" ) == 0 ) { + char *op; + + if ( argc != 2 ) { + Debug( LDAP_DEBUG_ANY, "%s: line %d: " + "operation list missing in " + "\"denyop <op-list>\" line.\n", + fname, lineno ); + return( 1 ); + } + + /* The on->on_bi.bi_private pointer can be used for + * anything this instance of the overlay needs. + */ + + op = argv[1]; + do { + char *next = strchr( op, ',' ); + + if ( next ) { + next[0] = '\0'; + next++; + } + + if ( strcmp( op, "add" ) == 0 ) { + oi->do_op[denyop_add] = 1; + + } else if ( strcmp( op, "bind" ) == 0 ) { + oi->do_op[denyop_bind] = 1; + + } else if ( strcmp( op, "compare" ) == 0 ) { + oi->do_op[denyop_compare] = 1; + + } else if ( strcmp( op, "delete" ) == 0 ) { + oi->do_op[denyop_delete] = 1; + + } else if ( strcmp( op, "extended" ) == 0 ) { + oi->do_op[denyop_extended] = 1; + + } else if ( strcmp( op, "modify" ) == 0 ) { + oi->do_op[denyop_modify] = 1; + + } else if ( strcmp( op, "modrdn" ) == 0 ) { + oi->do_op[denyop_modrdn] = 1; + + } else if ( strcmp( op, "search" ) == 0 ) { + oi->do_op[denyop_search] = 1; + + } else if ( strcmp( op, "unbind" ) == 0 ) { + oi->do_op[denyop_unbind] = 1; + + } else { + Debug( LDAP_DEBUG_ANY, "%s: line %d: " + "unknown operation \"%s\" at " + "\"denyop <op-list>\" line.\n", + fname, lineno, op ); + return( 1 ); + } + + op = next; + } while ( op ); + + } else { + return SLAP_CONF_UNKNOWN; + } + return 0; +} + +static int +denyop_destroy( + BackendDB *be, ConfigReply *cr +) +{ + slap_overinst *on = (slap_overinst *) be->bd_info; + denyop_info *oi = (denyop_info *)on->on_bi.bi_private; + + if ( oi ) { + ch_free( oi ); + } + + return 0; +} + +/* This overlay is set up for dynamic loading via moduleload. For static + * configuration, you'll need to arrange for the slap_overinst to be + * initialized and registered by some other function inside slapd. + */ + +static slap_overinst denyop; + +int +denyop_initialize( void ) +{ + memset( &denyop, 0, sizeof( slap_overinst ) ); + denyop.on_bi.bi_type = "denyop"; + denyop.on_bi.bi_flags = SLAPO_BFLAG_SINGLE; + denyop.on_bi.bi_db_init = denyop_over_init; + denyop.on_bi.bi_db_config = denyop_config; + denyop.on_bi.bi_db_destroy = denyop_destroy; + + denyop.on_bi.bi_op_bind = denyop_func; + denyop.on_bi.bi_op_search = denyop_func; + denyop.on_bi.bi_op_compare = denyop_func; + denyop.on_bi.bi_op_modify = denyop_func; + denyop.on_bi.bi_op_modrdn = denyop_func; + denyop.on_bi.bi_op_add = denyop_func; + denyop.on_bi.bi_op_delete = denyop_func; + denyop.on_bi.bi_extended = denyop_func; + denyop.on_bi.bi_op_unbind = denyop_func; + + denyop.on_response = NULL /* denyop_response */ ; + + return overlay_register( &denyop ); +} + +#if SLAPD_OVER_DENYOP == SLAPD_MOD_DYNAMIC +int +init_module( int argc, char *argv[] ) +{ + return denyop_initialize(); +} +#endif /* SLAPD_OVER_DENYOP == SLAPD_MOD_DYNAMIC */ + +#endif /* defined(SLAPD_OVER_DENYOP) */ |