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