1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 2005-2011 The OpenLDAP Foundation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted only as authorized by the OpenLDAP 9 * Public License. 10 * 11 * A copy of this license is available in the file LICENSE in the 12 * top-level directory of the distribution or, alternatively, at 13 * <http://www.OpenLDAP.org/license.html>. 14 */ 15/* ACKNOWLEDGEMENTS: 16 * This work was initially developed by Luke Howard for inclusion 17 * in OpenLDAP Software. 18 */ 19 20#include "portable.h" 21 22#include <ac/string.h> 23#include <ac/stdarg.h> 24#include <ac/ctype.h> 25#include <ac/unistd.h> 26#include <ldap_pvt.h> 27 28#include <slap.h> 29#include <slapi.h> 30 31#ifdef LDAP_SLAPI 32#define FLAG_DN 0x1 33#define FLAG_NDN 0x2 34 35void slapi_sdn_init( Slapi_DN *sdn ) 36{ 37 sdn->flag = 0; 38 BER_BVZERO( &sdn->dn ); 39 BER_BVZERO( &sdn->ndn ); 40} 41 42Slapi_DN *slapi_sdn_new( void ) 43{ 44 Slapi_DN *sdn; 45 46 sdn = (Slapi_DN *)slapi_ch_malloc( sizeof(*sdn )); 47 slapi_sdn_init( sdn ); 48 49 return sdn; 50} 51 52void slapi_sdn_done( Slapi_DN *sdn ) 53{ 54 if ( sdn == NULL ) 55 return; 56 57 if ( sdn->flag & FLAG_DN ) { 58 slapi_ch_free_string( &sdn->dn.bv_val ); 59 } 60 if ( sdn->flag & FLAG_NDN ) { 61 slapi_ch_free_string( &sdn->ndn.bv_val ); 62 } 63 64 slapi_sdn_init( sdn ); 65} 66 67void slapi_sdn_free( Slapi_DN **sdn ) 68{ 69 slapi_sdn_done( *sdn ); 70 slapi_ch_free( (void **)sdn ); 71} 72 73const char *slapi_sdn_get_dn( const Slapi_DN *sdn ) 74{ 75 if ( !BER_BVISNULL( &sdn->dn ) ) 76 return sdn->dn.bv_val; 77 else 78 return sdn->ndn.bv_val; 79} 80 81const char *slapi_sdn_get_ndn( const Slapi_DN *sdn ) 82{ 83 if ( BER_BVISNULL( &sdn->ndn ) ) { 84 dnNormalize( 0, NULL, NULL, 85 (struct berval *)&sdn->dn, (struct berval *)&sdn->ndn, NULL ); 86 ((Slapi_DN *)sdn)->flag |= FLAG_NDN; 87 } 88 89 return sdn->ndn.bv_val; 90} 91 92Slapi_DN *slapi_sdn_new_dn_byval( const char *dn ) 93{ 94 Slapi_DN *sdn; 95 96 sdn = slapi_sdn_new(); 97 return slapi_sdn_set_dn_byval( sdn, dn ); 98} 99 100Slapi_DN *slapi_sdn_new_ndn_byval( const char *ndn ) 101{ 102 Slapi_DN *sdn; 103 104 sdn = slapi_sdn_new(); 105 return slapi_sdn_set_ndn_byval( sdn, ndn ); 106} 107 108Slapi_DN *slapi_sdn_new_dn_byref( const char *dn ) 109{ 110 Slapi_DN *sdn; 111 112 sdn = slapi_sdn_new(); 113 return slapi_sdn_set_dn_byref( sdn, dn ); 114} 115 116Slapi_DN *slapi_sdn_new_ndn_byref( const char *ndn ) 117{ 118 Slapi_DN *sdn; 119 120 sdn = slapi_sdn_new(); 121 return slapi_sdn_set_ndn_byref( sdn, ndn ); 122} 123 124Slapi_DN *slapi_sdn_new_dn_passin( const char *dn ) 125{ 126 Slapi_DN *sdn; 127 128 sdn = slapi_sdn_new(); 129 return slapi_sdn_set_dn_passin( sdn, dn ); 130} 131 132Slapi_DN *slapi_sdn_set_dn_byval( Slapi_DN *sdn, const char *dn ) 133{ 134 if ( sdn == NULL ) { 135 return NULL; 136 } 137 138 slapi_sdn_done( sdn ); 139 if ( dn != NULL ) { 140 sdn->dn.bv_val = slapi_ch_strdup( dn ); 141 sdn->dn.bv_len = strlen( dn ); 142 } 143 sdn->flag |= FLAG_DN; 144 145 return sdn; 146} 147 148Slapi_DN *slapi_sdn_set_dn_byref( Slapi_DN *sdn, const char *dn ) 149{ 150 if ( sdn == NULL ) 151 return NULL; 152 153 slapi_sdn_done( sdn ); 154 if ( dn != NULL ) { 155 sdn->dn.bv_val = (char *)dn; 156 sdn->dn.bv_len = strlen( dn ); 157 } 158 159 return sdn; 160} 161 162Slapi_DN *slapi_sdn_set_dn_passin( Slapi_DN *sdn, const char *dn ) 163{ 164 if ( sdn == NULL ) 165 return NULL; 166 167 slapi_sdn_set_dn_byref( sdn, dn ); 168 sdn->flag |= FLAG_DN; 169 170 return sdn; 171} 172 173Slapi_DN *slapi_sdn_set_ndn_byval( Slapi_DN *sdn, const char *ndn ) 174{ 175 if ( sdn == NULL ) { 176 return NULL; 177 } 178 179 slapi_sdn_done( sdn ); 180 if ( ndn != NULL ) { 181 sdn->ndn.bv_val = slapi_ch_strdup( ndn ); 182 sdn->ndn.bv_len = strlen( ndn ); 183 } 184 sdn->flag |= FLAG_NDN; 185 186 return sdn; 187} 188 189Slapi_DN *slapi_sdn_set_ndn_byref( Slapi_DN *sdn, const char *ndn ) 190{ 191 if ( sdn == NULL ) 192 return NULL; 193 194 slapi_sdn_done( sdn ); 195 if ( ndn != NULL ) { 196 sdn->ndn.bv_val = (char *)ndn; 197 sdn->ndn.bv_len = strlen( ndn ); 198 } 199 200 return sdn; 201} 202 203Slapi_DN *slapi_sdn_set_ndn_passin( Slapi_DN *sdn, const char *ndn ) 204{ 205 if ( sdn == NULL ) 206 return NULL; 207 208 slapi_sdn_set_ndn_byref( sdn, ndn ); 209 sdn->flag |= FLAG_NDN; 210 211 return sdn; 212} 213 214void slapi_sdn_get_parent( const Slapi_DN *sdn, Slapi_DN *sdn_parent ) 215{ 216 struct berval parent_dn; 217 218 if ( !(sdn->flag & FLAG_DN) ) { 219 dnParent( (struct berval *)&sdn->ndn, &parent_dn ); 220 slapi_sdn_set_ndn_byval( sdn_parent, parent_dn.bv_val ); 221 } else { 222 dnParent( (struct berval *)&sdn->dn, &parent_dn ); 223 slapi_sdn_set_dn_byval( sdn_parent, parent_dn.bv_val ); 224 } 225} 226 227void slapi_sdn_get_backend_parent( const Slapi_DN *sdn, 228 Slapi_DN *sdn_parent, 229 const Slapi_Backend *backend ) 230{ 231 slapi_sdn_get_ndn( sdn ); 232 233 if ( backend == NULL || 234 be_issuffix( (Slapi_Backend *)backend, (struct berval *)&sdn->ndn ) == 0 ) { 235 slapi_sdn_get_parent( sdn, sdn_parent ); 236 } 237 238} 239 240Slapi_DN * slapi_sdn_dup( const Slapi_DN *sdn ) 241{ 242 Slapi_DN *new_sdn; 243 244 new_sdn = slapi_sdn_new(); 245 slapi_sdn_copy( sdn, new_sdn ); 246 247 return new_sdn; 248} 249 250void slapi_sdn_copy( const Slapi_DN *from, Slapi_DN *to ) 251{ 252 slapi_sdn_set_dn_byval( to, from->dn.bv_val ); 253} 254 255int slapi_sdn_compare( const Slapi_DN *sdn1, const Slapi_DN *sdn2 ) 256{ 257 int match = -1; 258 259 slapi_sdn_get_ndn( sdn1 ); 260 slapi_sdn_get_ndn( sdn2 ); 261 262 dnMatch( &match, 0, slap_schema.si_syn_distinguishedName, NULL, 263 (struct berval *)&sdn1->ndn, (void *)&sdn2->ndn ); 264 265 return match; 266} 267 268int slapi_sdn_isempty( const Slapi_DN *sdn) 269{ 270 return ( BER_BVISEMPTY( &sdn->dn ) && BER_BVISEMPTY( &sdn->ndn ) ); 271} 272 273int slapi_sdn_issuffix( const Slapi_DN *sdn, const Slapi_DN *suffix_sdn ) 274{ 275 slapi_sdn_get_ndn( sdn ); 276 slapi_sdn_get_ndn( suffix_sdn ); 277 278 return dnIsSuffix( &sdn->ndn, &suffix_sdn->ndn ); 279} 280 281int slapi_sdn_isparent( const Slapi_DN *parent, const Slapi_DN *child ) 282{ 283 Slapi_DN child_parent; 284 285 slapi_sdn_get_ndn( child ); 286 287 slapi_sdn_init( &child_parent ); 288 dnParent( (struct berval *)&child->ndn, &child_parent.ndn ); 289 290 return ( slapi_sdn_compare( parent, &child_parent ) == 0 ); 291} 292 293int slapi_sdn_isgrandparent( const Slapi_DN *parent, const Slapi_DN *child ) 294{ 295 Slapi_DN child_grandparent; 296 297 slapi_sdn_get_ndn( child ); 298 299 slapi_sdn_init( &child_grandparent ); 300 dnParent( (struct berval *)&child->ndn, &child_grandparent.ndn ); 301 if ( child_grandparent.ndn.bv_len == 0 ) { 302 return 0; 303 } 304 305 dnParent( &child_grandparent.ndn, &child_grandparent.ndn ); 306 307 return ( slapi_sdn_compare( parent, &child_grandparent ) == 0 ); 308} 309 310int slapi_sdn_get_ndn_len( const Slapi_DN *sdn ) 311{ 312 slapi_sdn_get_ndn( sdn ); 313 314 return sdn->ndn.bv_len; 315} 316 317int slapi_sdn_scope_test( const Slapi_DN *dn, const Slapi_DN *base, int scope ) 318{ 319 int rc; 320 321 switch ( scope ) { 322 case LDAP_SCOPE_BASE: 323 rc = ( slapi_sdn_compare( dn, base ) == 0 ); 324 break; 325 case LDAP_SCOPE_ONELEVEL: 326 rc = slapi_sdn_isparent( base, dn ); 327 break; 328 case LDAP_SCOPE_SUBTREE: 329 rc = slapi_sdn_issuffix( dn, base ); 330 break; 331 default: 332 rc = 0; 333 break; 334 } 335 336 return rc; 337} 338 339void slapi_rdn_init( Slapi_RDN *rdn ) 340{ 341 rdn->flag = 0; 342 BER_BVZERO( &rdn->bv ); 343 rdn->rdn = NULL; 344} 345 346Slapi_RDN *slapi_rdn_new( void ) 347{ 348 Slapi_RDN *rdn; 349 350 rdn = (Slapi_RDN *)slapi_ch_malloc( sizeof(*rdn )); 351 slapi_rdn_init( rdn ); 352 353 return rdn; 354} 355 356Slapi_RDN *slapi_rdn_new_dn( const char *dn ) 357{ 358 Slapi_RDN *rdn; 359 360 rdn = slapi_rdn_new(); 361 slapi_rdn_init_dn( rdn, dn ); 362 return rdn; 363} 364 365Slapi_RDN *slapi_rdn_new_sdn( const Slapi_DN *sdn ) 366{ 367 return slapi_rdn_new_dn( slapi_sdn_get_dn( sdn ) ); 368} 369 370Slapi_RDN *slapi_rdn_new_rdn( const Slapi_RDN *fromrdn ) 371{ 372 return slapi_rdn_new_dn( fromrdn->bv.bv_val ); 373} 374 375void slapi_rdn_init_dn( Slapi_RDN *rdn, const char *dn ) 376{ 377 slapi_rdn_init( rdn ); 378 slapi_rdn_set_dn( rdn, dn ); 379} 380 381void slapi_rdn_init_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn ) 382{ 383 slapi_rdn_init( rdn ); 384 slapi_rdn_set_sdn( rdn, sdn ); 385} 386 387void slapi_rdn_init_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn ) 388{ 389 slapi_rdn_init( rdn ); 390 slapi_rdn_set_rdn( rdn, fromrdn ); 391} 392 393void slapi_rdn_set_dn( Slapi_RDN *rdn, const char *dn ) 394{ 395 struct berval bv; 396 397 slapi_rdn_done( rdn ); 398 399 BER_BVZERO( &bv ); 400 401 if ( dn != NULL ) { 402 bv.bv_val = (char *)dn; 403 bv.bv_len = strlen( dn ); 404 } 405 406 dnExtractRdn( &bv, &rdn->bv, NULL ); 407 rdn->flag |= FLAG_DN; 408} 409 410void slapi_rdn_set_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn ) 411{ 412 slapi_rdn_set_dn( rdn, slapi_sdn_get_dn( sdn ) ); 413} 414 415void slapi_rdn_set_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn ) 416{ 417 slapi_rdn_set_dn( rdn, fromrdn->bv.bv_val ); 418} 419 420void slapi_rdn_free( Slapi_RDN **rdn ) 421{ 422 slapi_rdn_done( *rdn ); 423 slapi_ch_free( (void **)rdn ); 424} 425 426void slapi_rdn_done( Slapi_RDN *rdn ) 427{ 428 if ( rdn->rdn != NULL ) { 429 ldap_rdnfree( rdn->rdn ); 430 rdn->rdn = NULL; 431 } 432 slapi_ch_free_string( &rdn->bv.bv_val ); 433 slapi_rdn_init( rdn ); 434} 435 436const char *slapi_rdn_get_rdn( const Slapi_RDN *rdn ) 437{ 438 return rdn->bv.bv_val; 439} 440 441static int slapi_int_rdn_explode( Slapi_RDN *rdn ) 442{ 443 char *next; 444 445 if ( rdn->rdn != NULL ) { 446 return LDAP_SUCCESS; 447 } 448 449 return ldap_bv2rdn( &rdn->bv, &rdn->rdn, &next, LDAP_DN_FORMAT_LDAP ); 450} 451 452static int slapi_int_rdn_implode( Slapi_RDN *rdn ) 453{ 454 struct berval bv; 455 int rc; 456 457 if ( rdn->rdn == NULL ) { 458 return LDAP_SUCCESS; 459 } 460 461 rc = ldap_rdn2bv( rdn->rdn, &bv, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY ); 462 if ( rc != LDAP_SUCCESS ) { 463 return rc; 464 } 465 466 slapi_ch_free_string( &rdn->bv.bv_val ); 467 rdn->bv = bv; 468 469 return 0; 470} 471 472int slapi_rdn_get_num_components( Slapi_RDN *rdn ) 473{ 474 int i; 475 476 if ( slapi_int_rdn_explode( rdn ) != LDAP_SUCCESS ) 477 return 0; 478 479 for ( i = 0; rdn->rdn[i] != NULL; i++ ) 480 ; 481 482 return i; 483} 484 485int slapi_rdn_get_first( Slapi_RDN *rdn, char **type, char **value ) 486{ 487 return slapi_rdn_get_next( rdn, 0, type, value ); 488} 489 490int slapi_rdn_get_next( Slapi_RDN *rdn, int index, char **type, char **value ) 491{ 492 slapi_int_rdn_explode( rdn ); 493 494 if ( rdn->rdn == NULL || rdn->rdn[index] == NULL ) 495 return -1; 496 497 *type = rdn->rdn[index]->la_attr.bv_val; 498 *value = rdn->rdn[index]->la_value.bv_val; 499 500 return index + 1; 501} 502 503int slapi_rdn_get_index( Slapi_RDN *rdn, const char *type, const char *value, size_t length ) 504{ 505 int i, match; 506 struct berval bv; 507 AttributeDescription *ad = NULL; 508 const char *text; 509 510 slapi_int_rdn_explode( rdn ); 511 512 if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) { 513 return -1; 514 } 515 516 bv.bv_val = (char *)value; 517 bv.bv_len = length; 518 519 for ( i = 0; rdn->rdn[i] != NULL; i++ ) { 520 if ( !slapi_attr_types_equivalent( ad->ad_cname.bv_val, type )) 521 continue; 522 523 if ( value_match( &match, ad, ad->ad_type->sat_equality, 0, 524 &rdn->rdn[i]->la_value, (void *)&bv, &text ) != LDAP_SUCCESS ) 525 match = -1; 526 527 if ( match == 0 ) 528 return i; 529 } 530 531 return -1; 532} 533 534int slapi_rdn_get_index_attr( Slapi_RDN *rdn, const char *type, char **value ) 535{ 536 int i; 537 538 for ( i = 0; rdn->rdn[i] != NULL; i++ ) { 539 if ( slapi_attr_types_equivalent( rdn->rdn[i]->la_attr.bv_val, type ) ) { 540 *value = rdn->rdn[i]->la_value.bv_val; 541 return i; 542 } 543 } 544 545 return -1; 546} 547 548int slapi_rdn_contains( Slapi_RDN *rdn, const char *type, const char *value, size_t length ) 549{ 550 return ( slapi_rdn_get_index( rdn, type, value, length ) != -1 ); 551} 552 553int slapi_rdn_contains_attr( Slapi_RDN *rdn, const char *type, char **value ) 554{ 555 return ( slapi_rdn_get_index_attr( rdn, type, value ) != -1 ); 556} 557 558int slapi_rdn_compare( Slapi_RDN *rdn1, Slapi_RDN *rdn2 ) 559{ 560 struct berval nrdn1 = BER_BVNULL; 561 struct berval nrdn2 = BER_BVNULL; 562 int match; 563 564 rdnNormalize( 0, NULL, NULL, (struct berval *)&rdn1->bv, &nrdn1, NULL ); 565 rdnNormalize( 0, NULL, NULL, (struct berval *)&rdn2->bv, &nrdn2, NULL ); 566 567 if ( rdnMatch( &match, 0, NULL, NULL, &nrdn1, (void *)&nrdn2 ) != LDAP_SUCCESS) { 568 match = -1; 569 } 570 571 return match; 572} 573 574int slapi_rdn_isempty( const Slapi_RDN *rdn ) 575{ 576 return ( BER_BVISEMPTY( &rdn->bv ) ); 577} 578 579int slapi_rdn_add( Slapi_RDN *rdn, const char *type, const char *value ) 580{ 581 char *s; 582 size_t len; 583 584 len = strlen(type) + 1 + strlen( value ); 585 if ( !BER_BVISEMPTY( &rdn->bv ) ) { 586 len += 1 + rdn->bv.bv_len; 587 } 588 589 s = slapi_ch_malloc( len + 1 ); 590 591 if ( BER_BVISEMPTY( &rdn->bv ) ) { 592 snprintf( s, len + 1, "%s=%s", type, value ); 593 } else { 594 snprintf( s, len + 1, "%s=%s+%s", type, value, rdn->bv.bv_val ); 595 } 596 597 slapi_rdn_done( rdn ); 598 599 rdn->bv.bv_len = len; 600 rdn->bv.bv_val = s; 601 602 return 1; 603} 604 605int slapi_rdn_remove_index( Slapi_RDN *rdn, int atindex ) 606{ 607 int count, i; 608 609 count = slapi_rdn_get_num_components( rdn ); 610 611 if ( atindex < 0 || atindex >= count ) 612 return 0; 613 614 if ( rdn->rdn == NULL ) 615 return 0; 616 617 slapi_ch_free_string( &rdn->rdn[atindex]->la_attr.bv_val ); 618 slapi_ch_free_string( &rdn->rdn[atindex]->la_value.bv_val ); 619 620 for ( i = atindex; i < count; i++ ) { 621 rdn->rdn[i] = rdn->rdn[i + 1]; 622 } 623 624 if ( slapi_int_rdn_implode( rdn ) != LDAP_SUCCESS ) 625 return 0; 626 627 return 1; 628} 629 630int slapi_rdn_remove( Slapi_RDN *rdn, const char *type, const char *value, size_t length ) 631{ 632 int index = slapi_rdn_get_index( rdn, type, value, length ); 633 634 return slapi_rdn_remove_index( rdn, index ); 635} 636 637int slapi_rdn_remove_attr( Slapi_RDN *rdn, const char *type ) 638{ 639 char *value; 640 int index = slapi_rdn_get_index_attr( rdn, type, &value ); 641 642 return slapi_rdn_remove_index( rdn, index ); 643} 644 645Slapi_DN *slapi_sdn_add_rdn( Slapi_DN *sdn, const Slapi_RDN *rdn ) 646{ 647 struct berval bv; 648 649 build_new_dn( &bv, &sdn->dn, (struct berval *)&rdn->bv, NULL ); 650 651 slapi_sdn_done( sdn ); 652 sdn->dn = bv; 653 654 return sdn; 655} 656 657Slapi_DN *slapi_sdn_set_parent( Slapi_DN *sdn, const Slapi_DN *parentdn ) 658{ 659 Slapi_RDN rdn; 660 661 slapi_rdn_init_sdn( &rdn, sdn ); 662 slapi_sdn_set_dn_byref( sdn, slapi_sdn_get_dn( parentdn ) ); 663 slapi_sdn_add_rdn( sdn, &rdn ); 664 slapi_rdn_done( &rdn ); 665 666 return sdn; 667} 668 669#endif /* LDAP_SLAPI */ 670