1/* at.c - routines for dealing with attribute types */ 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 17#include "portable.h" 18 19#include <stdio.h> 20 21#include <ac/ctype.h> 22#include <ac/errno.h> 23#include <ac/socket.h> 24#include <ac/string.h> 25#include <ac/time.h> 26 27#include "slap.h" 28 29 30const char * 31at_syntax( 32 AttributeType *at ) 33{ 34 for ( ; at != NULL; at = at->sat_sup ) { 35 if ( at->sat_syntax_oid ) { 36 return at->sat_syntax_oid; 37 } 38 } 39 40 assert( 0 ); 41 42 return NULL; 43} 44 45int 46is_at_syntax( 47 AttributeType *at, 48 const char *oid ) 49{ 50 const char *syn_oid = at_syntax( at ); 51 52 if ( syn_oid ) { 53 return strcmp( syn_oid, oid ) == 0; 54 } 55 56 return 0; 57} 58 59int is_at_subtype( 60 AttributeType *sub, 61 AttributeType *sup ) 62{ 63 for( ; sub != NULL; sub = sub->sat_sup ) { 64 if( sub == sup ) return 1; 65 } 66 67 return 0; 68} 69 70struct aindexrec { 71 struct berval air_name; 72 AttributeType *air_at; 73}; 74 75static Avlnode *attr_index = NULL; 76static Avlnode *attr_cache = NULL; 77static LDAP_STAILQ_HEAD(ATList, AttributeType) attr_list 78 = LDAP_STAILQ_HEAD_INITIALIZER(attr_list); 79 80/* Last hardcoded attribute registered */ 81AttributeType *at_sys_tail; 82 83int at_oc_cache; 84 85static int 86attr_index_cmp( 87 const void *v_air1, 88 const void *v_air2 ) 89{ 90 const struct aindexrec *air1 = v_air1; 91 const struct aindexrec *air2 = v_air2; 92 int i = air1->air_name.bv_len - air2->air_name.bv_len; 93 if (i) return i; 94 return (strcasecmp( air1->air_name.bv_val, air2->air_name.bv_val )); 95} 96 97static int 98attr_index_name_cmp( 99 const void *v_type, 100 const void *v_air ) 101{ 102 const struct berval *type = v_type; 103 const struct aindexrec *air = v_air; 104 int i = type->bv_len - air->air_name.bv_len; 105 if (i) return i; 106 return (strncasecmp( type->bv_val, air->air_name.bv_val, type->bv_len )); 107} 108 109AttributeType * 110at_find( const char *name ) 111{ 112 struct berval bv; 113 114 bv.bv_val = (char *)name; 115 bv.bv_len = strlen( name ); 116 117 return at_bvfind( &bv ); 118} 119 120AttributeType * 121at_bvfind( struct berval *name ) 122{ 123 struct aindexrec *air; 124 125 if ( attr_cache ) { 126 air = avl_find( attr_cache, name, attr_index_name_cmp ); 127 if ( air ) return air->air_at; 128 } 129 130 air = avl_find( attr_index, name, attr_index_name_cmp ); 131 132 if ( air ) { 133 if ( air->air_at->sat_flags & SLAP_AT_DELETED ) { 134 air = NULL; 135 } else if (( slapMode & SLAP_TOOL_MODE ) && at_oc_cache ) { 136 avl_insert( &attr_cache, (caddr_t) air, 137 attr_index_cmp, avl_dup_error ); 138 } 139 } 140 141 return air != NULL ? air->air_at : NULL; 142} 143 144int 145at_append_to_list( 146 AttributeType *sat, 147 AttributeType ***listp ) 148{ 149 AttributeType **list; 150 AttributeType **list1; 151 int size; 152 153 list = *listp; 154 if ( !list ) { 155 size = 2; 156 list = ch_calloc(size, sizeof(AttributeType *)); 157 if ( !list ) { 158 return -1; 159 } 160 } else { 161 size = 0; 162 list1 = *listp; 163 while ( *list1 ) { 164 size++; 165 list1++; 166 } 167 size += 2; 168 list1 = ch_realloc(list, size*sizeof(AttributeType *)); 169 if ( !list1 ) { 170 return -1; 171 } 172 list = list1; 173 } 174 list[size-2] = sat; 175 list[size-1] = NULL; 176 *listp = list; 177 return 0; 178} 179 180int 181at_delete_from_list( 182 int pos, 183 AttributeType ***listp ) 184{ 185 AttributeType **list; 186 AttributeType **list1; 187 int i; 188 int j; 189 190 if ( pos < 0 ) { 191 return -2; 192 } 193 list = *listp; 194 for ( i=0; list[i]; i++ ) 195 ; 196 if ( pos >= i ) { 197 return -2; 198 } 199 for ( i=pos, j=pos+1; list[j]; i++, j++ ) { 200 list[i] = list[j]; 201 } 202 list[i] = NULL; 203 /* Tell the runtime this can be shrinked */ 204 list1 = ch_realloc(list, (i+1)*sizeof(AttributeType **)); 205 if ( !list1 ) { 206 return -1; 207 } 208 *listp = list1; 209 return 0; 210} 211 212int 213at_find_in_list( 214 AttributeType *sat, 215 AttributeType **list ) 216{ 217 int i; 218 219 if ( !list ) { 220 return -1; 221 } 222 for ( i=0; list[i]; i++ ) { 223 if ( sat == list[i] ) { 224 return i; 225 } 226 } 227 return -1; 228} 229 230static void 231at_delete_names( AttributeType *at ) 232{ 233 char **names = at->sat_names; 234 235 while (*names) { 236 struct aindexrec tmpair, *air; 237 238 ber_str2bv( *names, 0, 0, &tmpair.air_name ); 239 tmpair.air_at = at; 240 air = (struct aindexrec *)avl_delete( &attr_index, 241 (caddr_t)&tmpair, attr_index_cmp ); 242 assert( air != NULL ); 243 ldap_memfree( air ); 244 names++; 245 } 246} 247 248/* Mark the attribute as deleted, remove from list, and remove all its 249 * names from the AVL tree. Leave the OID in the tree. 250 */ 251void 252at_delete( AttributeType *at ) 253{ 254 at->sat_flags |= SLAP_AT_DELETED; 255 256 LDAP_STAILQ_REMOVE(&attr_list, at, AttributeType, sat_next); 257 258 at_delete_names( at ); 259} 260 261static void 262at_clean( AttributeType *a ) 263{ 264 if ( a->sat_equality ) { 265 MatchingRule *mr; 266 267 mr = mr_find( a->sat_equality->smr_oid ); 268 assert( mr != NULL ); 269 if ( mr != a->sat_equality ) { 270 ch_free( a->sat_equality ); 271 a->sat_equality = NULL; 272 } 273 } 274 275 assert( a->sat_syntax != NULL ); 276 if ( a->sat_syntax != NULL ) { 277 Syntax *syn; 278 279 syn = syn_find( a->sat_syntax->ssyn_oid ); 280 assert( syn != NULL ); 281 if ( syn != a->sat_syntax ) { 282 ch_free( a->sat_syntax ); 283 a->sat_syntax = NULL; 284 } 285 } 286 287 if ( a->sat_oidmacro ) { 288 ldap_memfree( a->sat_oidmacro ); 289 a->sat_oidmacro = NULL; 290 } 291 if ( a->sat_soidmacro ) { 292 ldap_memfree( a->sat_soidmacro ); 293 a->sat_soidmacro = NULL; 294 } 295 if ( a->sat_subtypes ) { 296 ldap_memfree( a->sat_subtypes ); 297 a->sat_subtypes = NULL; 298 } 299} 300 301static void 302at_destroy_one( void *v ) 303{ 304 struct aindexrec *air = v; 305 AttributeType *a = air->air_at; 306 307 at_clean( a ); 308 ad_destroy(a->sat_ad); 309 ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex); 310 ldap_attributetype_free((LDAPAttributeType *)a); 311 ldap_memfree(air); 312} 313 314void 315at_destroy( void ) 316{ 317 AttributeType *a; 318 319 while( !LDAP_STAILQ_EMPTY(&attr_list) ) { 320 a = LDAP_STAILQ_FIRST(&attr_list); 321 LDAP_STAILQ_REMOVE_HEAD(&attr_list, sat_next); 322 323 at_delete_names( a ); 324 } 325 326 avl_free(attr_index, at_destroy_one); 327 328 if ( slap_schema.si_at_undefined ) { 329 ad_destroy(slap_schema.si_at_undefined->sat_ad); 330 } 331 332 if ( slap_schema.si_at_proxied ) { 333 ad_destroy(slap_schema.si_at_proxied->sat_ad); 334 } 335} 336 337int 338at_start( AttributeType **at ) 339{ 340 assert( at != NULL ); 341 342 *at = LDAP_STAILQ_FIRST(&attr_list); 343 344 return (*at != NULL); 345} 346 347int 348at_next( AttributeType **at ) 349{ 350 assert( at != NULL ); 351 352#if 0 /* pedantic check: don't use this */ 353 { 354 AttributeType *tmp = NULL; 355 356 LDAP_STAILQ_FOREACH(tmp,&attr_list,sat_next) { 357 if ( tmp == *at ) { 358 break; 359 } 360 } 361 362 assert( tmp != NULL ); 363 } 364#endif 365 366 *at = LDAP_STAILQ_NEXT(*at,sat_next); 367 368 return (*at != NULL); 369} 370 371/* 372 * check whether the two attributeTypes actually __are__ identical, 373 * or rather inconsistent 374 */ 375static int 376at_check_dup( 377 AttributeType *sat, 378 AttributeType *new_sat ) 379{ 380 if ( new_sat->sat_oid != NULL ) { 381 if ( sat->sat_oid == NULL ) { 382 return SLAP_SCHERR_ATTR_INCONSISTENT; 383 } 384 385 if ( strcmp( sat->sat_oid, new_sat->sat_oid ) != 0 ) { 386 return SLAP_SCHERR_ATTR_INCONSISTENT; 387 } 388 389 } else { 390 if ( sat->sat_oid != NULL ) { 391 return SLAP_SCHERR_ATTR_INCONSISTENT; 392 } 393 } 394 395 if ( new_sat->sat_names ) { 396 int i; 397 398 if ( sat->sat_names == NULL ) { 399 return SLAP_SCHERR_ATTR_INCONSISTENT; 400 } 401 402 for ( i = 0; new_sat->sat_names[ i ]; i++ ) { 403 if ( sat->sat_names[ i ] == NULL ) { 404 return SLAP_SCHERR_ATTR_INCONSISTENT; 405 } 406 407 if ( strcasecmp( sat->sat_names[ i ], 408 new_sat->sat_names[ i ] ) != 0 ) 409 { 410 return SLAP_SCHERR_ATTR_INCONSISTENT; 411 } 412 } 413 } else { 414 if ( sat->sat_names != NULL ) { 415 return SLAP_SCHERR_ATTR_INCONSISTENT; 416 } 417 } 418 419 return SLAP_SCHERR_ATTR_DUP; 420} 421 422static struct aindexrec *air_old; 423 424static int 425at_dup_error( void *left, void *right ) 426{ 427 air_old = left; 428 return -1; 429} 430 431static int 432at_insert( 433 AttributeType **rat, 434 AttributeType *prev, 435 const char **err ) 436{ 437 struct aindexrec *air; 438 char **names = NULL; 439 AttributeType *sat = *rat; 440 441 if ( sat->sat_oid ) { 442 air = (struct aindexrec *) 443 ch_calloc( 1, sizeof(struct aindexrec) ); 444 ber_str2bv( sat->sat_oid, 0, 0, &air->air_name ); 445 air->air_at = sat; 446 air_old = NULL; 447 448 if ( avl_insert( &attr_index, (caddr_t) air, 449 attr_index_cmp, at_dup_error ) ) 450 { 451 AttributeType *old_sat; 452 int rc; 453 454 *err = sat->sat_oid; 455 456 assert( air_old != NULL ); 457 old_sat = air_old->air_at; 458 459 /* replacing a deleted definition? */ 460 if ( old_sat->sat_flags & SLAP_AT_DELETED ) { 461 AttributeType tmp; 462 AttributeDescription *ad; 463 464 /* Keep old oid, free new oid; 465 * Keep old ads, free new ads; 466 * Keep old ad_mutex, free new ad_mutex; 467 * Keep new everything else, free old 468 */ 469 tmp = *old_sat; 470 *old_sat = *sat; 471 old_sat->sat_oid = tmp.sat_oid; 472 tmp.sat_oid = sat->sat_oid; 473 old_sat->sat_ad = tmp.sat_ad; 474 tmp.sat_ad = sat->sat_ad; 475 old_sat->sat_ad_mutex = tmp.sat_ad_mutex; 476 tmp.sat_ad_mutex = sat->sat_ad_mutex; 477 *sat = tmp; 478 479 /* Check for basic ad pointing at old cname */ 480 for ( ad = old_sat->sat_ad; ad; ad=ad->ad_next ) { 481 if ( ad->ad_cname.bv_val == sat->sat_cname.bv_val ) { 482 ad->ad_cname = old_sat->sat_cname; 483 break; 484 } 485 } 486 487 at_clean( sat ); 488 at_destroy_one( air ); 489 490 air = air_old; 491 sat = old_sat; 492 *rat = sat; 493 } else { 494 ldap_memfree( air ); 495 496 rc = at_check_dup( old_sat, sat ); 497 498 return rc; 499 } 500 } 501 /* FIX: temporal consistency check */ 502 at_bvfind( &air->air_name ); 503 } 504 505 names = sat->sat_names; 506 if ( names ) { 507 while ( *names ) { 508 air = (struct aindexrec *) 509 ch_calloc( 1, sizeof(struct aindexrec) ); 510 ber_str2bv( *names, 0, 0, &air->air_name ); 511 air->air_at = sat; 512 if ( avl_insert( &attr_index, (caddr_t) air, 513 attr_index_cmp, avl_dup_error ) ) 514 { 515 AttributeType *old_sat; 516 int rc; 517 518 *err = *names; 519 520 old_sat = at_bvfind( &air->air_name ); 521 assert( old_sat != NULL ); 522 rc = at_check_dup( old_sat, sat ); 523 524 ldap_memfree(air); 525 526 while ( names > sat->sat_names ) { 527 struct aindexrec tmpair; 528 529 names--; 530 ber_str2bv( *names, 0, 0, &tmpair.air_name ); 531 tmpair.air_at = sat; 532 air = (struct aindexrec *)avl_delete( &attr_index, 533 (caddr_t)&tmpair, attr_index_cmp ); 534 assert( air != NULL ); 535 ldap_memfree( air ); 536 } 537 538 if ( sat->sat_oid ) { 539 struct aindexrec tmpair; 540 541 ber_str2bv( sat->sat_oid, 0, 0, &tmpair.air_name ); 542 tmpair.air_at = sat; 543 air = (struct aindexrec *)avl_delete( &attr_index, 544 (caddr_t)&tmpair, attr_index_cmp ); 545 assert( air != NULL ); 546 ldap_memfree( air ); 547 } 548 549 return rc; 550 } 551 /* FIX: temporal consistency check */ 552 at_bvfind(&air->air_name); 553 names++; 554 } 555 } 556 557 if ( sat->sat_oid ) { 558 slap_ad_undef_promote( sat->sat_oid, sat ); 559 } 560 561 names = sat->sat_names; 562 if ( names ) { 563 while ( *names ) { 564 slap_ad_undef_promote( *names, sat ); 565 names++; 566 } 567 } 568 569 if ( sat->sat_flags & SLAP_AT_HARDCODE ) { 570 prev = at_sys_tail; 571 at_sys_tail = sat; 572 } 573 if ( prev ) { 574 LDAP_STAILQ_INSERT_AFTER( &attr_list, prev, sat, sat_next ); 575 } else { 576 LDAP_STAILQ_INSERT_TAIL( &attr_list, sat, sat_next ); 577 } 578 579 return 0; 580} 581 582int 583at_add( 584 LDAPAttributeType *at, 585 int user, 586 AttributeType **rsat, 587 AttributeType *prev, 588 const char **err ) 589{ 590 AttributeType *sat = NULL; 591 MatchingRule *mr = NULL; 592 Syntax *syn = NULL; 593 int i; 594 int code = LDAP_SUCCESS; 595 char *cname = NULL; 596 char *oidm = NULL; 597 char *soidm = NULL; 598 599 if ( !at->at_oid ) { 600 *err = ""; 601 return SLAP_SCHERR_ATTR_INCOMPLETE; 602 } 603 604 if ( !OID_LEADCHAR( at->at_oid[0] )) { 605 char *oid; 606 607 /* Expand OID macros */ 608 oid = oidm_find( at->at_oid ); 609 if ( !oid ) { 610 *err = at->at_oid; 611 return SLAP_SCHERR_OIDM; 612 } 613 if ( oid != at->at_oid ) { 614 oidm = at->at_oid; 615 at->at_oid = oid; 616 } 617 } 618 619 if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) { 620 char *oid; 621 622 /* Expand OID macros */ 623 oid = oidm_find( at->at_syntax_oid ); 624 if ( !oid ) { 625 *err = at->at_syntax_oid; 626 code = SLAP_SCHERR_OIDM; 627 goto error_return; 628 } 629 if ( oid != at->at_syntax_oid ) { 630 soidm = at->at_syntax_oid; 631 at->at_syntax_oid = oid; 632 } 633 } 634 635 if ( at->at_names && at->at_names[0] ) { 636 int i; 637 638 for( i=0; at->at_names[i]; i++ ) { 639 if( !slap_valid_descr( at->at_names[i] ) ) { 640 *err = at->at_names[i]; 641 code = SLAP_SCHERR_BAD_DESCR; 642 goto error_return; 643 } 644 } 645 646 cname = at->at_names[0]; 647 648 } else { 649 cname = at->at_oid; 650 651 } 652 653 *err = cname; 654 655 if ( !at->at_usage && at->at_no_user_mod ) { 656 /* user attribute must be modifable */ 657 code = SLAP_SCHERR_ATTR_BAD_USAGE; 658 goto error_return; 659 } 660 661 if ( at->at_collective ) { 662 if( at->at_usage ) { 663 /* collective attributes cannot be operational */ 664 code = SLAP_SCHERR_ATTR_BAD_USAGE; 665 goto error_return; 666 } 667 668 if( at->at_single_value ) { 669 /* collective attributes cannot be single-valued */ 670 code = SLAP_SCHERR_ATTR_BAD_USAGE; 671 goto error_return; 672 } 673 } 674 675 sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) ); 676 AC_MEMCPY( &sat->sat_atype, at, sizeof(LDAPAttributeType)); 677 678 sat->sat_cname.bv_val = cname; 679 sat->sat_cname.bv_len = strlen( cname ); 680 sat->sat_oidmacro = oidm; 681 sat->sat_soidmacro = soidm; 682 ldap_pvt_thread_mutex_init(&sat->sat_ad_mutex); 683 684 if ( at->at_sup_oid ) { 685 AttributeType *supsat = at_find(at->at_sup_oid); 686 687 if ( supsat == NULL ) { 688 *err = at->at_sup_oid; 689 code = SLAP_SCHERR_ATTR_NOT_FOUND; 690 goto error_return; 691 } 692 693 sat->sat_sup = supsat; 694 695 if ( at_append_to_list(sat, &supsat->sat_subtypes) ) { 696 code = SLAP_SCHERR_OUTOFMEM; 697 goto error_return; 698 } 699 700 if ( sat->sat_usage != supsat->sat_usage ) { 701 /* subtypes must have same usage as their SUP */ 702 code = SLAP_SCHERR_ATTR_BAD_USAGE; 703 goto error_return; 704 } 705 706 if ( supsat->sat_obsolete && !sat->sat_obsolete ) { 707 /* subtypes must be obsolete if super is */ 708 code = SLAP_SCHERR_ATTR_BAD_SUP; 709 goto error_return; 710 } 711 712 if ( sat->sat_flags & SLAP_AT_FINAL ) { 713 /* cannot subtype a "final" attribute type */ 714 code = SLAP_SCHERR_ATTR_BAD_SUP; 715 goto error_return; 716 } 717 } 718 719 /* 720 * Inherit definitions from superiors. We only check the 721 * direct superior since that one has already inherited from 722 * its own superiorss 723 */ 724 if ( sat->sat_sup ) { 725 Syntax *syn = syn_find(sat->sat_sup->sat_syntax->ssyn_oid); 726 if ( syn != sat->sat_sup->sat_syntax ) { 727 sat->sat_syntax = ch_malloc( sizeof( Syntax )); 728 *sat->sat_syntax = *sat->sat_sup->sat_syntax; 729 } else { 730 sat->sat_syntax = sat->sat_sup->sat_syntax; 731 } 732 if ( sat->sat_sup->sat_equality ) { 733 MatchingRule *mr = mr_find( sat->sat_sup->sat_equality->smr_oid ); 734 if ( mr != sat->sat_sup->sat_equality ) { 735 sat->sat_equality = ch_malloc( sizeof( MatchingRule )); 736 *sat->sat_equality = *sat->sat_sup->sat_equality; 737 } else { 738 sat->sat_equality = sat->sat_sup->sat_equality; 739 } 740 } 741 sat->sat_approx = sat->sat_sup->sat_approx; 742 sat->sat_ordering = sat->sat_sup->sat_ordering; 743 sat->sat_substr = sat->sat_sup->sat_substr; 744 } 745 746 /* 747 * check for X-ORDERED attributes 748 */ 749 if ( sat->sat_extensions ) { 750 for (i=0; sat->sat_extensions[i]; i++) { 751 if (!strcasecmp( sat->sat_extensions[i]->lsei_name, 752 "X-ORDERED" ) && sat->sat_extensions[i]->lsei_values ) { 753 if ( !strcasecmp( sat->sat_extensions[i]->lsei_values[0], 754 "VALUES" )) { 755 sat->sat_flags |= SLAP_AT_ORDERED_VAL; 756 break; 757 } else if ( !strcasecmp( sat->sat_extensions[i]->lsei_values[0], 758 "SIBLINGS" )) { 759 sat->sat_flags |= SLAP_AT_ORDERED_SIB; 760 break; 761 } 762 } 763 } 764 } 765 766 if ( !user ) 767 sat->sat_flags |= SLAP_AT_HARDCODE; 768 769 if ( at->at_syntax_oid ) { 770 syn = syn_find(sat->sat_syntax_oid); 771 if ( syn == NULL ) { 772 *err = sat->sat_syntax_oid; 773 code = SLAP_SCHERR_SYN_NOT_FOUND; 774 goto error_return; 775 } 776 777 if ( sat->sat_syntax != NULL && sat->sat_syntax != syn ) { 778 /* BEWARE: no loop detection! */ 779 if ( syn_is_sup( sat->sat_syntax, syn ) ) { 780 code = SLAP_SCHERR_ATTR_BAD_SUP; 781 goto error_return; 782 } 783 } 784 785 sat->sat_syntax = syn; 786 787 } else if ( sat->sat_syntax == NULL ) { 788 code = SLAP_SCHERR_ATTR_INCOMPLETE; 789 goto error_return; 790 } 791 792 if ( sat->sat_equality_oid ) { 793 mr = mr_find(sat->sat_equality_oid); 794 795 if( mr == NULL ) { 796 *err = sat->sat_equality_oid; 797 code = SLAP_SCHERR_MR_NOT_FOUND; 798 goto error_return; 799 } 800 801 if(( mr->smr_usage & SLAP_MR_EQUALITY ) != SLAP_MR_EQUALITY ) { 802 *err = sat->sat_equality_oid; 803 code = SLAP_SCHERR_ATTR_BAD_MR; 804 goto error_return; 805 } 806 807 if( sat->sat_syntax != mr->smr_syntax ) { 808 if( mr->smr_compat_syntaxes == NULL ) { 809 *err = sat->sat_equality_oid; 810 code = SLAP_SCHERR_ATTR_BAD_MR; 811 goto error_return; 812 } 813 814 for(i=0; mr->smr_compat_syntaxes[i]; i++) { 815 if( sat->sat_syntax == mr->smr_compat_syntaxes[i] ) { 816 i = -1; 817 break; 818 } 819 } 820 821 if( i >= 0 ) { 822 *err = sat->sat_equality_oid; 823 code = SLAP_SCHERR_ATTR_BAD_MR; 824 goto error_return; 825 } 826 } 827 828 sat->sat_equality = mr; 829 sat->sat_approx = mr->smr_associated; 830 } 831 832 if ( sat->sat_ordering_oid ) { 833 if( !sat->sat_equality ) { 834 *err = sat->sat_ordering_oid; 835 code = SLAP_SCHERR_ATTR_BAD_MR; 836 goto error_return; 837 } 838 839 mr = mr_find(sat->sat_ordering_oid); 840 841 if( mr == NULL ) { 842 *err = sat->sat_ordering_oid; 843 code = SLAP_SCHERR_MR_NOT_FOUND; 844 goto error_return; 845 } 846 847 if(( mr->smr_usage & SLAP_MR_ORDERING ) != SLAP_MR_ORDERING ) { 848 *err = sat->sat_ordering_oid; 849 code = SLAP_SCHERR_ATTR_BAD_MR; 850 goto error_return; 851 } 852 853 if( sat->sat_syntax != mr->smr_syntax ) { 854 if( mr->smr_compat_syntaxes == NULL ) { 855 *err = sat->sat_ordering_oid; 856 code = SLAP_SCHERR_ATTR_BAD_MR; 857 goto error_return; 858 } 859 860 for(i=0; mr->smr_compat_syntaxes[i]; i++) { 861 if( sat->sat_syntax == mr->smr_compat_syntaxes[i] ) { 862 i = -1; 863 break; 864 } 865 } 866 867 if( i >= 0 ) { 868 *err = sat->sat_ordering_oid; 869 code = SLAP_SCHERR_ATTR_BAD_MR; 870 goto error_return; 871 } 872 } 873 874 sat->sat_ordering = mr; 875 } 876 877 if ( sat->sat_substr_oid ) { 878 if( !sat->sat_equality ) { 879 *err = sat->sat_substr_oid; 880 code = SLAP_SCHERR_ATTR_BAD_MR; 881 goto error_return; 882 } 883 884 mr = mr_find(sat->sat_substr_oid); 885 886 if( mr == NULL ) { 887 *err = sat->sat_substr_oid; 888 code = SLAP_SCHERR_MR_NOT_FOUND; 889 goto error_return; 890 } 891 892 if(( mr->smr_usage & SLAP_MR_SUBSTR ) != SLAP_MR_SUBSTR ) { 893 *err = sat->sat_substr_oid; 894 code = SLAP_SCHERR_ATTR_BAD_MR; 895 goto error_return; 896 } 897 898 /* due to funky LDAP builtin substring rules, 899 * we check against the equality rule assertion 900 * syntax and compat syntaxes instead of those 901 * associated with the substrings rule. 902 */ 903 if( sat->sat_syntax != sat->sat_equality->smr_syntax ) { 904 if( sat->sat_equality->smr_compat_syntaxes == NULL ) { 905 *err = sat->sat_substr_oid; 906 code = SLAP_SCHERR_ATTR_BAD_MR; 907 goto error_return; 908 } 909 910 for(i=0; sat->sat_equality->smr_compat_syntaxes[i]; i++) { 911 if( sat->sat_syntax == 912 sat->sat_equality->smr_compat_syntaxes[i] ) 913 { 914 i = -1; 915 break; 916 } 917 } 918 919 if( i >= 0 ) { 920 *err = sat->sat_substr_oid; 921 code = SLAP_SCHERR_ATTR_BAD_MR; 922 goto error_return; 923 } 924 } 925 926 sat->sat_substr = mr; 927 } 928 929 code = at_insert( &sat, prev, err ); 930 if ( code != 0 ) { 931error_return:; 932 if ( sat ) { 933 ldap_pvt_thread_mutex_destroy( &sat->sat_ad_mutex ); 934 ch_free( sat ); 935 } 936 937 if ( oidm ) { 938 SLAP_FREE( at->at_oid ); 939 at->at_oid = oidm; 940 } 941 942 if ( soidm ) { 943 SLAP_FREE( at->at_syntax_oid ); 944 at->at_syntax_oid = soidm; 945 } 946 947 } else if ( rsat ) { 948 *rsat = sat; 949 } 950 951 return code; 952} 953 954#ifdef LDAP_DEBUG 955#ifdef SLAPD_UNUSED 956static int 957at_index_printnode( void *v_air, void *ignore ) 958{ 959 struct aindexrec *air = v_air; 960 printf("%s = %s\n", 961 air->air_name.bv_val, 962 ldap_attributetype2str(&air->air_at->sat_atype) ); 963 return( 0 ); 964} 965 966static void 967at_index_print( void ) 968{ 969 printf("Printing attribute type index:\n"); 970 (void) avl_apply( attr_index, at_index_printnode, 0, -1, AVL_INORDER ); 971} 972#endif 973#endif 974 975void 976at_unparse( BerVarray *res, AttributeType *start, AttributeType *end, int sys ) 977{ 978 AttributeType *at; 979 int i, num; 980 struct berval bv, *bva = NULL, idx; 981 char ibuf[32]; 982 983 if ( !start ) 984 start = LDAP_STAILQ_FIRST( &attr_list ); 985 986 /* count the result size */ 987 i = 0; 988 for ( at=start; at; at=LDAP_STAILQ_NEXT(at, sat_next)) { 989 if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) break; 990 i++; 991 if ( at == end ) break; 992 } 993 if (!i) return; 994 995 num = i; 996 bva = ch_malloc( (num+1) * sizeof(struct berval) ); 997 BER_BVZERO( bva ); 998 idx.bv_val = ibuf; 999 if ( sys ) { 1000 idx.bv_len = 0; 1001 ibuf[0] = '\0'; 1002 } 1003 i = 0; 1004 for ( at=start; at; at=LDAP_STAILQ_NEXT(at, sat_next)) { 1005 LDAPAttributeType lat, *latp; 1006 if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) break; 1007 if ( at->sat_oidmacro || at->sat_soidmacro ) { 1008 lat = at->sat_atype; 1009 if ( at->sat_oidmacro ) 1010 lat.at_oid = at->sat_oidmacro; 1011 if ( at->sat_soidmacro ) 1012 lat.at_syntax_oid = at->sat_soidmacro; 1013 latp = ⪫ 1014 } else { 1015 latp = &at->sat_atype; 1016 } 1017 if ( ldap_attributetype2bv( latp, &bv ) == NULL ) { 1018 ber_bvarray_free( bva ); 1019 } 1020 if ( !sys ) { 1021 idx.bv_len = sprintf(idx.bv_val, "{%d}", i); 1022 } 1023 bva[i].bv_len = idx.bv_len + bv.bv_len; 1024 bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 ); 1025 strcpy( bva[i].bv_val, ibuf ); 1026 strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val ); 1027 i++; 1028 bva[i].bv_val = NULL; 1029 ldap_memfree( bv.bv_val ); 1030 if ( at == end ) break; 1031 } 1032 *res = bva; 1033} 1034 1035int 1036at_schema_info( Entry *e ) 1037{ 1038 AttributeDescription *ad_attributeTypes = slap_schema.si_ad_attributeTypes; 1039 AttributeType *at; 1040 struct berval val; 1041 struct berval nval; 1042 1043 LDAP_STAILQ_FOREACH(at,&attr_list,sat_next) { 1044 if( at->sat_flags & SLAP_AT_HIDE ) continue; 1045 1046 if ( ldap_attributetype2bv( &at->sat_atype, &val ) == NULL ) { 1047 return -1; 1048 } 1049 1050 ber_str2bv( at->sat_oid, 0, 0, &nval ); 1051 1052 if( attr_merge_one( e, ad_attributeTypes, &val, &nval ) ) 1053 { 1054 return -1; 1055 } 1056 ldap_memfree( val.bv_val ); 1057 } 1058 return 0; 1059} 1060 1061int 1062register_at( const char *def, AttributeDescription **rad, int dupok ) 1063{ 1064 LDAPAttributeType *at; 1065 int code, freeit = 0; 1066 const char *err; 1067 AttributeDescription *ad = NULL; 1068 1069 at = ldap_str2attributetype( def, &code, &err, LDAP_SCHEMA_ALLOW_ALL ); 1070 if ( !at ) { 1071 Debug( LDAP_DEBUG_ANY, 1072 "register_at: AttributeType \"%s\": %s, %s\n", 1073 def, ldap_scherr2str(code), err ); 1074 return code; 1075 } 1076 1077 code = at_add( at, 0, NULL, NULL, &err ); 1078 if ( code ) { 1079 if ( code == SLAP_SCHERR_ATTR_DUP && dupok ) { 1080 freeit = 1; 1081 1082 } else { 1083 Debug( LDAP_DEBUG_ANY, 1084 "register_at: AttributeType \"%s\": %s, %s\n", 1085 def, scherr2str(code), err ); 1086 ldap_attributetype_free( at ); 1087 return code; 1088 } 1089 } 1090 code = slap_str2ad( at->at_names[0], &ad, &err ); 1091 if ( freeit || code ) { 1092 ldap_attributetype_free( at ); 1093 } else { 1094 ldap_memfree( at ); 1095 } 1096 if ( code ) { 1097 Debug( LDAP_DEBUG_ANY, "register_at: AttributeType \"%s\": %s\n", 1098 def, err, 0 ); 1099 } 1100 if ( rad ) *rad = ad; 1101 return code; 1102} 1103