1 /* $NetBSD: dn.c,v 1.3 2021/08/14 16:14:58 christos Exp $ */ 2 3 /* dn.c - routines for dealing with distinguished names */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2021 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that this notice is preserved and that due credit is given 23 * to the University of Michigan at Ann Arbor. The name of the University 24 * may not be used to endorse or promote products derived from this 25 * software without specific prior written permission. This software 26 * is provided ``as is'' without express or implied warranty. 27 */ 28 29 #include <sys/cdefs.h> 30 __RCSID("$NetBSD: dn.c,v 1.3 2021/08/14 16:14:58 christos Exp $"); 31 32 #include "portable.h" 33 34 #include <stdio.h> 35 36 #include <ac/ctype.h> 37 #include <ac/socket.h> 38 #include <ac/string.h> 39 #include <ac/time.h> 40 41 #include "slap.h" 42 #include "lutil.h" 43 44 /* 45 * The DN syntax-related functions take advantage of the dn representation 46 * handling functions ldap_str2dn/ldap_dn2str. The latter are not schema- 47 * aware, so the attributes and their values need be validated (and possibly 48 * normalized). In the current implementation the required validation/nor- 49 * malization/"pretty"ing are done on newly created DN structural represen- 50 * tations; however the idea is to move towards DN handling in structural 51 * representation instead of the current string representation. To this 52 * purpose, we need to do only the required operations and keep track of 53 * what has been done to minimize their impact on performances. 54 * 55 * Developers are strongly encouraged to use this feature, to speed-up 56 * its stabilization. 57 */ 58 59 #define AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private ) 60 61 int slap_DN_strict = SLAP_AD_NOINSERT; 62 63 static int 64 LDAPRDN_validate( LDAPRDN rdn ) 65 { 66 int iAVA; 67 int rc; 68 69 assert( rdn != NULL ); 70 71 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 72 LDAPAVA *ava = rdn[ iAVA ]; 73 AttributeDescription *ad; 74 slap_syntax_validate_func *validate = NULL; 75 76 assert( ava != NULL ); 77 78 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) { 79 const char *text = NULL; 80 81 rc = slap_bv2ad( &ava->la_attr, &ad, &text ); 82 if ( rc != LDAP_SUCCESS ) { 83 rc = slap_bv2undef_ad( &ava->la_attr, 84 &ad, &text, 85 SLAP_AD_PROXIED|slap_DN_strict ); 86 if ( rc != LDAP_SUCCESS ) { 87 return LDAP_INVALID_SYNTAX; 88 } 89 } 90 91 ava->la_private = ( void * )ad; 92 } 93 94 /* 95 * Do not allow X-ORDERED 'VALUES' naming attributes 96 */ 97 if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) { 98 return LDAP_INVALID_SYNTAX; 99 } 100 101 /* 102 * Replace attr oid/name with the canonical name 103 */ 104 ava->la_attr = ad->ad_cname; 105 106 validate = ad->ad_type->sat_syntax->ssyn_validate; 107 108 if ( validate ) { 109 /* 110 * validate value by validate function 111 */ 112 rc = ( *validate )( ad->ad_type->sat_syntax, 113 &ava->la_value ); 114 115 if ( rc != LDAP_SUCCESS ) { 116 return LDAP_INVALID_SYNTAX; 117 } 118 } 119 } 120 121 return LDAP_SUCCESS; 122 } 123 124 /* 125 * In-place, schema-aware validation of the 126 * structural representation of a distinguished name. 127 */ 128 static int 129 LDAPDN_validate( LDAPDN dn ) 130 { 131 int iRDN; 132 int rc; 133 134 assert( dn != NULL ); 135 136 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) { 137 rc = LDAPRDN_validate( dn[ iRDN ] ); 138 if ( rc != LDAP_SUCCESS ) { 139 return rc; 140 } 141 } 142 143 return LDAP_SUCCESS; 144 } 145 146 /* 147 * dn validate routine 148 */ 149 int 150 dnValidate( 151 Syntax *syntax, 152 struct berval *in ) 153 { 154 int rc; 155 LDAPDN dn = NULL; 156 157 assert( in != NULL ); 158 159 if ( in->bv_len == 0 ) { 160 return LDAP_SUCCESS; 161 162 } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) { 163 return LDAP_INVALID_SYNTAX; 164 } 165 166 rc = ldap_bv2dn( in, &dn, LDAP_DN_FORMAT_LDAP ); 167 if ( rc != LDAP_SUCCESS ) { 168 return LDAP_INVALID_SYNTAX; 169 } 170 171 assert( strlen( in->bv_val ) == in->bv_len ); 172 173 /* 174 * Schema-aware validate 175 */ 176 rc = LDAPDN_validate( dn ); 177 ldap_dnfree( dn ); 178 179 if ( rc != LDAP_SUCCESS ) { 180 return LDAP_INVALID_SYNTAX; 181 } 182 183 return LDAP_SUCCESS; 184 } 185 186 int 187 rdnValidate( 188 Syntax *syntax, 189 struct berval *in ) 190 { 191 int rc; 192 LDAPRDN rdn; 193 char* p; 194 195 assert( in != NULL ); 196 if ( in->bv_len == 0 ) { 197 return LDAP_SUCCESS; 198 199 } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) { 200 return LDAP_INVALID_SYNTAX; 201 } 202 203 rc = ldap_bv2rdn_x( in , &rdn, (char **) &p, 204 LDAP_DN_FORMAT_LDAP, NULL); 205 if ( rc != LDAP_SUCCESS ) { 206 return LDAP_INVALID_SYNTAX; 207 } 208 209 assert( strlen( in->bv_val ) == in->bv_len ); 210 211 /* 212 * Schema-aware validate 213 */ 214 rc = LDAPRDN_validate( rdn ); 215 ldap_rdnfree( rdn ); 216 217 if ( rc != LDAP_SUCCESS ) { 218 return LDAP_INVALID_SYNTAX; 219 } 220 221 return LDAP_SUCCESS; 222 } 223 224 225 /* 226 * AVA sorting inside a RDN 227 * 228 * Rule: sort attributeTypes in alphabetical order. 229 * 230 * Note: the sorting can be slightly improved by sorting first 231 * by attribute type length, then by alphabetical order. 232 * 233 * uses an insertion sort; should be fine since the number of AVAs in 234 * a RDN should be limited. 235 */ 236 static int 237 AVA_Sort( LDAPRDN rdn, int nAVAs ) 238 { 239 LDAPAVA *ava_i; 240 int i; 241 int rc = LDAP_SUCCESS; 242 243 assert( rdn != NULL ); 244 245 for ( i = 1; i < nAVAs; i++ ) { 246 LDAPAVA *ava_j; 247 int j; 248 249 ava_i = rdn[ i ]; 250 for ( j = i-1; j >=0; j-- ) { 251 int a; 252 253 ava_j = rdn[ j ]; 254 a = strcmp( ava_i->la_attr.bv_val, ava_j->la_attr.bv_val ); 255 256 /* RFC4512 does not allow multiple AVAs 257 * with the same attribute type in RDN (ITS#5968) */ 258 if ( a == 0 ) 259 rc = LDAP_INVALID_DN_SYNTAX; 260 261 if ( a > 0 ) 262 break; 263 264 rdn[ j+1 ] = rdn[ j ]; 265 } 266 rdn[ j+1 ] = ava_i; 267 } 268 return rc; 269 } 270 271 static int 272 LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx ) 273 { 274 275 int rc, iAVA, do_sort = 0; 276 277 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { 278 LDAPAVA *ava = rdn[ iAVA ]; 279 AttributeDescription *ad; 280 slap_syntax_validate_func *validf = NULL; 281 slap_mr_normalize_func *normf = NULL; 282 slap_syntax_transform_func *transf = NULL; 283 MatchingRule *mr = NULL; 284 struct berval bv = BER_BVNULL; 285 286 assert( ava != NULL ); 287 288 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) { 289 const char *text = NULL; 290 291 rc = slap_bv2ad( &ava->la_attr, &ad, &text ); 292 if ( rc != LDAP_SUCCESS ) { 293 rc = slap_bv2undef_ad( &ava->la_attr, 294 &ad, &text, 295 SLAP_AD_PROXIED|slap_DN_strict ); 296 if ( rc != LDAP_SUCCESS ) { 297 return LDAP_INVALID_SYNTAX; 298 } 299 } 300 301 ava->la_private = ( void * )ad; 302 do_sort = 1; 303 } 304 305 /* 306 * Replace attr oid/name with the canonical name 307 */ 308 ava->la_attr = ad->ad_cname; 309 310 if( ava->la_flags & LDAP_AVA_BINARY ) { 311 /* AVA is binary encoded, not supported */ 312 return LDAP_INVALID_SYNTAX; 313 314 /* Do not allow X-ORDERED 'VALUES' naming attributes */ 315 } else if( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) { 316 return LDAP_INVALID_SYNTAX; 317 318 } else if( flags & SLAP_LDAPDN_PRETTY ) { 319 transf = ad->ad_type->sat_syntax->ssyn_pretty; 320 if( !transf ) { 321 validf = ad->ad_type->sat_syntax->ssyn_validate; 322 } 323 } else { /* normalization */ 324 validf = ad->ad_type->sat_syntax->ssyn_validate; 325 mr = ad->ad_type->sat_equality; 326 if( mr && (!( mr->smr_usage & SLAP_MR_MUTATION_NORMALIZER ))) { 327 normf = mr->smr_normalize; 328 } 329 } 330 331 if ( validf ) { 332 /* validate value before normalization */ 333 rc = ( *validf )( ad->ad_type->sat_syntax, 334 ava->la_value.bv_len 335 ? &ava->la_value 336 : (struct berval *) &slap_empty_bv ); 337 338 if ( rc != LDAP_SUCCESS ) { 339 return LDAP_INVALID_SYNTAX; 340 } 341 } 342 343 if ( transf ) { 344 /* 345 * transform value by pretty function 346 * if value is empty, use empty_bv 347 */ 348 rc = ( *transf )( ad->ad_type->sat_syntax, 349 ava->la_value.bv_len 350 ? &ava->la_value 351 : (struct berval *) &slap_empty_bv, 352 &bv, ctx ); 353 354 if ( rc != LDAP_SUCCESS ) { 355 return LDAP_INVALID_SYNTAX; 356 } 357 } 358 359 if ( normf ) { 360 /* 361 * normalize value 362 * if value is empty, use empty_bv 363 */ 364 rc = ( *normf )( 365 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, 366 ad->ad_type->sat_syntax, 367 mr, 368 ava->la_value.bv_len 369 ? &ava->la_value 370 : (struct berval *) &slap_empty_bv, 371 &bv, ctx ); 372 373 if ( rc != LDAP_SUCCESS ) { 374 return LDAP_INVALID_SYNTAX; 375 } 376 } 377 378 379 if( bv.bv_val ) { 380 if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) 381 ber_memfree_x( ava->la_value.bv_val, ctx ); 382 ava->la_value = bv; 383 ava->la_flags |= LDAP_AVA_FREE_VALUE; 384 } 385 /* reject empty values */ 386 if (!ava->la_value.bv_len) { 387 return LDAP_INVALID_SYNTAX; 388 } 389 } 390 rc = LDAP_SUCCESS; 391 392 if ( do_sort ) { 393 rc = AVA_Sort( rdn, iAVA ); 394 } 395 396 return rc; 397 } 398 399 /* 400 * In-place, schema-aware normalization / "pretty"ing of the 401 * structural representation of a distinguished name. 402 */ 403 static int 404 LDAPDN_rewrite( LDAPDN dn, unsigned flags, void *ctx ) 405 { 406 int iRDN; 407 int rc; 408 409 assert( dn != NULL ); 410 411 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) { 412 rc = LDAPRDN_rewrite( dn[ iRDN ], flags, ctx ); 413 if ( rc != LDAP_SUCCESS ) { 414 return rc; 415 } 416 } 417 418 return LDAP_SUCCESS; 419 } 420 421 int 422 dnNormalize( 423 slap_mask_t use, 424 Syntax *syntax, 425 MatchingRule *mr, 426 struct berval *val, 427 struct berval *out, 428 void *ctx) 429 { 430 assert( val != NULL ); 431 assert( out != NULL ); 432 433 Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val ? val->bv_val : "" ); 434 435 if ( val->bv_len != 0 ) { 436 LDAPDN dn = NULL; 437 int rc; 438 439 /* 440 * Go to structural representation 441 */ 442 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); 443 if ( rc != LDAP_SUCCESS ) { 444 return LDAP_INVALID_SYNTAX; 445 } 446 447 assert( strlen( val->bv_val ) == val->bv_len ); 448 449 /* 450 * Schema-aware rewrite 451 */ 452 if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) { 453 ldap_dnfree_x( dn, ctx ); 454 return LDAP_INVALID_SYNTAX; 455 } 456 457 /* 458 * Back to string representation 459 */ 460 rc = ldap_dn2bv_x( dn, out, 461 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); 462 463 ldap_dnfree_x( dn, ctx ); 464 465 if ( rc != LDAP_SUCCESS ) { 466 return LDAP_INVALID_SYNTAX; 467 } 468 } else { 469 ber_dupbv_x( out, val, ctx ); 470 } 471 472 Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val ? out->bv_val : "" ); 473 474 return LDAP_SUCCESS; 475 } 476 477 int 478 rdnNormalize( 479 slap_mask_t use, 480 Syntax *syntax, 481 MatchingRule *mr, 482 struct berval *val, 483 struct berval *out, 484 void *ctx) 485 { 486 assert( val != NULL ); 487 assert( out != NULL ); 488 489 Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val ? val->bv_val : "" ); 490 if ( val->bv_len != 0 ) { 491 LDAPRDN rdn = NULL; 492 int rc; 493 char* p; 494 495 /* 496 * Go to structural representation 497 */ 498 rc = ldap_bv2rdn_x( val , &rdn, (char **) &p, 499 LDAP_DN_FORMAT_LDAP, ctx); 500 501 if ( rc != LDAP_SUCCESS ) { 502 return LDAP_INVALID_SYNTAX; 503 } 504 505 assert( strlen( val->bv_val ) == val->bv_len ); 506 507 /* 508 * Schema-aware rewrite 509 */ 510 if ( LDAPRDN_rewrite( rdn, 0, ctx ) != LDAP_SUCCESS ) { 511 ldap_rdnfree_x( rdn, ctx ); 512 return LDAP_INVALID_SYNTAX; 513 } 514 515 /* 516 * Back to string representation 517 */ 518 rc = ldap_rdn2bv_x( rdn, out, 519 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); 520 521 ldap_rdnfree_x( rdn, ctx ); 522 523 if ( rc != LDAP_SUCCESS ) { 524 return LDAP_INVALID_SYNTAX; 525 } 526 } else { 527 ber_dupbv_x( out, val, ctx ); 528 } 529 530 Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val ? out->bv_val : "" ); 531 532 return LDAP_SUCCESS; 533 } 534 535 int 536 dnPretty( 537 Syntax *syntax, 538 struct berval *val, 539 struct berval *out, 540 void *ctx) 541 { 542 assert( val != NULL ); 543 assert( out != NULL ); 544 545 Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val ? val->bv_val : "" ); 546 547 if ( val->bv_len == 0 ) { 548 ber_dupbv_x( out, val, ctx ); 549 550 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { 551 return LDAP_INVALID_SYNTAX; 552 553 } else { 554 LDAPDN dn = NULL; 555 int rc; 556 557 /* FIXME: should be liberal in what we accept */ 558 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); 559 if ( rc != LDAP_SUCCESS ) { 560 return LDAP_INVALID_SYNTAX; 561 } 562 563 assert( strlen( val->bv_val ) == val->bv_len ); 564 565 /* 566 * Schema-aware rewrite 567 */ 568 if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) { 569 ldap_dnfree_x( dn, ctx ); 570 return LDAP_INVALID_SYNTAX; 571 } 572 573 /* FIXME: not sure why the default isn't pretty */ 574 /* RE: the default is the form that is used as 575 * an internal representation; the pretty form 576 * is a variant */ 577 rc = ldap_dn2bv_x( dn, out, 578 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); 579 580 ldap_dnfree_x( dn, ctx ); 581 582 if ( rc != LDAP_SUCCESS ) { 583 return LDAP_INVALID_SYNTAX; 584 } 585 } 586 587 Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val ? out->bv_val : "" ); 588 589 return LDAP_SUCCESS; 590 } 591 592 int 593 rdnPretty( 594 Syntax *syntax, 595 struct berval *val, 596 struct berval *out, 597 void *ctx) 598 { 599 assert( val != NULL ); 600 assert( out != NULL ); 601 602 Debug( LDAP_DEBUG_TRACE, ">>> rdnPretty: <%s>\n", val->bv_val ? val->bv_val : "" ); 603 604 if ( val->bv_len == 0 ) { 605 ber_dupbv_x( out, val, ctx ); 606 607 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { 608 return LDAP_INVALID_SYNTAX; 609 610 } else { 611 LDAPRDN rdn = NULL; 612 int rc; 613 char* p; 614 615 /* FIXME: should be liberal in what we accept */ 616 rc = ldap_bv2rdn_x( val , &rdn, (char **) &p, 617 LDAP_DN_FORMAT_LDAP, ctx); 618 if ( rc != LDAP_SUCCESS ) { 619 return LDAP_INVALID_SYNTAX; 620 } 621 622 assert( strlen( val->bv_val ) == val->bv_len ); 623 624 /* 625 * Schema-aware rewrite 626 */ 627 if ( LDAPRDN_rewrite( rdn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) { 628 ldap_rdnfree_x( rdn, ctx ); 629 return LDAP_INVALID_SYNTAX; 630 } 631 632 /* FIXME: not sure why the default isn't pretty */ 633 /* RE: the default is the form that is used as 634 * an internal representation; the pretty form 635 * is a variant */ 636 rc = ldap_rdn2bv_x( rdn, out, 637 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); 638 639 ldap_rdnfree_x( rdn, ctx ); 640 641 if ( rc != LDAP_SUCCESS ) { 642 return LDAP_INVALID_SYNTAX; 643 } 644 } 645 646 Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val ? out->bv_val : "" ); 647 648 return LDAP_SUCCESS; 649 } 650 651 652 int 653 dnPrettyNormalDN( 654 Syntax *syntax, 655 struct berval *val, 656 LDAPDN *dn, 657 int flags, 658 void *ctx ) 659 { 660 assert( val != NULL ); 661 assert( dn != NULL ); 662 663 Debug( LDAP_DEBUG_TRACE, ">>> dn%sDN: <%s>\n", 664 flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal", 665 val->bv_val ? val->bv_val : "" ); 666 667 if ( val->bv_len == 0 ) { 668 return LDAP_SUCCESS; 669 670 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { 671 return LDAP_INVALID_SYNTAX; 672 673 } else { 674 int rc; 675 676 /* FIXME: should be liberal in what we accept */ 677 rc = ldap_bv2dn_x( val, dn, LDAP_DN_FORMAT_LDAP, ctx ); 678 if ( rc != LDAP_SUCCESS ) { 679 return LDAP_INVALID_SYNTAX; 680 } 681 682 assert( strlen( val->bv_val ) == val->bv_len ); 683 684 /* 685 * Schema-aware rewrite 686 */ 687 if ( LDAPDN_rewrite( *dn, flags, ctx ) != LDAP_SUCCESS ) { 688 ldap_dnfree_x( *dn, ctx ); 689 *dn = NULL; 690 return LDAP_INVALID_SYNTAX; 691 } 692 } 693 694 Debug( LDAP_DEBUG_TRACE, "<<< dn%sDN\n", 695 flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal" ); 696 697 return LDAP_SUCCESS; 698 } 699 700 /* 701 * Combination of both dnPretty and dnNormalize 702 */ 703 int 704 dnPrettyNormal( 705 Syntax *syntax, 706 struct berval *val, 707 struct berval *pretty, 708 struct berval *normal, 709 void *ctx) 710 { 711 assert( val != NULL ); 712 assert( pretty != NULL ); 713 assert( normal != NULL ); 714 Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val ? val->bv_val : "" ); 715 716 if ( val->bv_len == 0 ) { 717 ber_dupbv_x( pretty, val, ctx ); 718 ber_dupbv_x( normal, val, ctx ); 719 720 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { 721 /* too big */ 722 return LDAP_INVALID_SYNTAX; 723 724 } else { 725 LDAPDN dn = NULL; 726 int rc; 727 728 pretty->bv_val = NULL; 729 normal->bv_val = NULL; 730 pretty->bv_len = 0; 731 normal->bv_len = 0; 732 733 /* FIXME: should be liberal in what we accept */ 734 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); 735 if ( rc != LDAP_SUCCESS ) { 736 return LDAP_INVALID_SYNTAX; 737 } 738 739 assert( strlen( val->bv_val ) == val->bv_len ); 740 741 /* 742 * Schema-aware rewrite 743 */ 744 if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) { 745 ldap_dnfree_x( dn, ctx ); 746 return LDAP_INVALID_SYNTAX; 747 } 748 749 rc = ldap_dn2bv_x( dn, pretty, 750 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); 751 752 if ( rc != LDAP_SUCCESS ) { 753 ldap_dnfree_x( dn, ctx ); 754 return LDAP_INVALID_SYNTAX; 755 } 756 757 if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) { 758 ldap_dnfree_x( dn, ctx ); 759 ber_memfree_x( pretty->bv_val, ctx ); 760 pretty->bv_val = NULL; 761 pretty->bv_len = 0; 762 return LDAP_INVALID_SYNTAX; 763 } 764 765 rc = ldap_dn2bv_x( dn, normal, 766 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); 767 768 ldap_dnfree_x( dn, ctx ); 769 if ( rc != LDAP_SUCCESS ) { 770 ber_memfree_x( pretty->bv_val, ctx ); 771 pretty->bv_val = NULL; 772 pretty->bv_len = 0; 773 return LDAP_INVALID_SYNTAX; 774 } 775 } 776 777 Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n", 778 pretty->bv_val ? pretty->bv_val : "", 779 normal->bv_val ? normal->bv_val : "" ); 780 781 return LDAP_SUCCESS; 782 } 783 784 /* 785 * dnMatch routine 786 */ 787 int 788 dnMatch( 789 int *matchp, 790 slap_mask_t flags, 791 Syntax *syntax, 792 MatchingRule *mr, 793 struct berval *value, 794 void *assertedValue ) 795 { 796 int match; 797 struct berval *asserted = (struct berval *) assertedValue; 798 799 assert( matchp != NULL ); 800 assert( value != NULL ); 801 assert( assertedValue != NULL ); 802 assert( !BER_BVISNULL( value ) ); 803 assert( !BER_BVISNULL( asserted ) ); 804 805 match = value->bv_len - asserted->bv_len; 806 807 if ( match == 0 ) { 808 match = memcmp( value->bv_val, asserted->bv_val, 809 value->bv_len ); 810 } 811 812 Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n", 813 match, value->bv_val, asserted->bv_val ); 814 815 *matchp = match; 816 return LDAP_SUCCESS; 817 } 818 819 /* 820 * dnRelativeMatch routine 821 */ 822 int 823 dnRelativeMatch( 824 int *matchp, 825 slap_mask_t flags, 826 Syntax *syntax, 827 MatchingRule *mr, 828 struct berval *value, 829 void *assertedValue ) 830 { 831 int match; 832 struct berval *asserted = (struct berval *) assertedValue; 833 834 assert( matchp != NULL ); 835 assert( value != NULL ); 836 assert( assertedValue != NULL ); 837 assert( !BER_BVISNULL( value ) ); 838 assert( !BER_BVISNULL( asserted ) ); 839 840 if( mr == slap_schema.si_mr_dnSubtreeMatch ) { 841 if( asserted->bv_len > value->bv_len ) { 842 match = -1; 843 } else if ( asserted->bv_len == value->bv_len ) { 844 match = memcmp( value->bv_val, asserted->bv_val, 845 value->bv_len ); 846 } else { 847 if ( BER_BVISEMPTY( asserted ) ) { 848 match = 0; 849 } else if ( DN_SEPARATOR( 850 value->bv_val[value->bv_len - asserted->bv_len - 1] )) 851 { 852 match = memcmp( 853 &value->bv_val[value->bv_len - asserted->bv_len], 854 asserted->bv_val, 855 asserted->bv_len ); 856 } else { 857 match = 1; 858 } 859 } 860 861 *matchp = match; 862 return LDAP_SUCCESS; 863 } 864 865 if( mr == slap_schema.si_mr_dnSuperiorMatch ) { 866 asserted = value; 867 value = (struct berval *) assertedValue; 868 mr = slap_schema.si_mr_dnSubordinateMatch; 869 } 870 871 if( mr == slap_schema.si_mr_dnSubordinateMatch ) { 872 if( asserted->bv_len >= value->bv_len ) { 873 match = -1; 874 } else { 875 if ( BER_BVISEMPTY( asserted ) ) { 876 match = 0; 877 } else if ( DN_SEPARATOR( 878 value->bv_val[value->bv_len - asserted->bv_len - 1] )) 879 { 880 match = memcmp( 881 &value->bv_val[value->bv_len - asserted->bv_len], 882 asserted->bv_val, 883 asserted->bv_len ); 884 } else { 885 match = 1; 886 } 887 } 888 889 *matchp = match; 890 return LDAP_SUCCESS; 891 } 892 893 if( mr == slap_schema.si_mr_dnOneLevelMatch ) { 894 if( asserted->bv_len >= value->bv_len ) { 895 match = -1; 896 } else { 897 if( DN_SEPARATOR( 898 value->bv_val[value->bv_len - asserted->bv_len - 1] )) 899 { 900 match = memcmp( 901 &value->bv_val[value->bv_len - asserted->bv_len], 902 asserted->bv_val, 903 asserted->bv_len ); 904 905 if( !match ) { 906 struct berval rdn; 907 rdn.bv_val = value->bv_val; 908 rdn.bv_len = value->bv_len - asserted->bv_len - 1; 909 match = dnIsOneLevelRDN( &rdn ) ? 0 : 1; 910 } 911 } else { 912 match = 1; 913 } 914 } 915 916 *matchp = match; 917 return LDAP_SUCCESS; 918 } 919 920 /* should not be reachable */ 921 assert( 0 ); 922 return LDAP_OTHER; 923 } 924 925 int 926 rdnMatch( 927 int *matchp, 928 slap_mask_t flags, 929 Syntax *syntax, 930 MatchingRule *mr, 931 struct berval *value, 932 void *assertedValue ) 933 { 934 int match; 935 struct berval *asserted = (struct berval *) assertedValue; 936 937 assert( matchp != NULL ); 938 assert( value != NULL ); 939 assert( assertedValue != NULL ); 940 941 match = value->bv_len - asserted->bv_len; 942 943 if ( match == 0 ) { 944 match = memcmp( value->bv_val, asserted->bv_val, 945 value->bv_len ); 946 } 947 948 Debug( LDAP_DEBUG_ARGS, "rdnMatch %d\n\t\"%s\"\n\t\"%s\"\n", 949 match, value->bv_val, asserted->bv_val ); 950 951 *matchp = match; 952 return LDAP_SUCCESS; 953 } 954 955 956 /* 957 * dnParent - dn's parent, in-place 958 * note: the incoming dn is assumed to be normalized/prettyfied, 959 * so that escaped rdn/ava separators are in '\'+hexpair form 960 * 961 * note: "dn" and "pdn" can point to the same berval; 962 * beware that, in this case, the pointer to the original buffer 963 * will get lost. 964 */ 965 void 966 dnParent( 967 struct berval *dn, 968 struct berval *pdn ) 969 { 970 char *p; 971 972 p = ber_bvchr( dn, ',' ); 973 974 /* one-level dn */ 975 if ( p == NULL ) { 976 pdn->bv_val = dn->bv_val + dn->bv_len; 977 pdn->bv_len = 0; 978 return; 979 } 980 981 assert( DN_SEPARATOR( p[ 0 ] ) ); 982 p++; 983 984 assert( ATTR_LEADCHAR( p[ 0 ] ) ); 985 pdn->bv_len = dn->bv_len - (p - dn->bv_val); 986 pdn->bv_val = p; 987 988 return; 989 } 990 991 /* 992 * dnRdn - dn's rdn, in-place 993 * note: the incoming dn is assumed to be normalized/prettyfied, 994 * so that escaped rdn/ava separators are in '\'+hexpair form 995 */ 996 void 997 dnRdn( 998 struct berval *dn, 999 struct berval *rdn ) 1000 { 1001 char *p; 1002 1003 *rdn = *dn; 1004 p = ber_bvchr( dn, ',' ); 1005 1006 /* one-level dn */ 1007 if ( p == NULL ) { 1008 return; 1009 } 1010 1011 assert( DN_SEPARATOR( p[ 0 ] ) ); 1012 assert( ATTR_LEADCHAR( p[ 1 ] ) ); 1013 rdn->bv_len = p - dn->bv_val; 1014 1015 return; 1016 } 1017 1018 int 1019 dnExtractRdn( 1020 struct berval *dn, 1021 struct berval *rdn, 1022 void *ctx ) 1023 { 1024 LDAPRDN tmpRDN; 1025 const char *p; 1026 int rc; 1027 1028 assert( dn != NULL ); 1029 assert( rdn != NULL ); 1030 1031 if( dn->bv_len == 0 ) { 1032 return LDAP_OTHER; 1033 } 1034 1035 rc = ldap_bv2rdn_x( dn, &tmpRDN, (char **)&p, LDAP_DN_FORMAT_LDAP, ctx ); 1036 if ( rc != LDAP_SUCCESS ) { 1037 return rc; 1038 } 1039 1040 rc = ldap_rdn2bv_x( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, 1041 ctx ); 1042 1043 ldap_rdnfree_x( tmpRDN, ctx ); 1044 return rc; 1045 } 1046 1047 /* 1048 * We can assume the input is a prettied or normalized DN 1049 */ 1050 ber_len_t 1051 dn_rdnlen( 1052 Backend *be, 1053 struct berval *dn_in ) 1054 { 1055 const char *p; 1056 1057 assert( dn_in != NULL ); 1058 1059 if ( dn_in == NULL ) { 1060 return 0; 1061 } 1062 1063 if ( !dn_in->bv_len ) { 1064 return 0; 1065 } 1066 1067 if ( be != NULL && be_issuffix( be, dn_in ) ) { 1068 return 0; 1069 } 1070 1071 p = ber_bvchr( dn_in, ',' ); 1072 1073 return p ? (ber_len_t) (p - dn_in->bv_val) : dn_in->bv_len; 1074 } 1075 1076 1077 /* rdnValidate: 1078 * 1079 * LDAP_SUCCESS if rdn is a legal rdn; 1080 * LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns) 1081 */ 1082 int 1083 rdn_validate( struct berval *rdn ) 1084 { 1085 #if 1 1086 /* Major cheat! 1087 * input is a pretty or normalized DN 1088 * hence, we can just search for ',' 1089 */ 1090 if( rdn == NULL || rdn->bv_len == 0 || 1091 rdn->bv_len > SLAP_LDAPDN_MAXLEN ) 1092 { 1093 return LDAP_INVALID_SYNTAX; 1094 } 1095 return ber_bvchr( rdn, ',' ) == NULL 1096 ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX; 1097 1098 #else 1099 LDAPRDN *RDN, **DN[ 2 ] = { &RDN, NULL }; 1100 const char *p; 1101 int rc; 1102 1103 /* 1104 * must be non-empty 1105 */ 1106 if ( rdn == NULL || rdn == '\0' ) { 1107 return 0; 1108 } 1109 1110 /* 1111 * must be parsable 1112 */ 1113 rc = ldap_bv2rdn( rdn, &RDN, (char **)&p, LDAP_DN_FORMAT_LDAP ); 1114 if ( rc != LDAP_SUCCESS ) { 1115 return 0; 1116 } 1117 1118 /* 1119 * Must be one-level 1120 */ 1121 if ( p[ 0 ] != '\0' ) { 1122 return 0; 1123 } 1124 1125 /* 1126 * Schema-aware validate 1127 */ 1128 if ( rc == LDAP_SUCCESS ) { 1129 rc = LDAPDN_validate( DN ); 1130 } 1131 ldap_rdnfree( RDN ); 1132 1133 /* 1134 * Must validate (there's a repeated parsing ...) 1135 */ 1136 return ( rc == LDAP_SUCCESS ); 1137 #endif 1138 } 1139 1140 1141 /* build_new_dn: 1142 * 1143 * Used to create the new dn of entries being renamed. 1144 * 1145 * new_dn = parent (p_dn) + separator + rdn (newrdn) + null. 1146 */ 1147 1148 void 1149 build_new_dn( struct berval * new_dn, 1150 struct berval * parent_dn, 1151 struct berval * newrdn, 1152 void *memctx ) 1153 { 1154 char *ptr; 1155 1156 if ( parent_dn == NULL || parent_dn->bv_len == 0 ) { 1157 ber_dupbv_x( new_dn, newrdn, memctx ); 1158 return; 1159 } 1160 1161 new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1; 1162 new_dn->bv_val = (char *) slap_sl_malloc( new_dn->bv_len + 1, memctx ); 1163 1164 ptr = lutil_strncopy( new_dn->bv_val, newrdn->bv_val, newrdn->bv_len ); 1165 *ptr++ = ','; 1166 strcpy( ptr, parent_dn->bv_val ); 1167 } 1168 1169 1170 /* 1171 * dnIsSuffix - tells whether suffix is a suffix of dn. 1172 * Both dn and suffix must be normalized. 1173 */ 1174 int 1175 dnIsSuffix( 1176 const struct berval *dn, 1177 const struct berval *suffix ) 1178 { 1179 int d; 1180 1181 assert( dn != NULL ); 1182 assert( suffix != NULL ); 1183 1184 d = dn->bv_len - suffix->bv_len; 1185 1186 /* empty suffix matches any dn */ 1187 if ( suffix->bv_len == 0 ) { 1188 return 1; 1189 } 1190 1191 /* suffix longer than dn */ 1192 if ( d < 0 ) { 1193 return 0; 1194 } 1195 1196 /* no rdn separator or escaped rdn separator */ 1197 if ( d > 1 && !DN_SEPARATOR( dn->bv_val[ d - 1 ] ) ) { 1198 return 0; 1199 } 1200 1201 /* no possible match or malformed dn */ 1202 if ( d == 1 ) { 1203 return 0; 1204 } 1205 1206 /* compare */ 1207 return( strncmp( dn->bv_val + d, suffix->bv_val, suffix->bv_len ) == 0 ); 1208 } 1209 1210 /* 1211 * In place; assumes: 1212 * - ndn is normalized 1213 * - nbase is normalized 1214 * - dnIsSuffix( ndn, nbase ) == TRUE 1215 * - LDAP_SCOPE_DEFAULT == LDAP_SCOPE_SUBTREE 1216 */ 1217 int 1218 dnIsWithinScope( struct berval *ndn, struct berval *nbase, int scope ) 1219 { 1220 assert( ndn != NULL ); 1221 assert( nbase != NULL ); 1222 assert( !BER_BVISNULL( ndn ) ); 1223 assert( !BER_BVISNULL( nbase ) ); 1224 1225 switch ( scope ) { 1226 case LDAP_SCOPE_DEFAULT: 1227 case LDAP_SCOPE_SUBTREE: 1228 break; 1229 1230 case LDAP_SCOPE_BASE: 1231 if ( ndn->bv_len != nbase->bv_len ) { 1232 return 0; 1233 } 1234 break; 1235 1236 case LDAP_SCOPE_ONELEVEL: { 1237 struct berval pndn; 1238 dnParent( ndn, &pndn ); 1239 if ( pndn.bv_len != nbase->bv_len ) { 1240 return 0; 1241 } 1242 } break; 1243 1244 case LDAP_SCOPE_SUBORDINATE: 1245 if ( ndn->bv_len == nbase->bv_len ) { 1246 return 0; 1247 } 1248 break; 1249 1250 /* unknown scope */ 1251 default: 1252 return -1; 1253 } 1254 1255 return 1; 1256 } 1257 1258 /* 1259 * In place; assumes: 1260 * - ndn is normalized 1261 * - nbase is normalized 1262 * - LDAP_SCOPE_DEFAULT == LDAP_SCOPE_SUBTREE 1263 */ 1264 int 1265 dnIsSuffixScope( struct berval *ndn, struct berval *nbase, int scope ) 1266 { 1267 if ( !dnIsSuffix( ndn, nbase ) ) { 1268 return 0; 1269 } 1270 1271 return dnIsWithinScope( ndn, nbase, scope ); 1272 } 1273 1274 int 1275 dnIsOneLevelRDN( struct berval *rdn ) 1276 { 1277 ber_len_t len = rdn->bv_len; 1278 for ( ; len--; ) { 1279 if ( DN_SEPARATOR( rdn->bv_val[ len ] ) ) { 1280 return 0; 1281 } 1282 } 1283 1284 return 1; 1285 } 1286 1287 #ifdef HAVE_TLS 1288 static SLAP_CERT_MAP_FN *DNX509PeerNormalizeCertMap = NULL; 1289 #endif 1290 1291 int register_certificate_map_function(SLAP_CERT_MAP_FN *fn) 1292 { 1293 #ifdef HAVE_TLS 1294 if ( DNX509PeerNormalizeCertMap == NULL ) { 1295 DNX509PeerNormalizeCertMap = fn; 1296 return 0; 1297 } 1298 #endif 1299 1300 return -1; 1301 } 1302 1303 /* 1304 * Convert an X.509 DN into a normalized LDAP DN 1305 */ 1306 int 1307 dnX509normalize( void *x509_name, struct berval *out ) 1308 { 1309 /* Invoke the LDAP library's converter with our schema-rewriter */ 1310 int rc = ldap_X509dn2bv( x509_name, out, LDAPDN_rewrite, 0 ); 1311 1312 Debug( LDAP_DEBUG_TRACE, 1313 "dnX509Normalize: <%s> (%d)\n", 1314 BER_BVISNULL( out ) ? "(null)" : out->bv_val, rc ); 1315 1316 return rc; 1317 } 1318 1319 #ifdef HAVE_TLS 1320 /* 1321 * Get the TLS session's peer's DN into a normalized LDAP DN 1322 */ 1323 int 1324 dnX509peerNormalize( void *ssl, struct berval *dn ) 1325 { 1326 int rc = LDAP_INVALID_CREDENTIALS; 1327 1328 if ( DNX509PeerNormalizeCertMap != NULL ) 1329 rc = (*DNX509PeerNormalizeCertMap)( ssl, dn ); 1330 1331 if ( rc != LDAP_SUCCESS ) { 1332 rc = ldap_pvt_tls_get_peer_dn( ssl, dn, 1333 (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 ); 1334 } 1335 1336 return rc; 1337 } 1338 #endif 1339