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