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