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