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