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