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