1 1.3 christos /* $NetBSD: rwmmap.c,v 1.4 2025/09/05 21:16:32 christos Exp $ */ 2 1.2 christos 3 1.1 lukem /* rwmmap.c - rewrite/mapping routines */ 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 1999-2024 The OpenLDAP Foundation. 8 1.1 lukem * Portions Copyright 1999-2003 Howard Chu. 9 1.1 lukem * Portions Copyright 2000-2003 Pierangelo Masarati. 10 1.1 lukem * All rights reserved. 11 1.1 lukem * 12 1.1 lukem * Redistribution and use in source and binary forms, with or without 13 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP 14 1.1 lukem * Public License. 15 1.1 lukem * 16 1.1 lukem * A copy of this license is available in the file LICENSE in the 17 1.1 lukem * top-level directory of the distribution or, alternatively, at 18 1.1 lukem * <http://www.OpenLDAP.org/license.html>. 19 1.1 lukem */ 20 1.1 lukem /* ACKNOWLEDGEMENTS: 21 1.1 lukem * This work was initially developed by the Howard Chu for inclusion 22 1.1 lukem * in OpenLDAP Software and subsequently enhanced by Pierangelo 23 1.1 lukem * Masarati. 24 1.1 lukem */ 25 1.1 lukem 26 1.2 christos #include <sys/cdefs.h> 27 1.3 christos __RCSID("$NetBSD: rwmmap.c,v 1.4 2025/09/05 21:16:32 christos Exp $"); 28 1.2 christos 29 1.1 lukem #include "portable.h" 30 1.1 lukem 31 1.1 lukem #ifdef SLAPD_OVER_RWM 32 1.1 lukem 33 1.1 lukem #include <stdio.h> 34 1.1 lukem 35 1.1 lukem #include <ac/string.h> 36 1.1 lukem #include <ac/socket.h> 37 1.1 lukem 38 1.1 lukem #include "slap.h" 39 1.1 lukem #include "rwm.h" 40 1.1 lukem 41 1.1 lukem #undef ldap_debug /* silence a warning in ldap-int.h */ 42 1.1 lukem #include "../../../libraries/libldap/ldap-int.h" 43 1.1 lukem 44 1.1 lukem int 45 1.1 lukem rwm_mapping_cmp( const void *c1, const void *c2 ) 46 1.1 lukem { 47 1.1 lukem struct ldapmapping *map1 = (struct ldapmapping *)c1; 48 1.1 lukem struct ldapmapping *map2 = (struct ldapmapping *)c2; 49 1.1 lukem int rc = map1->m_src.bv_len - map2->m_src.bv_len; 50 1.1 lukem 51 1.1 lukem if ( rc ) { 52 1.1 lukem return rc; 53 1.1 lukem } 54 1.1 lukem 55 1.1 lukem return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ); 56 1.1 lukem } 57 1.1 lukem 58 1.1 lukem int 59 1.1 lukem rwm_mapping_dup( void *c1, void *c2 ) 60 1.1 lukem { 61 1.1 lukem struct ldapmapping *map1 = (struct ldapmapping *)c1; 62 1.1 lukem struct ldapmapping *map2 = (struct ldapmapping *)c2; 63 1.1 lukem int rc = map1->m_src.bv_len - map2->m_src.bv_len; 64 1.1 lukem 65 1.1 lukem if ( rc ) { 66 1.1 lukem return 0; 67 1.1 lukem } 68 1.1 lukem 69 1.1 lukem return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 ); 70 1.1 lukem } 71 1.1 lukem 72 1.1 lukem int 73 1.1 lukem rwm_map_init( struct ldapmap *lm, struct ldapmapping **m ) 74 1.1 lukem { 75 1.1 lukem struct ldapmapping *mapping; 76 1.1 lukem const char *text; 77 1.1 lukem int rc; 78 1.1 lukem 79 1.1 lukem assert( m != NULL ); 80 1.1 lukem 81 1.1 lukem *m = NULL; 82 1.1 lukem 83 1.1 lukem mapping = (struct ldapmapping *)ch_calloc( 2, 84 1.1 lukem sizeof( struct ldapmapping ) ); 85 1.1 lukem if ( mapping == NULL ) { 86 1.1 lukem return LDAP_NO_MEMORY; 87 1.1 lukem } 88 1.1 lukem 89 1.2 christos /* NOTE: this is needed to make sure that 90 1.2 christos * rwm-map attribute * 91 1.2 christos * does not filter out all attributes including objectClass */ 92 1.1 lukem rc = slap_str2ad( "objectClass", &mapping[0].m_src_ad, &text ); 93 1.1 lukem if ( rc != LDAP_SUCCESS ) { 94 1.1 lukem ch_free( mapping ); 95 1.1 lukem return rc; 96 1.1 lukem } 97 1.1 lukem 98 1.1 lukem mapping[0].m_dst_ad = mapping[0].m_src_ad; 99 1.1 lukem ber_dupbv( &mapping[0].m_src, &mapping[0].m_src_ad->ad_cname ); 100 1.1 lukem ber_dupbv( &mapping[0].m_dst, &mapping[0].m_src ); 101 1.1 lukem 102 1.1 lukem mapping[1].m_src = mapping[0].m_src; 103 1.1 lukem mapping[1].m_dst = mapping[0].m_dst; 104 1.1 lukem mapping[1].m_src_ad = mapping[0].m_src_ad; 105 1.1 lukem mapping[1].m_dst_ad = mapping[1].m_src_ad; 106 1.1 lukem 107 1.3 christos ldap_avl_insert( &lm->map, (caddr_t)&mapping[0], 108 1.1 lukem rwm_mapping_cmp, rwm_mapping_dup ); 109 1.3 christos ldap_avl_insert( &lm->remap, (caddr_t)&mapping[1], 110 1.1 lukem rwm_mapping_cmp, rwm_mapping_dup ); 111 1.1 lukem 112 1.1 lukem *m = mapping; 113 1.1 lukem 114 1.1 lukem return rc; 115 1.1 lukem } 116 1.1 lukem 117 1.1 lukem int 118 1.1 lukem rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap ) 119 1.1 lukem { 120 1.1 lukem Avlnode *tree; 121 1.1 lukem struct ldapmapping fmapping; 122 1.1 lukem 123 1.1 lukem if ( map == NULL ) { 124 1.1 lukem return 0; 125 1.1 lukem } 126 1.1 lukem 127 1.1 lukem assert( m != NULL ); 128 1.1 lukem 129 1.2 christos /* let special attrnames slip through (ITS#5760) */ 130 1.2 christos if ( bvmatch( s, slap_bv_no_attrs ) 131 1.2 christos || bvmatch( s, slap_bv_all_user_attrs ) 132 1.2 christos || bvmatch( s, slap_bv_all_operational_attrs ) ) 133 1.2 christos { 134 1.2 christos *m = NULL; 135 1.2 christos return 0; 136 1.2 christos } 137 1.2 christos 138 1.1 lukem if ( remap == RWM_REMAP ) { 139 1.1 lukem tree = map->remap; 140 1.1 lukem 141 1.1 lukem } else { 142 1.1 lukem tree = map->map; 143 1.1 lukem } 144 1.1 lukem 145 1.1 lukem fmapping.m_src = *s; 146 1.3 christos *m = (struct ldapmapping *)ldap_avl_find( tree, (caddr_t)&fmapping, 147 1.1 lukem rwm_mapping_cmp ); 148 1.1 lukem 149 1.1 lukem if ( *m == NULL ) { 150 1.1 lukem return map->drop_missing; 151 1.1 lukem } 152 1.1 lukem 153 1.1 lukem return 0; 154 1.1 lukem } 155 1.1 lukem 156 1.1 lukem void 157 1.1 lukem rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap ) 158 1.1 lukem { 159 1.1 lukem struct ldapmapping *mapping; 160 1.1 lukem 161 1.1 lukem /* map->map may be NULL when mapping is configured, 162 1.1 lukem * but map->remap can't */ 163 1.1 lukem if ( map->remap == NULL ) { 164 1.1 lukem *bv = *s; 165 1.1 lukem return; 166 1.1 lukem } 167 1.1 lukem 168 1.1 lukem BER_BVZERO( bv ); 169 1.1 lukem ( void )rwm_mapping( map, s, &mapping, remap ); 170 1.1 lukem if ( mapping != NULL ) { 171 1.1 lukem if ( !BER_BVISNULL( &mapping->m_dst ) ) { 172 1.1 lukem *bv = mapping->m_dst; 173 1.1 lukem } 174 1.1 lukem return; 175 1.1 lukem } 176 1.1 lukem 177 1.1 lukem if ( !map->drop_missing ) { 178 1.1 lukem *bv = *s; 179 1.1 lukem } 180 1.1 lukem } 181 1.1 lukem 182 1.1 lukem /* 183 1.1 lukem * Map attribute names in place 184 1.1 lukem */ 185 1.1 lukem int 186 1.1 lukem rwm_map_attrnames( 187 1.2 christos Operation *op, 188 1.1 lukem struct ldapmap *at_map, 189 1.1 lukem struct ldapmap *oc_map, 190 1.1 lukem AttributeName *an, 191 1.1 lukem AttributeName **anp, 192 1.1 lukem int remap ) 193 1.1 lukem { 194 1.2 christos int i, j, x; 195 1.1 lukem 196 1.1 lukem assert( anp != NULL ); 197 1.1 lukem 198 1.1 lukem *anp = NULL; 199 1.1 lukem 200 1.2 christos if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) { 201 1.1 lukem return LDAP_SUCCESS; 202 1.1 lukem } 203 1.1 lukem 204 1.2 christos i = 0; 205 1.2 christos if ( an != NULL ) { 206 1.2 christos for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) 207 1.2 christos /* just count */ ; 208 1.2 christos } 209 1.2 christos 210 1.2 christos x = 0; 211 1.2 christos if ( op->o_bd->be_extra_anlist ) { 212 1.2 christos for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) 213 1.2 christos /* just count */ ; 214 1.2 christos } 215 1.2 christos 216 1.2 christos assert( i > 0 || x > 0 ); 217 1.2 christos *anp = op->o_tmpcalloc( ( i + x + 1 ), sizeof( AttributeName ), 218 1.2 christos op->o_tmpmemctx ); 219 1.1 lukem if ( *anp == NULL ) { 220 1.1 lukem return LDAP_NO_MEMORY; 221 1.1 lukem } 222 1.1 lukem 223 1.2 christos j = 0; 224 1.2 christos if ( an != NULL ) { 225 1.2 christos for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) { 226 1.1 lukem struct ldapmapping *m; 227 1.1 lukem int at_drop_missing = 0, 228 1.1 lukem oc_drop_missing = 0; 229 1.1 lukem 230 1.1 lukem if ( an[i].an_desc ) { 231 1.1 lukem if ( !at_map ) { 232 1.1 lukem /* FIXME: better leave as is? */ 233 1.1 lukem continue; 234 1.1 lukem } 235 1.1 lukem 236 1.1 lukem at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap ); 237 1.1 lukem if ( at_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) { 238 1.1 lukem continue; 239 1.1 lukem } 240 1.1 lukem 241 1.1 lukem if ( !m ) { 242 1.1 lukem (*anp)[j] = an[i]; 243 1.1 lukem j++; 244 1.1 lukem continue; 245 1.1 lukem } 246 1.1 lukem 247 1.1 lukem (*anp)[j] = an[i]; 248 1.1 lukem if ( remap == RWM_MAP ) { 249 1.1 lukem (*anp)[j].an_name = m->m_dst; 250 1.1 lukem (*anp)[j].an_desc = m->m_dst_ad; 251 1.1 lukem } else { 252 1.1 lukem (*anp)[j].an_name = m->m_src; 253 1.1 lukem (*anp)[j].an_desc = m->m_src_ad; 254 1.1 lukem 255 1.1 lukem } 256 1.1 lukem 257 1.1 lukem j++; 258 1.1 lukem continue; 259 1.1 lukem 260 1.1 lukem } else if ( an[i].an_oc ) { 261 1.1 lukem if ( !oc_map ) { 262 1.1 lukem /* FIXME: better leave as is? */ 263 1.1 lukem continue; 264 1.1 lukem } 265 1.1 lukem 266 1.1 lukem oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap ); 267 1.1 lukem 268 1.1 lukem if ( oc_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) { 269 1.1 lukem continue; 270 1.1 lukem } 271 1.1 lukem 272 1.1 lukem if ( !m ) { 273 1.1 lukem (*anp)[j] = an[i]; 274 1.1 lukem j++; 275 1.1 lukem continue; 276 1.1 lukem } 277 1.1 lukem 278 1.1 lukem (*anp)[j] = an[i]; 279 1.1 lukem if ( remap == RWM_MAP ) { 280 1.1 lukem (*anp)[j].an_name = m->m_dst; 281 1.1 lukem (*anp)[j].an_oc = m->m_dst_oc; 282 1.1 lukem } else { 283 1.1 lukem (*anp)[j].an_name = m->m_src; 284 1.1 lukem (*anp)[j].an_oc = m->m_src_oc; 285 1.1 lukem } 286 1.1 lukem 287 1.1 lukem } else { 288 1.1 lukem at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap ); 289 1.1 lukem 290 1.1 lukem if ( at_drop_missing || !m ) { 291 1.1 lukem oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap ); 292 1.1 lukem 293 1.1 lukem /* if both at_map and oc_map required to drop missing, 294 1.1 lukem * then do it */ 295 1.1 lukem if ( oc_drop_missing && at_drop_missing ) { 296 1.1 lukem continue; 297 1.1 lukem } 298 1.1 lukem 299 1.1 lukem /* if no oc_map mapping was found and at_map required 300 1.1 lukem * to drop missing, then do it; otherwise, at_map wins 301 1.1 lukem * and an is considered an attr and is left unchanged */ 302 1.1 lukem if ( !m ) { 303 1.1 lukem if ( at_drop_missing ) { 304 1.1 lukem continue; 305 1.1 lukem } 306 1.1 lukem (*anp)[j] = an[i]; 307 1.1 lukem j++; 308 1.1 lukem continue; 309 1.1 lukem } 310 1.1 lukem 311 1.1 lukem if ( BER_BVISNULL( &m->m_dst ) ) { 312 1.1 lukem continue; 313 1.1 lukem } 314 1.1 lukem 315 1.1 lukem (*anp)[j] = an[i]; 316 1.1 lukem if ( remap == RWM_MAP ) { 317 1.1 lukem (*anp)[j].an_name = m->m_dst; 318 1.1 lukem (*anp)[j].an_oc = m->m_dst_oc; 319 1.1 lukem } else { 320 1.1 lukem (*anp)[j].an_name = m->m_src; 321 1.1 lukem (*anp)[j].an_oc = m->m_src_oc; 322 1.1 lukem } 323 1.1 lukem j++; 324 1.1 lukem continue; 325 1.1 lukem } 326 1.1 lukem 327 1.1 lukem if ( !BER_BVISNULL( &m->m_dst ) ) { 328 1.1 lukem (*anp)[j] = an[i]; 329 1.1 lukem if ( remap == RWM_MAP ) { 330 1.1 lukem (*anp)[j].an_name = m->m_dst; 331 1.1 lukem (*anp)[j].an_desc = m->m_dst_ad; 332 1.1 lukem } else { 333 1.1 lukem (*anp)[j].an_name = m->m_src; 334 1.1 lukem (*anp)[j].an_desc = m->m_src_ad; 335 1.1 lukem } 336 1.1 lukem j++; 337 1.1 lukem continue; 338 1.1 lukem } 339 1.1 lukem } 340 1.1 lukem } 341 1.2 christos } 342 1.2 christos 343 1.2 christos if ( op->o_bd->be_extra_anlist != NULL ) { 344 1.2 christos /* we assume be_extra_anlist are already mapped */ 345 1.2 christos for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) { 346 1.2 christos BER_BVZERO( &(*anp)[j].an_name ); 347 1.2 christos if ( op->o_bd->be_extra_anlist[x].an_desc && 348 1.2 christos ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, *anp ) ) 349 1.2 christos { 350 1.2 christos continue; 351 1.2 christos } 352 1.2 christos 353 1.2 christos (*anp)[j] = op->o_bd->be_extra_anlist[x]; 354 1.2 christos j++; 355 1.2 christos } 356 1.2 christos } 357 1.1 lukem 358 1.2 christos if ( j == 0 && ( i != 0 || x != 0 ) ) { 359 1.1 lukem memset( &(*anp)[0], 0, sizeof( AttributeName ) ); 360 1.2 christos (*anp)[0].an_name = *slap_bv_no_attrs; 361 1.1 lukem j = 1; 362 1.1 lukem } 363 1.1 lukem memset( &(*anp)[j], 0, sizeof( AttributeName ) ); 364 1.1 lukem 365 1.1 lukem return LDAP_SUCCESS; 366 1.1 lukem } 367 1.1 lukem 368 1.2 christos #if 0 /* unused! */ 369 1.1 lukem int 370 1.1 lukem rwm_map_attrs( 371 1.1 lukem struct ldapmap *at_map, 372 1.1 lukem AttributeName *an, 373 1.1 lukem int remap, 374 1.1 lukem char ***mapped_attrs ) 375 1.1 lukem { 376 1.1 lukem int i, j; 377 1.1 lukem char **na; 378 1.1 lukem 379 1.1 lukem if ( an == NULL ) { 380 1.1 lukem *mapped_attrs = NULL; 381 1.1 lukem return LDAP_SUCCESS; 382 1.1 lukem } 383 1.1 lukem 384 1.1 lukem for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ ) 385 1.1 lukem /* count'em */ ; 386 1.1 lukem 387 1.1 lukem na = (char **)ch_calloc( i + 1, sizeof( char * ) ); 388 1.1 lukem if ( na == NULL ) { 389 1.1 lukem *mapped_attrs = NULL; 390 1.1 lukem return LDAP_NO_MEMORY; 391 1.1 lukem } 392 1.1 lukem 393 1.1 lukem for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) { 394 1.1 lukem struct ldapmapping *mapping; 395 1.1 lukem 396 1.1 lukem if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) { 397 1.1 lukem continue; 398 1.1 lukem } 399 1.1 lukem 400 1.1 lukem if ( !mapping ) { 401 1.1 lukem na[ j++ ] = an[ i ].an_name.bv_val; 402 1.1 lukem 403 1.1 lukem } else if ( !BER_BVISNULL( &mapping->m_dst ) ) { 404 1.1 lukem na[ j++ ] = mapping->m_dst.bv_val; 405 1.1 lukem } 406 1.1 lukem } 407 1.1 lukem 408 1.1 lukem if ( j == 0 && i != 0 ) { 409 1.1 lukem na[ j++ ] = LDAP_NO_ATTRS; 410 1.1 lukem } 411 1.1 lukem 412 1.1 lukem na[ j ] = NULL; 413 1.1 lukem 414 1.1 lukem *mapped_attrs = na; 415 1.1 lukem 416 1.1 lukem return LDAP_SUCCESS; 417 1.1 lukem } 418 1.2 christos #endif 419 1.1 lukem 420 1.1 lukem static int 421 1.1 lukem map_attr_value( 422 1.1 lukem dncookie *dc, 423 1.1 lukem AttributeDescription **adp, 424 1.1 lukem struct berval *mapped_attr, 425 1.1 lukem struct berval *value, 426 1.1 lukem struct berval *mapped_value, 427 1.2 christos int remap, 428 1.2 christos void *memctx ) 429 1.1 lukem { 430 1.1 lukem struct berval vtmp = BER_BVNULL; 431 1.1 lukem int freeval = 0; 432 1.1 lukem AttributeDescription *ad = *adp; 433 1.1 lukem struct ldapmapping *mapping = NULL; 434 1.1 lukem 435 1.1 lukem rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap ); 436 1.1 lukem if ( mapping == NULL ) { 437 1.1 lukem if ( dc->rwmap->rwm_at.drop_missing ) { 438 1.1 lukem return -1; 439 1.1 lukem } 440 1.1 lukem 441 1.1 lukem *mapped_attr = ad->ad_cname; 442 1.1 lukem 443 1.1 lukem } else { 444 1.1 lukem *mapped_attr = mapping->m_dst; 445 1.1 lukem } 446 1.1 lukem 447 1.1 lukem if ( value != NULL ) { 448 1.1 lukem assert( mapped_value != NULL ); 449 1.1 lukem 450 1.1 lukem if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName 451 1.1 lukem || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) 452 1.1 lukem { 453 1.1 lukem dncookie fdc = *dc; 454 1.1 lukem int rc; 455 1.1 lukem 456 1.1 lukem fdc.ctx = "searchFilterAttrDN"; 457 1.1 lukem 458 1.1 lukem vtmp = *value; 459 1.1 lukem rc = rwm_dn_massage_normalize( &fdc, value, &vtmp ); 460 1.1 lukem switch ( rc ) { 461 1.1 lukem case LDAP_SUCCESS: 462 1.1 lukem if ( vtmp.bv_val != value->bv_val ) { 463 1.1 lukem freeval = 1; 464 1.1 lukem } 465 1.1 lukem break; 466 1.1 lukem 467 1.1 lukem case LDAP_UNWILLING_TO_PERFORM: 468 1.1 lukem case LDAP_OTHER: 469 1.1 lukem default: 470 1.1 lukem return -1; 471 1.1 lukem } 472 1.1 lukem 473 1.2 christos } else if ( ad->ad_type->sat_equality && 474 1.2 christos ( ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) ) 475 1.2 christos { 476 1.1 lukem if ( ad->ad_type->sat_equality->smr_normalize( 477 1.1 lukem (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX), 478 1.2 christos NULL, NULL, value, &vtmp, memctx ) ) 479 1.1 lukem { 480 1.1 lukem return -1; 481 1.1 lukem } 482 1.2 christos freeval = 2; 483 1.1 lukem 484 1.1 lukem } else if ( ad == slap_schema.si_ad_objectClass 485 1.1 lukem || ad == slap_schema.si_ad_structuralObjectClass ) 486 1.1 lukem { 487 1.1 lukem rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap ); 488 1.1 lukem if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) { 489 1.1 lukem vtmp = *value; 490 1.1 lukem } 491 1.1 lukem 492 1.1 lukem } else { 493 1.1 lukem vtmp = *value; 494 1.1 lukem } 495 1.1 lukem 496 1.2 christos filter_escape_value_x( &vtmp, mapped_value, memctx ); 497 1.1 lukem 498 1.2 christos switch ( freeval ) { 499 1.2 christos case 1: 500 1.1 lukem ch_free( vtmp.bv_val ); 501 1.2 christos break; 502 1.2 christos 503 1.2 christos case 2: 504 1.2 christos ber_memfree_x( vtmp.bv_val, memctx ); 505 1.2 christos break; 506 1.1 lukem } 507 1.1 lukem } 508 1.1 lukem 509 1.1 lukem if ( mapping != NULL ) { 510 1.1 lukem assert( mapping->m_dst_ad != NULL ); 511 1.1 lukem *adp = mapping->m_dst_ad; 512 1.1 lukem } 513 1.1 lukem 514 1.1 lukem return 0; 515 1.1 lukem } 516 1.1 lukem 517 1.1 lukem static int 518 1.1 lukem rwm_int_filter_map_rewrite( 519 1.1 lukem Operation *op, 520 1.1 lukem dncookie *dc, 521 1.1 lukem Filter *f, 522 1.1 lukem struct berval *fstr ) 523 1.1 lukem { 524 1.1 lukem int i; 525 1.3 christos Filter *p, ftmp; 526 1.1 lukem AttributeDescription *ad; 527 1.1 lukem struct berval atmp, 528 1.1 lukem vtmp, 529 1.1 lukem *tmp; 530 1.1 lukem static struct berval 531 1.1 lukem /* better than nothing... */ 532 1.1 lukem ber_bvfalse = BER_BVC( "(!(objectClass=*))" ), 533 1.1 lukem ber_bvtf_false = BER_BVC( "(|)" ), 534 1.1 lukem /* better than nothing... */ 535 1.1 lukem ber_bvtrue = BER_BVC( "(objectClass=*)" ), 536 1.1 lukem ber_bvtf_true = BER_BVC( "(&)" ), 537 1.1 lukem #if 0 538 1.1 lukem /* no longer needed; preserved for completeness */ 539 1.1 lukem ber_bvundefined = BER_BVC( "(?=undefined)" ), 540 1.1 lukem #endif 541 1.1 lukem ber_bverror = BER_BVC( "(?=error)" ), 542 1.1 lukem ber_bvunknown = BER_BVC( "(?=unknown)" ), 543 1.1 lukem ber_bvnone = BER_BVC( "(?=none)" ); 544 1.1 lukem ber_len_t len; 545 1.1 lukem 546 1.1 lukem assert( fstr != NULL ); 547 1.1 lukem BER_BVZERO( fstr ); 548 1.1 lukem 549 1.1 lukem if ( f == NULL ) { 550 1.2 christos ber_dupbv_x( fstr, &ber_bvnone, op->o_tmpmemctx ); 551 1.1 lukem return LDAP_OTHER; 552 1.1 lukem } 553 1.1 lukem 554 1.2 christos #if 0 555 1.2 christos /* ITS#6814: give the caller a chance to use undefined filters */ 556 1.2 christos if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) { 557 1.2 christos goto computed; 558 1.2 christos } 559 1.2 christos #endif 560 1.2 christos 561 1.1 lukem switch ( f->f_choice & SLAPD_FILTER_MASK ) { 562 1.1 lukem case LDAP_FILTER_EQUALITY: 563 1.1 lukem ad = f->f_av_desc; 564 1.1 lukem if ( map_attr_value( dc, &ad, &atmp, 565 1.2 christos &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) ) 566 1.1 lukem { 567 1.1 lukem goto computed; 568 1.1 lukem } 569 1.1 lukem 570 1.1 lukem fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" ); 571 1.2 christos fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); 572 1.1 lukem 573 1.1 lukem snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)", 574 1.1 lukem atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 575 1.1 lukem 576 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 577 1.1 lukem break; 578 1.1 lukem 579 1.1 lukem case LDAP_FILTER_GE: 580 1.1 lukem ad = f->f_av_desc; 581 1.1 lukem if ( map_attr_value( dc, &ad, &atmp, 582 1.2 christos &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) ) 583 1.1 lukem { 584 1.1 lukem goto computed; 585 1.1 lukem } 586 1.1 lukem 587 1.1 lukem fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" ); 588 1.2 christos fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); 589 1.1 lukem 590 1.1 lukem snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)", 591 1.1 lukem atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 592 1.1 lukem 593 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 594 1.1 lukem break; 595 1.1 lukem 596 1.1 lukem case LDAP_FILTER_LE: 597 1.1 lukem ad = f->f_av_desc; 598 1.1 lukem if ( map_attr_value( dc, &ad, &atmp, 599 1.2 christos &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) ) 600 1.1 lukem { 601 1.1 lukem goto computed; 602 1.1 lukem } 603 1.1 lukem 604 1.1 lukem fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" ); 605 1.2 christos fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); 606 1.1 lukem 607 1.1 lukem snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)", 608 1.1 lukem atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 609 1.1 lukem 610 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 611 1.1 lukem break; 612 1.1 lukem 613 1.1 lukem case LDAP_FILTER_APPROX: 614 1.1 lukem ad = f->f_av_desc; 615 1.1 lukem if ( map_attr_value( dc, &ad, &atmp, 616 1.2 christos &f->f_av_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) ) 617 1.1 lukem { 618 1.1 lukem goto computed; 619 1.1 lukem } 620 1.1 lukem 621 1.1 lukem fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" ); 622 1.2 christos fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); 623 1.1 lukem 624 1.1 lukem snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)", 625 1.1 lukem atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" ); 626 1.1 lukem 627 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 628 1.1 lukem break; 629 1.1 lukem 630 1.1 lukem case LDAP_FILTER_SUBSTRINGS: 631 1.1 lukem ad = f->f_sub_desc; 632 1.1 lukem if ( map_attr_value( dc, &ad, &atmp, 633 1.2 christos NULL, NULL, RWM_MAP, op->o_tmpmemctx ) ) 634 1.1 lukem { 635 1.1 lukem goto computed; 636 1.1 lukem } 637 1.1 lukem 638 1.1 lukem /* cannot be a DN ... */ 639 1.1 lukem 640 1.1 lukem fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" ); 641 1.2 christos fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx ); 642 1.1 lukem 643 1.1 lukem snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)", 644 1.1 lukem atmp.bv_val ); 645 1.1 lukem 646 1.1 lukem if ( !BER_BVISNULL( &f->f_sub_initial ) ) { 647 1.1 lukem len = fstr->bv_len; 648 1.1 lukem 649 1.2 christos filter_escape_value_x( &f->f_sub_initial, &vtmp, op->o_tmpmemctx ); 650 1.1 lukem 651 1.1 lukem fstr->bv_len += vtmp.bv_len; 652 1.2 christos fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, 653 1.2 christos op->o_tmpmemctx ); 654 1.1 lukem 655 1.1 lukem snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3, 656 1.1 lukem /* "(attr=" */ "%s*)", 657 1.1 lukem vtmp.bv_len ? vtmp.bv_val : "" ); 658 1.1 lukem 659 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 660 1.1 lukem } 661 1.1 lukem 662 1.1 lukem if ( f->f_sub_any != NULL ) { 663 1.1 lukem for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) { 664 1.1 lukem len = fstr->bv_len; 665 1.2 christos filter_escape_value_x( &f->f_sub_any[i], &vtmp, 666 1.2 christos op->o_tmpmemctx ); 667 1.1 lukem 668 1.1 lukem fstr->bv_len += vtmp.bv_len + 1; 669 1.2 christos fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, 670 1.2 christos op->o_tmpmemctx ); 671 1.1 lukem 672 1.1 lukem snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3, 673 1.1 lukem /* "(attr=[init]*[any*]" */ "%s*)", 674 1.1 lukem vtmp.bv_len ? vtmp.bv_val : "" ); 675 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 676 1.1 lukem } 677 1.1 lukem } 678 1.1 lukem 679 1.1 lukem if ( !BER_BVISNULL( &f->f_sub_final ) ) { 680 1.1 lukem len = fstr->bv_len; 681 1.1 lukem 682 1.2 christos filter_escape_value_x( &f->f_sub_final, &vtmp, op->o_tmpmemctx ); 683 1.1 lukem 684 1.1 lukem fstr->bv_len += vtmp.bv_len; 685 1.2 christos fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, 686 1.2 christos op->o_tmpmemctx ); 687 1.1 lukem 688 1.1 lukem snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3, 689 1.1 lukem /* "(attr=[init*][any*]" */ "%s)", 690 1.1 lukem vtmp.bv_len ? vtmp.bv_val : "" ); 691 1.1 lukem 692 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 693 1.1 lukem } 694 1.1 lukem 695 1.1 lukem break; 696 1.1 lukem 697 1.1 lukem case LDAP_FILTER_PRESENT: 698 1.1 lukem ad = f->f_desc; 699 1.1 lukem if ( map_attr_value( dc, &ad, &atmp, 700 1.2 christos NULL, NULL, RWM_MAP, op->o_tmpmemctx ) ) 701 1.1 lukem { 702 1.1 lukem goto computed; 703 1.1 lukem } 704 1.1 lukem 705 1.1 lukem fstr->bv_len = atmp.bv_len + STRLENOF( "(=*)" ); 706 1.2 christos fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); 707 1.1 lukem 708 1.1 lukem snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)", 709 1.1 lukem atmp.bv_val ); 710 1.1 lukem break; 711 1.1 lukem 712 1.1 lukem case LDAP_FILTER_AND: 713 1.1 lukem case LDAP_FILTER_OR: 714 1.1 lukem case LDAP_FILTER_NOT: 715 1.1 lukem fstr->bv_len = STRLENOF( "(%)" ); 716 1.2 christos fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx ); 717 1.1 lukem 718 1.1 lukem snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)", 719 1.1 lukem f->f_choice == LDAP_FILTER_AND ? '&' : 720 1.1 lukem f->f_choice == LDAP_FILTER_OR ? '|' : '!' ); 721 1.1 lukem 722 1.1 lukem for ( p = f->f_list; p != NULL; p = p->f_next ) { 723 1.1 lukem int rc; 724 1.1 lukem 725 1.1 lukem len = fstr->bv_len; 726 1.1 lukem 727 1.1 lukem rc = rwm_int_filter_map_rewrite( op, dc, p, &vtmp ); 728 1.1 lukem if ( rc != LDAP_SUCCESS ) { 729 1.1 lukem return rc; 730 1.1 lukem } 731 1.1 lukem 732 1.1 lukem fstr->bv_len += vtmp.bv_len; 733 1.2 christos fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, 734 1.2 christos op->o_tmpmemctx ); 735 1.1 lukem 736 1.1 lukem snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 737 1.1 lukem /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" ); 738 1.1 lukem 739 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 740 1.1 lukem } 741 1.1 lukem 742 1.1 lukem break; 743 1.1 lukem 744 1.1 lukem case LDAP_FILTER_EXT: { 745 1.1 lukem if ( f->f_mr_desc ) { 746 1.1 lukem ad = f->f_mr_desc; 747 1.1 lukem if ( map_attr_value( dc, &ad, &atmp, 748 1.2 christos &f->f_mr_value, &vtmp, RWM_MAP, op->o_tmpmemctx ) ) 749 1.1 lukem { 750 1.1 lukem goto computed; 751 1.1 lukem } 752 1.1 lukem 753 1.1 lukem } else { 754 1.1 lukem BER_BVSTR( &atmp, "" ); 755 1.2 christos filter_escape_value_x( &f->f_mr_value, &vtmp, op->o_tmpmemctx ); 756 1.1 lukem } 757 1.1 lukem 758 1.1 lukem 759 1.1 lukem fstr->bv_len = atmp.bv_len + 760 1.1 lukem ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) + 761 1.1 lukem ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) + 762 1.1 lukem vtmp.bv_len + STRLENOF( "(:=)" ); 763 1.2 christos fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); 764 1.1 lukem 765 1.1 lukem snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)", 766 1.1 lukem atmp.bv_val, 767 1.1 lukem f->f_mr_dnattrs ? ":dn" : "", 768 1.1 lukem !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "", 769 1.1 lukem !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "", 770 1.1 lukem vtmp.bv_len ? vtmp.bv_val : "" ); 771 1.2 christos op->o_tmpfree( vtmp.bv_val, op->o_tmpmemctx ); 772 1.1 lukem break; 773 1.1 lukem } 774 1.1 lukem 775 1.1 lukem case -1: 776 1.1 lukem computed:; 777 1.3 christos f = &ftmp; 778 1.1 lukem f->f_choice = SLAPD_FILTER_COMPUTED; 779 1.1 lukem f->f_result = SLAPD_COMPARE_UNDEFINED; 780 1.1 lukem /* fallthru */ 781 1.1 lukem 782 1.1 lukem case SLAPD_FILTER_COMPUTED: 783 1.1 lukem switch ( f->f_result ) { 784 1.1 lukem case LDAP_COMPARE_FALSE: 785 1.1 lukem /* FIXME: treat UNDEFINED as FALSE */ 786 1.1 lukem case SLAPD_COMPARE_UNDEFINED: 787 1.1 lukem if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) { 788 1.1 lukem tmp = &ber_bvtf_false; 789 1.1 lukem break; 790 1.1 lukem } 791 1.1 lukem tmp = &ber_bvfalse; 792 1.1 lukem break; 793 1.1 lukem 794 1.1 lukem case LDAP_COMPARE_TRUE: 795 1.1 lukem if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) { 796 1.1 lukem tmp = &ber_bvtf_true; 797 1.1 lukem break; 798 1.1 lukem } 799 1.1 lukem tmp = &ber_bvtrue; 800 1.1 lukem break; 801 1.1 lukem 802 1.1 lukem default: 803 1.1 lukem tmp = &ber_bverror; 804 1.1 lukem break; 805 1.1 lukem } 806 1.1 lukem 807 1.2 christos ber_dupbv_x( fstr, tmp, op->o_tmpmemctx ); 808 1.1 lukem break; 809 1.1 lukem 810 1.1 lukem default: 811 1.2 christos ber_dupbv_x( fstr, &ber_bvunknown, op->o_tmpmemctx ); 812 1.1 lukem break; 813 1.1 lukem } 814 1.1 lukem 815 1.1 lukem return LDAP_SUCCESS; 816 1.1 lukem } 817 1.1 lukem 818 1.1 lukem int 819 1.1 lukem rwm_filter_map_rewrite( 820 1.1 lukem Operation *op, 821 1.1 lukem dncookie *dc, 822 1.1 lukem Filter *f, 823 1.1 lukem struct berval *fstr ) 824 1.1 lukem { 825 1.1 lukem int rc; 826 1.1 lukem dncookie fdc; 827 1.1 lukem struct berval ftmp; 828 1.1 lukem 829 1.1 lukem rc = rwm_int_filter_map_rewrite( op, dc, f, fstr ); 830 1.1 lukem 831 1.1 lukem if ( rc != 0 ) { 832 1.1 lukem return rc; 833 1.1 lukem } 834 1.1 lukem 835 1.1 lukem fdc = *dc; 836 1.1 lukem ftmp = *fstr; 837 1.1 lukem 838 1.1 lukem fdc.ctx = "searchFilter"; 839 1.1 lukem 840 1.1 lukem switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx, 841 1.1 lukem ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : "" ), 842 1.1 lukem fdc.conn, &fstr->bv_val ) ) 843 1.1 lukem { 844 1.1 lukem case REWRITE_REGEXEC_OK: 845 1.1 lukem if ( !BER_BVISNULL( fstr ) ) { 846 1.1 lukem fstr->bv_len = strlen( fstr->bv_val ); 847 1.1 lukem 848 1.1 lukem } else { 849 1.1 lukem *fstr = ftmp; 850 1.1 lukem } 851 1.1 lukem 852 1.1 lukem Debug( LDAP_DEBUG_ARGS, 853 1.1 lukem "[rw] %s: \"%s\" -> \"%s\"\n", 854 1.1 lukem fdc.ctx, ftmp.bv_val, fstr->bv_val ); 855 1.2 christos if ( fstr->bv_val != ftmp.bv_val ) { 856 1.2 christos ber_bvreplace_x( &ftmp, fstr, op->o_tmpmemctx ); 857 1.2 christos ch_free( fstr->bv_val ); 858 1.2 christos *fstr = ftmp; 859 1.2 christos } 860 1.1 lukem rc = LDAP_SUCCESS; 861 1.1 lukem break; 862 1.1 lukem 863 1.1 lukem case REWRITE_REGEXEC_UNWILLING: 864 1.1 lukem if ( fdc.rs ) { 865 1.1 lukem fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 866 1.1 lukem fdc.rs->sr_text = "Operation not allowed"; 867 1.1 lukem } 868 1.2 christos op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx ); 869 1.1 lukem rc = LDAP_UNWILLING_TO_PERFORM; 870 1.1 lukem break; 871 1.1 lukem 872 1.1 lukem case REWRITE_REGEXEC_ERR: 873 1.1 lukem if ( fdc.rs ) { 874 1.1 lukem fdc.rs->sr_err = LDAP_OTHER; 875 1.1 lukem fdc.rs->sr_text = "Rewrite error"; 876 1.1 lukem } 877 1.2 christos op->o_tmpfree( ftmp.bv_val, op->o_tmpmemctx ); 878 1.1 lukem rc = LDAP_OTHER; 879 1.1 lukem break; 880 1.1 lukem } 881 1.1 lukem 882 1.1 lukem return rc; 883 1.1 lukem } 884 1.1 lukem 885 1.1 lukem /* 886 1.1 lukem * I don't like this much, but we need two different 887 1.1 lukem * functions because different heap managers may be 888 1.1 lukem * in use in back-ldap/meta to reduce the amount of 889 1.1 lukem * calls to malloc routines, and some of the free() 890 1.1 lukem * routines may be macros with args 891 1.1 lukem */ 892 1.1 lukem int 893 1.1 lukem rwm_referral_rewrite( 894 1.1 lukem Operation *op, 895 1.1 lukem SlapReply *rs, 896 1.1 lukem void *cookie, 897 1.1 lukem BerVarray a_vals, 898 1.1 lukem BerVarray *pa_nvals ) 899 1.1 lukem { 900 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 901 1.1 lukem struct ldaprwmap *rwmap = 902 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private; 903 1.1 lukem 904 1.1 lukem int i, last; 905 1.1 lukem 906 1.1 lukem dncookie dc; 907 1.1 lukem struct berval dn = BER_BVNULL, 908 1.1 lukem ndn = BER_BVNULL; 909 1.1 lukem 910 1.1 lukem assert( a_vals != NULL ); 911 1.1 lukem 912 1.1 lukem /* 913 1.1 lukem * Rewrite the dn if needed 914 1.1 lukem */ 915 1.1 lukem dc.rwmap = rwmap; 916 1.1 lukem dc.conn = op->o_conn; 917 1.1 lukem dc.rs = rs; 918 1.1 lukem dc.ctx = (char *)cookie; 919 1.1 lukem 920 1.1 lukem for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ ) 921 1.1 lukem ; 922 1.1 lukem last--; 923 1.1 lukem 924 1.1 lukem if ( pa_nvals != NULL ) { 925 1.1 lukem if ( *pa_nvals == NULL ) { 926 1.1 lukem *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) ); 927 1.1 lukem memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) ); 928 1.1 lukem } 929 1.1 lukem } 930 1.1 lukem 931 1.1 lukem for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) { 932 1.1 lukem struct berval olddn = BER_BVNULL, 933 1.1 lukem oldval; 934 1.1 lukem int rc; 935 1.1 lukem LDAPURLDesc *ludp; 936 1.1 lukem 937 1.1 lukem oldval = a_vals[i]; 938 1.1 lukem rc = ldap_url_parse( oldval.bv_val, &ludp ); 939 1.1 lukem if ( rc != LDAP_URL_SUCCESS ) { 940 1.1 lukem /* leave attr untouched if massage failed */ 941 1.1 lukem if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) { 942 1.1 lukem ber_dupbv( &(*pa_nvals)[i], &oldval ); 943 1.1 lukem } 944 1.1 lukem continue; 945 1.1 lukem } 946 1.1 lukem 947 1.1 lukem /* FIXME: URLs like "ldap:///dc=suffix" if passed 948 1.1 lukem * thru ldap_url_parse() and ldap_url_desc2str() 949 1.1 lukem * get rewritten as "ldap:///dc=suffix??base"; 950 1.1 lukem * we don't want this to occur... */ 951 1.1 lukem if ( ludp->lud_scope == LDAP_SCOPE_BASE ) { 952 1.1 lukem ludp->lud_scope = LDAP_SCOPE_DEFAULT; 953 1.1 lukem } 954 1.1 lukem 955 1.1 lukem ber_str2bv( ludp->lud_dn, 0, 0, &olddn ); 956 1.1 lukem 957 1.1 lukem dn = olddn; 958 1.1 lukem if ( pa_nvals ) { 959 1.1 lukem ndn = olddn; 960 1.1 lukem rc = rwm_dn_massage_pretty_normalize( &dc, &olddn, 961 1.1 lukem &dn, &ndn ); 962 1.1 lukem } else { 963 1.1 lukem rc = rwm_dn_massage_pretty( &dc, &olddn, &dn ); 964 1.1 lukem } 965 1.1 lukem 966 1.1 lukem switch ( rc ) { 967 1.1 lukem case LDAP_UNWILLING_TO_PERFORM: 968 1.1 lukem /* 969 1.1 lukem * FIXME: need to check if it may be considered 970 1.1 lukem * legal to trim values when adding/modifying; 971 1.1 lukem * it should be when searching (e.g. ACLs). 972 1.1 lukem */ 973 1.1 lukem ch_free( a_vals[i].bv_val ); 974 1.1 lukem if (last > i ) { 975 1.1 lukem a_vals[i] = a_vals[last]; 976 1.1 lukem if ( pa_nvals ) { 977 1.1 lukem (*pa_nvals)[i] = (*pa_nvals)[last]; 978 1.1 lukem } 979 1.1 lukem } 980 1.1 lukem BER_BVZERO( &a_vals[last] ); 981 1.1 lukem if ( pa_nvals ) { 982 1.1 lukem BER_BVZERO( &(*pa_nvals)[last] ); 983 1.1 lukem } 984 1.1 lukem last--; 985 1.1 lukem break; 986 1.1 lukem 987 1.1 lukem case LDAP_SUCCESS: 988 1.1 lukem if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) { 989 1.1 lukem char *newurl; 990 1.1 lukem 991 1.1 lukem ludp->lud_dn = dn.bv_val; 992 1.1 lukem newurl = ldap_url_desc2str( ludp ); 993 1.1 lukem ludp->lud_dn = olddn.bv_val; 994 1.1 lukem ch_free( dn.bv_val ); 995 1.1 lukem if ( newurl == NULL ) { 996 1.1 lukem /* FIXME: leave attr untouched 997 1.1 lukem * even if ldap_url_desc2str failed... 998 1.1 lukem */ 999 1.1 lukem break; 1000 1.1 lukem } 1001 1.1 lukem 1002 1.1 lukem ber_str2bv( newurl, 0, 1, &a_vals[i] ); 1003 1.2 christos ber_memfree( newurl ); 1004 1.1 lukem 1005 1.1 lukem if ( pa_nvals ) { 1006 1.1 lukem ludp->lud_dn = ndn.bv_val; 1007 1.1 lukem newurl = ldap_url_desc2str( ludp ); 1008 1.1 lukem ludp->lud_dn = olddn.bv_val; 1009 1.1 lukem ch_free( ndn.bv_val ); 1010 1.1 lukem if ( newurl == NULL ) { 1011 1.1 lukem /* FIXME: leave attr untouched 1012 1.1 lukem * even if ldap_url_desc2str failed... 1013 1.1 lukem */ 1014 1.1 lukem ch_free( a_vals[i].bv_val ); 1015 1.1 lukem a_vals[i] = oldval; 1016 1.1 lukem break; 1017 1.1 lukem } 1018 1.1 lukem 1019 1.1 lukem if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) { 1020 1.1 lukem ch_free( (*pa_nvals)[i].bv_val ); 1021 1.1 lukem } 1022 1.1 lukem ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] ); 1023 1.2 christos ber_memfree( newurl ); 1024 1.1 lukem } 1025 1.1 lukem 1026 1.1 lukem ch_free( oldval.bv_val ); 1027 1.1 lukem ludp->lud_dn = olddn.bv_val; 1028 1.1 lukem } 1029 1.1 lukem break; 1030 1.1 lukem 1031 1.1 lukem default: 1032 1.1 lukem /* leave attr untouched if massage failed */ 1033 1.1 lukem if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) { 1034 1.1 lukem ber_dupbv( &(*pa_nvals)[i], &a_vals[i] ); 1035 1.1 lukem } 1036 1.1 lukem break; 1037 1.1 lukem } 1038 1.1 lukem ldap_free_urldesc( ludp ); 1039 1.1 lukem } 1040 1.1 lukem 1041 1.1 lukem return 0; 1042 1.1 lukem } 1043 1.1 lukem 1044 1.1 lukem /* 1045 1.1 lukem * I don't like this much, but we need two different 1046 1.1 lukem * functions because different heap managers may be 1047 1.1 lukem * in use in back-ldap/meta to reduce the amount of 1048 1.1 lukem * calls to malloc routines, and some of the free() 1049 1.1 lukem * routines may be macros with args 1050 1.1 lukem */ 1051 1.1 lukem int 1052 1.1 lukem rwm_dnattr_rewrite( 1053 1.1 lukem Operation *op, 1054 1.1 lukem SlapReply *rs, 1055 1.1 lukem void *cookie, 1056 1.1 lukem BerVarray a_vals, 1057 1.1 lukem BerVarray *pa_nvals ) 1058 1.1 lukem { 1059 1.1 lukem slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 1060 1.1 lukem struct ldaprwmap *rwmap = 1061 1.1 lukem (struct ldaprwmap *)on->on_bi.bi_private; 1062 1.1 lukem 1063 1.1 lukem int i, last; 1064 1.1 lukem 1065 1.1 lukem dncookie dc; 1066 1.1 lukem struct berval dn = BER_BVNULL, 1067 1.1 lukem ndn = BER_BVNULL; 1068 1.1 lukem BerVarray in; 1069 1.1 lukem 1070 1.1 lukem if ( a_vals ) { 1071 1.1 lukem in = a_vals; 1072 1.1 lukem 1073 1.1 lukem } else { 1074 1.1 lukem if ( pa_nvals == NULL || *pa_nvals == NULL ) { 1075 1.1 lukem return LDAP_OTHER; 1076 1.1 lukem } 1077 1.1 lukem in = *pa_nvals; 1078 1.1 lukem } 1079 1.1 lukem 1080 1.1 lukem /* 1081 1.1 lukem * Rewrite the dn if needed 1082 1.1 lukem */ 1083 1.1 lukem dc.rwmap = rwmap; 1084 1.1 lukem dc.conn = op->o_conn; 1085 1.1 lukem dc.rs = rs; 1086 1.1 lukem dc.ctx = (char *)cookie; 1087 1.1 lukem 1088 1.1 lukem for ( last = 0; !BER_BVISNULL( &in[last] ); last++ ); 1089 1.1 lukem last--; 1090 1.1 lukem if ( pa_nvals != NULL ) { 1091 1.1 lukem if ( *pa_nvals == NULL ) { 1092 1.1 lukem *pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) ); 1093 1.1 lukem memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) ); 1094 1.1 lukem } 1095 1.1 lukem } 1096 1.1 lukem 1097 1.1 lukem for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) { 1098 1.1 lukem int rc; 1099 1.1 lukem 1100 1.1 lukem if ( a_vals ) { 1101 1.1 lukem dn = in[i]; 1102 1.1 lukem if ( pa_nvals ) { 1103 1.1 lukem ndn = (*pa_nvals)[i]; 1104 1.1 lukem rc = rwm_dn_massage_pretty_normalize( &dc, &in[i], &dn, &ndn ); 1105 1.1 lukem } else { 1106 1.1 lukem rc = rwm_dn_massage_pretty( &dc, &in[i], &dn ); 1107 1.1 lukem } 1108 1.1 lukem } else { 1109 1.1 lukem ndn = in[i]; 1110 1.1 lukem rc = rwm_dn_massage_normalize( &dc, &in[i], &ndn ); 1111 1.1 lukem } 1112 1.1 lukem 1113 1.1 lukem switch ( rc ) { 1114 1.1 lukem case LDAP_UNWILLING_TO_PERFORM: 1115 1.1 lukem /* 1116 1.1 lukem * FIXME: need to check if it may be considered 1117 1.1 lukem * legal to trim values when adding/modifying; 1118 1.1 lukem * it should be when searching (e.g. ACLs). 1119 1.1 lukem */ 1120 1.1 lukem ch_free( in[i].bv_val ); 1121 1.1 lukem if (last > i ) { 1122 1.1 lukem in[i] = in[last]; 1123 1.1 lukem if ( a_vals && pa_nvals ) { 1124 1.1 lukem (*pa_nvals)[i] = (*pa_nvals)[last]; 1125 1.1 lukem } 1126 1.1 lukem } 1127 1.1 lukem BER_BVZERO( &in[last] ); 1128 1.1 lukem if ( a_vals && pa_nvals ) { 1129 1.1 lukem BER_BVZERO( &(*pa_nvals)[last] ); 1130 1.1 lukem } 1131 1.1 lukem last--; 1132 1.1 lukem break; 1133 1.1 lukem 1134 1.1 lukem case LDAP_SUCCESS: 1135 1.1 lukem if ( a_vals ) { 1136 1.1 lukem if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) { 1137 1.1 lukem ch_free( a_vals[i].bv_val ); 1138 1.1 lukem a_vals[i] = dn; 1139 1.1 lukem 1140 1.1 lukem if ( pa_nvals ) { 1141 1.1 lukem if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) { 1142 1.1 lukem ch_free( (*pa_nvals)[i].bv_val ); 1143 1.1 lukem } 1144 1.1 lukem (*pa_nvals)[i] = ndn; 1145 1.1 lukem } 1146 1.1 lukem } 1147 1.1 lukem 1148 1.1 lukem } else { 1149 1.1 lukem if ( !BER_BVISNULL( &ndn ) && ndn.bv_val != (*pa_nvals)[i].bv_val ) { 1150 1.1 lukem ch_free( (*pa_nvals)[i].bv_val ); 1151 1.1 lukem (*pa_nvals)[i] = ndn; 1152 1.1 lukem } 1153 1.1 lukem } 1154 1.1 lukem break; 1155 1.1 lukem 1156 1.1 lukem default: 1157 1.1 lukem /* leave attr untouched if massage failed */ 1158 1.1 lukem if ( a_vals && pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) { 1159 1.1 lukem dnNormalize( 0, NULL, NULL, &a_vals[i], &(*pa_nvals)[i], NULL ); 1160 1.1 lukem } 1161 1.1 lukem break; 1162 1.1 lukem } 1163 1.1 lukem } 1164 1.1 lukem 1165 1.1 lukem return 0; 1166 1.1 lukem } 1167 1.1 lukem 1168 1.1 lukem int 1169 1.1 lukem rwm_referral_result_rewrite( 1170 1.1 lukem dncookie *dc, 1171 1.1 lukem BerVarray a_vals ) 1172 1.1 lukem { 1173 1.1 lukem int i, last; 1174 1.1 lukem 1175 1.1 lukem for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ ); 1176 1.1 lukem last--; 1177 1.1 lukem 1178 1.1 lukem for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) { 1179 1.1 lukem struct berval dn, 1180 1.1 lukem olddn = BER_BVNULL; 1181 1.1 lukem int rc; 1182 1.1 lukem LDAPURLDesc *ludp; 1183 1.1 lukem 1184 1.1 lukem rc = ldap_url_parse( a_vals[i].bv_val, &ludp ); 1185 1.1 lukem if ( rc != LDAP_URL_SUCCESS ) { 1186 1.1 lukem /* leave attr untouched if massage failed */ 1187 1.1 lukem continue; 1188 1.1 lukem } 1189 1.1 lukem 1190 1.1 lukem /* FIXME: URLs like "ldap:///dc=suffix" if passed 1191 1.1 lukem * thru ldap_url_parse() and ldap_url_desc2str() 1192 1.1 lukem * get rewritten as "ldap:///dc=suffix??base"; 1193 1.1 lukem * we don't want this to occur... */ 1194 1.1 lukem if ( ludp->lud_scope == LDAP_SCOPE_BASE ) { 1195 1.1 lukem ludp->lud_scope = LDAP_SCOPE_DEFAULT; 1196 1.1 lukem } 1197 1.1 lukem 1198 1.1 lukem ber_str2bv( ludp->lud_dn, 0, 0, &olddn ); 1199 1.1 lukem 1200 1.1 lukem dn = olddn; 1201 1.1 lukem rc = rwm_dn_massage_pretty( dc, &olddn, &dn ); 1202 1.1 lukem switch ( rc ) { 1203 1.1 lukem case LDAP_UNWILLING_TO_PERFORM: 1204 1.1 lukem /* 1205 1.1 lukem * FIXME: need to check if it may be considered 1206 1.1 lukem * legal to trim values when adding/modifying; 1207 1.1 lukem * it should be when searching (e.g. ACLs). 1208 1.1 lukem */ 1209 1.1 lukem ch_free( a_vals[i].bv_val ); 1210 1.1 lukem if ( last > i ) { 1211 1.1 lukem a_vals[i] = a_vals[last]; 1212 1.1 lukem } 1213 1.1 lukem BER_BVZERO( &a_vals[last] ); 1214 1.1 lukem last--; 1215 1.1 lukem i--; 1216 1.1 lukem break; 1217 1.1 lukem 1218 1.1 lukem default: 1219 1.1 lukem /* leave attr untouched if massage failed */ 1220 1.1 lukem if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) { 1221 1.1 lukem char *newurl; 1222 1.1 lukem 1223 1.1 lukem ludp->lud_dn = dn.bv_val; 1224 1.1 lukem newurl = ldap_url_desc2str( ludp ); 1225 1.1 lukem if ( newurl == NULL ) { 1226 1.1 lukem /* FIXME: leave attr untouched 1227 1.1 lukem * even if ldap_url_desc2str failed... 1228 1.1 lukem */ 1229 1.1 lukem break; 1230 1.1 lukem } 1231 1.1 lukem 1232 1.1 lukem ch_free( a_vals[i].bv_val ); 1233 1.1 lukem ber_str2bv( newurl, 0, 1, &a_vals[i] ); 1234 1.2 christos ber_memfree( newurl ); 1235 1.1 lukem ludp->lud_dn = olddn.bv_val; 1236 1.1 lukem } 1237 1.1 lukem break; 1238 1.1 lukem } 1239 1.1 lukem 1240 1.1 lukem ldap_free_urldesc( ludp ); 1241 1.1 lukem } 1242 1.1 lukem 1243 1.1 lukem return 0; 1244 1.1 lukem } 1245 1.1 lukem 1246 1.1 lukem int 1247 1.1 lukem rwm_dnattr_result_rewrite( 1248 1.1 lukem dncookie *dc, 1249 1.2 christos BerVarray a_vals, 1250 1.2 christos BerVarray a_nvals ) 1251 1.1 lukem { 1252 1.1 lukem int i, last; 1253 1.1 lukem 1254 1.1 lukem for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ ); 1255 1.1 lukem last--; 1256 1.1 lukem 1257 1.1 lukem for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) { 1258 1.2 christos struct berval pdn, ndn = BER_BVNULL; 1259 1.1 lukem int rc; 1260 1.1 lukem 1261 1.2 christos pdn = a_vals[i]; 1262 1.2 christos rc = rwm_dn_massage_pretty_normalize( dc, &a_vals[i], &pdn, &ndn ); 1263 1.1 lukem switch ( rc ) { 1264 1.1 lukem case LDAP_UNWILLING_TO_PERFORM: 1265 1.1 lukem /* 1266 1.1 lukem * FIXME: need to check if it may be considered 1267 1.1 lukem * legal to trim values when adding/modifying; 1268 1.1 lukem * it should be when searching (e.g. ACLs). 1269 1.1 lukem */ 1270 1.2 christos assert( a_vals[i].bv_val != a_nvals[i].bv_val ); 1271 1.1 lukem ch_free( a_vals[i].bv_val ); 1272 1.2 christos ch_free( a_nvals[i].bv_val ); 1273 1.1 lukem if ( last > i ) { 1274 1.1 lukem a_vals[i] = a_vals[last]; 1275 1.2 christos a_nvals[i] = a_nvals[last]; 1276 1.1 lukem } 1277 1.1 lukem BER_BVZERO( &a_vals[last] ); 1278 1.2 christos BER_BVZERO( &a_nvals[last] ); 1279 1.1 lukem last--; 1280 1.1 lukem break; 1281 1.1 lukem 1282 1.1 lukem default: 1283 1.1 lukem /* leave attr untouched if massage failed */ 1284 1.2 christos if ( !BER_BVISNULL( &pdn ) && a_vals[i].bv_val != pdn.bv_val ) { 1285 1.1 lukem ch_free( a_vals[i].bv_val ); 1286 1.2 christos a_vals[i] = pdn; 1287 1.2 christos } 1288 1.2 christos if ( !BER_BVISNULL( &ndn ) && a_nvals[i].bv_val != ndn.bv_val ) { 1289 1.2 christos ch_free( a_nvals[i].bv_val ); 1290 1.2 christos a_nvals[i] = ndn; 1291 1.1 lukem } 1292 1.1 lukem break; 1293 1.1 lukem } 1294 1.1 lukem } 1295 1.1 lukem 1296 1.1 lukem return 0; 1297 1.1 lukem } 1298 1.1 lukem 1299 1.1 lukem void 1300 1.1 lukem rwm_mapping_dst_free( void *v_mapping ) 1301 1.1 lukem { 1302 1.1 lukem struct ldapmapping *mapping = v_mapping; 1303 1.1 lukem 1304 1.1 lukem if ( BER_BVISEMPTY( &mapping[0].m_dst ) ) { 1305 1.1 lukem rwm_mapping_free( &mapping[ -1 ] ); 1306 1.1 lukem } 1307 1.1 lukem } 1308 1.1 lukem 1309 1.1 lukem void 1310 1.1 lukem rwm_mapping_free( void *v_mapping ) 1311 1.1 lukem { 1312 1.1 lukem struct ldapmapping *mapping = v_mapping; 1313 1.1 lukem 1314 1.1 lukem if ( !BER_BVISNULL( &mapping[0].m_src ) ) { 1315 1.1 lukem ch_free( mapping[0].m_src.bv_val ); 1316 1.1 lukem } 1317 1.1 lukem 1318 1.1 lukem if ( mapping[0].m_flags & RWMMAP_F_FREE_SRC ) { 1319 1.1 lukem if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) { 1320 1.1 lukem if ( mapping[0].m_src_oc ) { 1321 1.1 lukem ch_free( mapping[0].m_src_oc ); 1322 1.1 lukem } 1323 1.1 lukem 1324 1.1 lukem } else { 1325 1.1 lukem if ( mapping[0].m_src_ad ) { 1326 1.1 lukem ch_free( mapping[0].m_src_ad ); 1327 1.1 lukem } 1328 1.1 lukem } 1329 1.1 lukem } 1330 1.1 lukem 1331 1.1 lukem if ( !BER_BVISNULL( &mapping[0].m_dst ) ) { 1332 1.1 lukem ch_free( mapping[0].m_dst.bv_val ); 1333 1.1 lukem } 1334 1.1 lukem 1335 1.1 lukem if ( mapping[0].m_flags & RWMMAP_F_FREE_DST ) { 1336 1.1 lukem if ( mapping[0].m_flags & RWMMAP_F_IS_OC ) { 1337 1.1 lukem if ( mapping[0].m_dst_oc ) { 1338 1.1 lukem ch_free( mapping[0].m_dst_oc ); 1339 1.1 lukem } 1340 1.1 lukem 1341 1.1 lukem } else { 1342 1.1 lukem if ( mapping[0].m_dst_ad ) { 1343 1.1 lukem ch_free( mapping[0].m_dst_ad ); 1344 1.1 lukem } 1345 1.1 lukem } 1346 1.1 lukem } 1347 1.1 lukem 1348 1.1 lukem ch_free( mapping ); 1349 1.1 lukem 1350 1.1 lukem } 1351 1.1 lukem 1352 1.1 lukem #endif /* SLAPD_OVER_RWM */ 1353