Home | History | Annotate | Line # | Download | only in slapd
      1 /*	$NetBSD: verbs.c,v 1.2 2025/09/05 21:16:26 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 1998-2024 The OpenLDAP Foundation.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted only as authorized by the OpenLDAP
     11  * Public License.
     12  *
     13  * A copy of this license is available in the file LICENSE in the
     14  * top-level directory of the distribution or, alternatively, at
     15  * <http://www.OpenLDAP.org/license.html>.
     16  */
     17 
     18 #include <sys/cdefs.h>
     19 __RCSID("$NetBSD: verbs.c,v 1.2 2025/09/05 21:16:26 christos Exp $");
     20 
     21 #include "portable.h"
     22 
     23 #include "slap.h"
     24 #include "slap-config.h"
     25 
     26 int
     27 bverb_to_mask( struct berval *bword, slap_verbmasks *v ) {
     28 	int i;
     29 	for ( i = 0; !BER_BVISNULL(&v[i].word); i++ ) {
     30 		if ( !ber_bvstrcasecmp( bword, &v[i].word) ) break;
     31 	}
     32 	return i;
     33 }
     34 
     35 int
     36 verb_to_mask( const char *word, slap_verbmasks *v ) {
     37 	struct berval	bword;
     38 	ber_str2bv( word, 0, 0, &bword );
     39 	return bverb_to_mask( &bword, v );
     40 }
     41 
     42 int
     43 verbs_to_mask( int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m ) {
     44 	int i, j;
     45 	for (i = 1; i < argc; i++ ) {
     46 		j = verb_to_mask( argv[i], v );
     47 		if ( BER_BVISNULL(&v[j].word) ) return i;
     48 		while ( !v[j].mask ) j--;
     49 		*m |= v[j].mask;
     50 	}
     51 	return 0;
     52 }
     53 
     54 /*
     55  * Mask keywords that represent multiple bits should occur before single
     56  * bit keywords in the verbmasks array.
     57  */
     58 int
     59 mask_to_verbs( slap_verbmasks *v, slap_mask_t m, BerVarray *bva ) {
     60 	int i, rc = 1;
     61 
     62 	if ( m ) {
     63 		for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) {
     64 			if (!v[i].mask) continue;
     65 			if ( ( m & v[i].mask ) == v[i].mask ) {
     66 				value_add_one( bva, &v[i].word );
     67 				rc = 0;
     68 				m ^= v[i].mask;
     69 				if ( !m ) break;
     70 			}
     71 		}
     72 	}
     73 	return rc;
     74 }
     75 
     76 /* Return the verbs as a single string, separated by delim */
     77 int
     78 mask_to_verbstring( slap_verbmasks *v, slap_mask_t m0, char delim, struct berval *bv )
     79 {
     80 	int i, rc = 1;
     81 
     82 	BER_BVZERO( bv );
     83 	if ( m0 ) {
     84 		slap_mask_t m = m0;
     85 		char *ptr;
     86 		for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) {
     87 			if ( !v[i].mask ) continue;
     88 			if ( ( m & v[i].mask ) == v[i].mask ) {
     89 				bv->bv_len += v[i].word.bv_len + 1;
     90 				rc = 0;
     91 				m ^= v[i].mask;
     92 				if ( !m ) break;
     93 			}
     94 		}
     95 		bv->bv_val = ch_malloc(bv->bv_len);
     96 		bv->bv_len--;
     97 		ptr = bv->bv_val;
     98 		m = m0;
     99 		for ( i=0; !BER_BVISNULL(&v[i].word); i++ ) {
    100 			if ( !v[i].mask ) continue;
    101 			if ( ( m & v[i].mask ) == v[i].mask ) {
    102 				ptr = lutil_strcopy( ptr, v[i].word.bv_val );
    103 				*ptr++ = delim;
    104 				m ^= v[i].mask;
    105 				if ( !m ) break;
    106 			}
    107 		}
    108 		ptr[-1] = '\0';
    109 	}
    110 	return rc;
    111 }
    112 
    113 /* Parse a verbstring */
    114 int
    115 verbstring_to_mask( slap_verbmasks *v, char *str, char delim, slap_mask_t *m ) {
    116 	int j;
    117 	char *d;
    118 	struct berval bv;
    119 
    120 	do {
    121 		bv.bv_val = str;
    122 		d = strchr( str, delim );
    123 		if ( d )
    124 			bv.bv_len = d - str;
    125 		else
    126 			bv.bv_len = strlen( str );
    127 		j = bverb_to_mask( &bv, v );
    128 		if ( BER_BVISNULL(&v[j].word) ) return 1;
    129 		while ( !v[j].mask ) j--;
    130 		*m |= v[j].mask;
    131 		str += bv.bv_len + 1;
    132 	} while ( d );
    133 	return 0;
    134 }
    135 
    136 int
    137 slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
    138 {
    139 	int		i;
    140 
    141 	assert( *vp == NULL );
    142 
    143 	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) /* EMPTY */;
    144 
    145 	*vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) );
    146 
    147 	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
    148 		ber_dupbv( &(*vp)[ i ].word, &v[ i ].word );
    149 		*((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask;
    150 	}
    151 
    152 	BER_BVZERO( &(*vp)[ i ].word );
    153 
    154 	return 0;
    155 }
    156 
    157 int
    158 slap_verbmasks_destroy( slap_verbmasks *v )
    159 {
    160 	int		i;
    161 
    162 	assert( v != NULL );
    163 
    164 	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
    165 		ch_free( v[ i ].word.bv_val );
    166 	}
    167 
    168 	ch_free( v );
    169 
    170 	return 0;
    171 }
    172 
    173 int
    174 slap_verbmasks_append(
    175 	slap_verbmasks	**vp,
    176 	slap_mask_t	m,
    177 	struct berval	*v,
    178 	slap_mask_t	*ignore )
    179 {
    180 	int	i;
    181 
    182 	if ( !m ) {
    183 		return LDAP_OPERATIONS_ERROR;
    184 	}
    185 
    186 	for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) {
    187 		if ( !(*vp)[ i ].mask ) continue;
    188 
    189 		if ( ignore != NULL ) {
    190 			int	j;
    191 
    192 			for ( j = 0; ignore[ j ] != 0; j++ ) {
    193 				if ( (*vp)[ i ].mask == ignore[ j ] ) {
    194 					goto check_next;
    195 				}
    196 			}
    197 		}
    198 
    199 		if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) {
    200 			if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) {
    201 				/* already set; ignore */
    202 				return LDAP_SUCCESS;
    203 			}
    204 			/* conflicts */
    205 			return LDAP_TYPE_OR_VALUE_EXISTS;
    206 		}
    207 
    208 		if ( m & (*vp)[ i ].mask ) {
    209 			/* conflicts */
    210 			return LDAP_CONSTRAINT_VIOLATION;
    211 		}
    212 check_next:;
    213 	}
    214 
    215 	*vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) );
    216 	ber_dupbv( &(*vp)[ i ].word, v );
    217 	*((slap_mask_t *)&(*vp)[ i ].mask) = m;
    218 	BER_BVZERO( &(*vp)[ i + 1 ].word );
    219 
    220 	return LDAP_SUCCESS;
    221 }
    222 
    223 int
    224 enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
    225 	int i;
    226 
    227 	for (i=0; !BER_BVISNULL(&v[i].word); i++) {
    228 		if ( m == v[i].mask ) {
    229 			if ( bv != NULL ) {
    230 				*bv = v[i].word;
    231 			}
    232 			return i;
    233 		}
    234 	}
    235 	return -1;
    236 }
    237 
    238 /* register a new verbmask */
    239 int
    240 slap_verbmask_register(
    241 	slap_verbmasks *vm_,
    242 	slap_verbmasks **vmp,
    243 	struct berval *bv,
    244 	int mask )
    245 {
    246 	slap_verbmasks	*vm = *vmp;
    247 	int		i;
    248 
    249 	/* check for duplicate word */
    250 	/* NOTE: we accept duplicate codes; the first occurrence will be used
    251 	 * when mapping from mask to verb */
    252 	i = verb_to_mask( bv->bv_val, vm );
    253 	if ( !BER_BVISNULL( &vm[ i ].word ) ) {
    254 		return -1;
    255 	}
    256 
    257 	for ( i = 0; !BER_BVISNULL( &vm[ i ].word ); i++ )
    258 		;
    259 
    260 	if ( vm == vm_ ) {
    261 		/* first time: duplicate array */
    262 		vm = ch_calloc( i + 2, sizeof( slap_verbmasks ) );
    263 		for ( i = 0; !BER_BVISNULL( &vm_[ i ].word ); i++ )
    264 		{
    265 			ber_dupbv( &vm[ i ].word, &vm_[ i ].word );
    266 			*((slap_mask_t*)&vm[ i ].mask) = vm_[ i ].mask;
    267 		}
    268 
    269 	} else {
    270 		vm = ch_realloc( vm, (i + 2) * sizeof( slap_verbmasks ) );
    271 	}
    272 
    273 	ber_dupbv( &vm[ i ].word, bv );
    274 	*((slap_mask_t*)&vm[ i ].mask) = mask;
    275 
    276 	BER_BVZERO( &vm[ i+1 ].word );
    277 
    278 	*vmp = vm;
    279 
    280 	return i;
    281 }
    282