Home | History | Annotate | Line # | Download | only in allop
      1  1.3  christos /*	$NetBSD: allop.c,v 1.4 2025/09/05 21:16:15 christos Exp $	*/
      2  1.2  christos 
      3  1.1     lukem /* allop.c - returns all operational attributes when appropriate */
      4  1.2  christos /* $OpenLDAP$ */
      5  1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  1.1     lukem  *
      7  1.4  christos  * Copyright 2005-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     lukem /*
     24  1.1     lukem  * The intended usage is as a global overlay for use with those clients
     25  1.1     lukem  * that do not make use of the RFC3673 allOp ("+") in the requested
     26  1.1     lukem  * attribute list, but expect all operational attributes to be returned.
     27  1.1     lukem  * Usage: add
     28  1.1     lukem  *
     29  1.1     lukem 
     30  1.1     lukem overlay		allop
     31  1.1     lukem allop-URI	<ldapURI>
     32  1.1     lukem 
     33  1.1     lukem  *
     34  1.1     lukem  * if the allop-URI is not given, the rootDSE, i.e. "ldap:///??base",
     35  1.1     lukem  * is assumed.
     36  1.1     lukem  */
     37  1.1     lukem 
     38  1.2  christos #include <sys/cdefs.h>
     39  1.3  christos __RCSID("$NetBSD: allop.c,v 1.4 2025/09/05 21:16:15 christos Exp $");
     40  1.2  christos 
     41  1.1     lukem #include "portable.h"
     42  1.1     lukem 
     43  1.1     lukem #include <stdio.h>
     44  1.1     lukem #include <ac/string.h>
     45  1.1     lukem 
     46  1.1     lukem #include "slap.h"
     47  1.3  christos #include "slap-config.h"
     48  1.1     lukem 
     49  1.1     lukem #define	SLAP_OVER_VERSION_REQUIRE(major,minor,patch) \
     50  1.1     lukem 	( \
     51  1.1     lukem 		( LDAP_VENDOR_VERSION_MAJOR == X || LDAP_VENDOR_VERSION_MAJOR >= (major) ) \
     52  1.1     lukem 		&& ( LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR >= (minor) ) \
     53  1.1     lukem 		&& ( LDAP_VENDOR_VERSION_PATCH == X || LDAP_VENDOR_VERSION_PATCH >= (patch) ) \
     54  1.1     lukem 	)
     55  1.1     lukem 
     56  1.1     lukem #if !SLAP_OVER_VERSION_REQUIRE(2,3,0)
     57  1.1     lukem #error "version mismatch"
     58  1.1     lukem #endif
     59  1.1     lukem 
     60  1.1     lukem typedef struct allop_t {
     61  1.1     lukem 	struct berval	ao_ndn;
     62  1.1     lukem 	int		ao_scope;
     63  1.1     lukem } allop_t;
     64  1.1     lukem 
     65  1.1     lukem static int
     66  1.1     lukem allop_db_config(
     67  1.1     lukem 	BackendDB	*be,
     68  1.1     lukem 	const char	*fname,
     69  1.1     lukem 	int		lineno,
     70  1.1     lukem 	int		argc,
     71  1.1     lukem 	char		**argv )
     72  1.1     lukem {
     73  1.1     lukem 	slap_overinst	*on = (slap_overinst *)be->bd_info;
     74  1.1     lukem 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
     75  1.1     lukem 
     76  1.1     lukem 	if ( strcasecmp( argv[ 0 ], "allop-uri" ) == 0 ) {
     77  1.1     lukem 		LDAPURLDesc	*lud;
     78  1.1     lukem 		struct berval	dn,
     79  1.1     lukem 				ndn;
     80  1.1     lukem 		int		scope,
     81  1.1     lukem 				rc = LDAP_SUCCESS;
     82  1.1     lukem 
     83  1.1     lukem 		if ( argc != 2 ) {
     84  1.1     lukem 			fprintf( stderr, "%s line %d: "
     85  1.1     lukem 				"need exactly 1 arg "
     86  1.1     lukem 				"in \"allop-uri <ldapURI>\" "
     87  1.1     lukem 				"directive.\n",
     88  1.1     lukem 				fname, lineno );
     89  1.1     lukem 			return 1;
     90  1.1     lukem 		}
     91  1.1     lukem 
     92  1.1     lukem 		if ( ldap_url_parse( argv[ 1 ], &lud ) != LDAP_URL_SUCCESS ) {
     93  1.1     lukem 			return -1;
     94  1.1     lukem 		}
     95  1.1     lukem 
     96  1.1     lukem 		scope = lud->lud_scope;
     97  1.1     lukem 		if ( scope == LDAP_SCOPE_DEFAULT ) {
     98  1.1     lukem 			scope = LDAP_SCOPE_BASE;
     99  1.1     lukem 		}
    100  1.1     lukem 
    101  1.1     lukem 		if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
    102  1.1     lukem 			if ( scope == LDAP_SCOPE_BASE ) {
    103  1.1     lukem 				BER_BVZERO( &ndn );
    104  1.1     lukem 
    105  1.1     lukem 			} else {
    106  1.1     lukem 				ber_str2bv( "", 0, 1, &ndn );
    107  1.1     lukem 			}
    108  1.1     lukem 
    109  1.1     lukem 		} else {
    110  1.1     lukem 
    111  1.1     lukem 			ber_str2bv( lud->lud_dn, 0, 0, &dn );
    112  1.1     lukem 			rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
    113  1.1     lukem 		}
    114  1.1     lukem 
    115  1.1     lukem 		ldap_free_urldesc( lud );
    116  1.1     lukem 		if ( rc != LDAP_SUCCESS ) {
    117  1.1     lukem 			return -1;
    118  1.1     lukem 		}
    119  1.1     lukem 
    120  1.1     lukem 		if ( BER_BVISNULL( &ndn ) ) {
    121  1.1     lukem 			/* rootDSE */
    122  1.1     lukem 			if ( ao != NULL ) {
    123  1.1     lukem 				ch_free( ao->ao_ndn.bv_val );
    124  1.1     lukem 				ch_free( ao );
    125  1.1     lukem 				on->on_bi.bi_private = NULL;
    126  1.1     lukem 			}
    127  1.1     lukem 
    128  1.1     lukem 		} else {
    129  1.1     lukem 			if ( ao == NULL ) {
    130  1.1     lukem 				ao = ch_calloc( 1, sizeof( allop_t ) );
    131  1.1     lukem 				on->on_bi.bi_private = (void *)ao;
    132  1.1     lukem 
    133  1.1     lukem 			} else {
    134  1.1     lukem 				ch_free( ao->ao_ndn.bv_val );
    135  1.1     lukem 			}
    136  1.1     lukem 
    137  1.1     lukem 			ao->ao_ndn = ndn;
    138  1.1     lukem 			ao->ao_scope = scope;
    139  1.1     lukem 		}
    140  1.1     lukem 
    141  1.1     lukem 	} else {
    142  1.1     lukem 		return SLAP_CONF_UNKNOWN;
    143  1.1     lukem 	}
    144  1.1     lukem 
    145  1.1     lukem 	return 0;
    146  1.1     lukem }
    147  1.1     lukem 
    148  1.1     lukem static int
    149  1.1     lukem allop_db_destroy( BackendDB *be, ConfigReply *cr )
    150  1.1     lukem {
    151  1.1     lukem 	slap_overinst	*on = (slap_overinst *)be->bd_info;
    152  1.1     lukem 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
    153  1.1     lukem 
    154  1.1     lukem 	if ( ao != NULL ) {
    155  1.1     lukem 		assert( !BER_BVISNULL( &ao->ao_ndn ) );
    156  1.1     lukem 
    157  1.1     lukem 		ch_free( ao->ao_ndn.bv_val );
    158  1.1     lukem 		ch_free( ao );
    159  1.1     lukem 		on->on_bi.bi_private = NULL;
    160  1.1     lukem 	}
    161  1.1     lukem 
    162  1.1     lukem 	return 0;
    163  1.1     lukem }
    164  1.1     lukem 
    165  1.1     lukem static int
    166  1.1     lukem allop_op_search( Operation *op, SlapReply *rs )
    167  1.1     lukem {
    168  1.1     lukem 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    169  1.1     lukem 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
    170  1.1     lukem 
    171  1.1     lukem 	slap_mask_t	mask;
    172  1.1     lukem 	int		i,
    173  1.1     lukem 			add_allUser = 0;
    174  1.1     lukem 
    175  1.1     lukem 	if ( ao == NULL ) {
    176  1.1     lukem 		if ( !BER_BVISEMPTY( &op->o_req_ndn )
    177  1.1     lukem 			|| op->ors_scope != LDAP_SCOPE_BASE )
    178  1.1     lukem 		{
    179  1.1     lukem 			return SLAP_CB_CONTINUE;
    180  1.1     lukem 		}
    181  1.1     lukem 
    182  1.1     lukem 	} else {
    183  1.1     lukem 		if ( !dnIsSuffix( &op->o_req_ndn, &ao->ao_ndn ) ) {
    184  1.1     lukem 			return SLAP_CB_CONTINUE;
    185  1.1     lukem 		}
    186  1.1     lukem 
    187  1.1     lukem 		switch ( ao->ao_scope ) {
    188  1.1     lukem 		case LDAP_SCOPE_BASE:
    189  1.1     lukem 			if ( op->o_req_ndn.bv_len != ao->ao_ndn.bv_len ) {
    190  1.1     lukem 				return SLAP_CB_CONTINUE;
    191  1.1     lukem 			}
    192  1.1     lukem 			break;
    193  1.1     lukem 
    194  1.1     lukem 		case LDAP_SCOPE_ONELEVEL:
    195  1.1     lukem 			if ( op->ors_scope == LDAP_SCOPE_BASE ) {
    196  1.1     lukem 				struct berval	rdn = op->o_req_ndn;
    197  1.1     lukem 
    198  1.1     lukem 				rdn.bv_len -= ao->ao_ndn.bv_len + STRLENOF( "," );
    199  1.1     lukem 				if ( !dnIsOneLevelRDN( &rdn ) ) {
    200  1.1     lukem 					return SLAP_CB_CONTINUE;
    201  1.1     lukem 				}
    202  1.1     lukem 
    203  1.1     lukem 				break;
    204  1.1     lukem 			}
    205  1.1     lukem 			return SLAP_CB_CONTINUE;
    206  1.1     lukem 
    207  1.1     lukem 		case LDAP_SCOPE_SUBTREE:
    208  1.1     lukem 			break;
    209  1.1     lukem 		}
    210  1.1     lukem 	}
    211  1.1     lukem 
    212  1.1     lukem 	mask = slap_attr_flags( op->ors_attrs );
    213  1.1     lukem 	if ( SLAP_OPATTRS( mask ) ) {
    214  1.1     lukem 		return SLAP_CB_CONTINUE;
    215  1.1     lukem 	}
    216  1.1     lukem 
    217  1.1     lukem 	if ( !SLAP_USERATTRS( mask ) ) {
    218  1.1     lukem 		return SLAP_CB_CONTINUE;
    219  1.1     lukem 	}
    220  1.1     lukem 
    221  1.1     lukem 	i = 0;
    222  1.1     lukem 	if ( op->ors_attrs == NULL ) {
    223  1.1     lukem 		add_allUser = 1;
    224  1.1     lukem 
    225  1.1     lukem 	} else {
    226  1.1     lukem 		for ( ; !BER_BVISNULL( &op->ors_attrs[ i ].an_name ); i++ )
    227  1.1     lukem 			;
    228  1.1     lukem 	}
    229  1.1     lukem 
    230  1.1     lukem 	op->ors_attrs = op->o_tmprealloc( op->ors_attrs,
    231  1.1     lukem 		sizeof( AttributeName ) * ( i + add_allUser + 2 ),
    232  1.1     lukem 		op->o_tmpmemctx );
    233  1.1     lukem 
    234  1.1     lukem 	if ( add_allUser ) {
    235  1.1     lukem 		op->ors_attrs[ i ] = slap_anlist_all_user_attributes[ 0 ];
    236  1.1     lukem 		i++;
    237  1.1     lukem 	}
    238  1.1     lukem 
    239  1.1     lukem 	op->ors_attrs[ i ] = slap_anlist_all_operational_attributes[ 0 ];
    240  1.1     lukem 
    241  1.1     lukem 	BER_BVZERO( &op->ors_attrs[ i + 1 ].an_name );
    242  1.1     lukem 
    243  1.1     lukem 	return SLAP_CB_CONTINUE;
    244  1.1     lukem }
    245  1.1     lukem 
    246  1.1     lukem static slap_overinst 		allop;
    247  1.1     lukem 
    248  1.1     lukem int
    249  1.1     lukem allop_init()
    250  1.1     lukem {
    251  1.1     lukem 	allop.on_bi.bi_type = "allop";
    252  1.1     lukem 
    253  1.3  christos 	allop.on_bi.bi_flags = SLAPO_BFLAG_SINGLE;
    254  1.1     lukem 	allop.on_bi.bi_db_config = allop_db_config;
    255  1.1     lukem 	allop.on_bi.bi_db_destroy = allop_db_destroy;
    256  1.1     lukem 
    257  1.1     lukem 	allop.on_bi.bi_op_search = allop_op_search;
    258  1.1     lukem 
    259  1.1     lukem 	return overlay_register( &allop );
    260  1.1     lukem }
    261  1.1     lukem 
    262  1.1     lukem int
    263  1.1     lukem init_module( int argc, char *argv[] )
    264  1.1     lukem {
    265  1.1     lukem 	return allop_init();
    266  1.1     lukem }
    267  1.1     lukem 
    268