1 /* $NetBSD: oc.c,v 1.1.1.4 2014/05/28 09:58:47 tron Exp $ */ 2 3 /* oc.c - object class routines */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2014 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 "portable.h" 20 21 #include <stdio.h> 22 23 #include <ac/ctype.h> 24 #include <ac/string.h> 25 #include <ac/socket.h> 26 27 #include "slap.h" 28 29 int is_object_subclass( 30 ObjectClass *sup, 31 ObjectClass *sub ) 32 { 33 int i; 34 35 if( sub == NULL || sup == NULL ) return 0; 36 37 #if 0 38 Debug( LDAP_DEBUG_TRACE, "is_object_subclass(%s,%s) %d\n", 39 sup->soc_oid, sub->soc_oid, sup == sub ); 40 #endif 41 42 if ( sup == sub ) { 43 return 1; 44 } 45 46 if ( sub->soc_sups == NULL ) { 47 return 0; 48 } 49 50 for ( i = 0; sub->soc_sups[i] != NULL; i++ ) { 51 if ( is_object_subclass( sup, sub->soc_sups[i] ) ) { 52 return 1; 53 } 54 } 55 56 return 0; 57 } 58 59 int is_entry_objectclass( 60 Entry* e, 61 ObjectClass *oc, 62 unsigned flags ) 63 { 64 /* 65 * set_flags should only be true if oc is one of operational 66 * object classes which we support objectClass flags for 67 * (e.g., referral, alias, ...). See <slap.h>. 68 */ 69 70 Attribute *attr; 71 struct berval *bv; 72 73 assert( !( e == NULL || oc == NULL ) ); 74 assert( ( flags & SLAP_OCF_MASK ) != SLAP_OCF_MASK ); 75 76 if ( e == NULL || oc == NULL ) { 77 return 0; 78 } 79 80 if ( flags == SLAP_OCF_SET_FLAGS && ( e->e_ocflags & SLAP_OC__END ) ) 81 { 82 /* flags are set, use them */ 83 return (e->e_ocflags & oc->soc_flags & SLAP_OC__MASK) != 0; 84 } 85 86 /* 87 * find objectClass attribute 88 */ 89 attr = attr_find( e->e_attrs, slap_schema.si_ad_objectClass ); 90 if ( attr == NULL ) { 91 /* no objectClass attribute */ 92 Debug( LDAP_DEBUG_ANY, "is_entry_objectclass(\"%s\", \"%s\") " 93 "no objectClass attribute\n", 94 e->e_dn == NULL ? "" : e->e_dn, 95 oc->soc_oclass.oc_oid, 0 ); 96 97 /* mark flags as set */ 98 e->e_ocflags |= SLAP_OC__END; 99 100 return 0; 101 } 102 103 for ( bv = attr->a_vals; bv->bv_val; bv++ ) { 104 ObjectClass *objectClass = oc_bvfind( bv ); 105 106 if ( objectClass == NULL ) { 107 /* FIXME: is this acceptable? */ 108 continue; 109 } 110 111 if ( !( flags & SLAP_OCF_SET_FLAGS ) ) { 112 if ( objectClass == oc ) { 113 return 1; 114 } 115 116 if ( ( flags & SLAP_OCF_CHECK_SUP ) 117 && is_object_subclass( oc, objectClass ) ) 118 { 119 return 1; 120 } 121 } 122 123 e->e_ocflags |= objectClass->soc_flags; 124 } 125 126 /* mark flags as set */ 127 e->e_ocflags |= SLAP_OC__END; 128 129 return ( e->e_ocflags & oc->soc_flags & SLAP_OC__MASK ) != 0; 130 } 131 132 133 struct oindexrec { 134 struct berval oir_name; 135 ObjectClass *oir_oc; 136 }; 137 138 static Avlnode *oc_index = NULL; 139 static Avlnode *oc_cache = NULL; 140 static LDAP_STAILQ_HEAD(OCList, ObjectClass) oc_list 141 = LDAP_STAILQ_HEAD_INITIALIZER(oc_list); 142 143 ObjectClass *oc_sys_tail; 144 145 static int 146 oc_index_cmp( 147 const void *v_oir1, 148 const void *v_oir2 ) 149 { 150 const struct oindexrec *oir1 = v_oir1, *oir2 = v_oir2; 151 int i = oir1->oir_name.bv_len - oir2->oir_name.bv_len; 152 if (i) return i; 153 return strcasecmp( oir1->oir_name.bv_val, oir2->oir_name.bv_val ); 154 } 155 156 static int 157 oc_index_name_cmp( 158 const void *v_name, 159 const void *v_oir ) 160 { 161 const struct berval *name = v_name; 162 const struct oindexrec *oir = v_oir; 163 int i = name->bv_len - oir->oir_name.bv_len; 164 if (i) return i; 165 return strncasecmp( name->bv_val, oir->oir_name.bv_val, name->bv_len ); 166 } 167 168 ObjectClass * 169 oc_find( const char *ocname ) 170 { 171 struct berval bv; 172 173 bv.bv_val = (char *)ocname; 174 bv.bv_len = strlen( ocname ); 175 176 return( oc_bvfind( &bv ) ); 177 } 178 179 ObjectClass * 180 oc_bvfind( struct berval *ocname ) 181 { 182 struct oindexrec *oir; 183 184 if ( oc_cache ) { 185 oir = avl_find( oc_cache, ocname, oc_index_name_cmp ); 186 if ( oir ) return oir->oir_oc; 187 } 188 oir = avl_find( oc_index, ocname, oc_index_name_cmp ); 189 190 if ( oir != NULL ) { 191 if ( at_oc_cache ) { 192 avl_insert( &oc_cache, (caddr_t) oir, 193 oc_index_cmp, avl_dup_error ); 194 } 195 return( oir->oir_oc ); 196 } 197 198 return( NULL ); 199 } 200 201 static LDAP_STAILQ_HEAD(OCUList, ObjectClass) oc_undef_list 202 = LDAP_STAILQ_HEAD_INITIALIZER(oc_undef_list); 203 204 ObjectClass * 205 oc_bvfind_undef( struct berval *ocname ) 206 { 207 ObjectClass *oc = oc_bvfind( ocname ); 208 209 if ( oc ) { 210 return oc; 211 } 212 213 LDAP_STAILQ_FOREACH( oc, &oc_undef_list, soc_next ) { 214 int d = oc->soc_cname.bv_len - ocname->bv_len; 215 216 if ( d ) { 217 continue; 218 } 219 220 if ( strcasecmp( oc->soc_cname.bv_val, ocname->bv_val ) == 0 ) { 221 break; 222 } 223 } 224 225 if ( oc ) { 226 return oc; 227 } 228 229 oc = ch_malloc( sizeof( ObjectClass ) + ocname->bv_len + 1 ); 230 memset( oc, 0, sizeof( ObjectClass ) ); 231 232 oc->soc_cname.bv_len = ocname->bv_len; 233 oc->soc_cname.bv_val = (char *)&oc[ 1 ]; 234 AC_MEMCPY( oc->soc_cname.bv_val, ocname->bv_val, ocname->bv_len ); 235 oc->soc_cname.bv_val[ oc->soc_cname.bv_len ] = '\0'; 236 237 /* canonical to upper case */ 238 ldap_pvt_str2upper( oc->soc_cname.bv_val ); 239 240 LDAP_STAILQ_NEXT( oc, soc_next ) = NULL; 241 ldap_pvt_thread_mutex_lock( &oc_undef_mutex ); 242 LDAP_STAILQ_INSERT_HEAD( &oc_undef_list, oc, soc_next ); 243 ldap_pvt_thread_mutex_unlock( &oc_undef_mutex ); 244 245 return oc; 246 } 247 248 static int 249 oc_create_required( 250 ObjectClass *soc, 251 char **attrs, 252 int *op, 253 const char **err ) 254 { 255 char **attrs1; 256 AttributeType *sat; 257 AttributeType **satp; 258 int i; 259 260 if ( attrs ) { 261 attrs1 = attrs; 262 while ( *attrs1 ) { 263 sat = at_find(*attrs1); 264 if ( !sat ) { 265 *err = *attrs1; 266 return SLAP_SCHERR_ATTR_NOT_FOUND; 267 } 268 269 if( is_at_operational( sat )) (*op)++; 270 271 if ( at_find_in_list(sat, soc->soc_required) < 0) { 272 if ( at_append_to_list(sat, &soc->soc_required) ) { 273 *err = *attrs1; 274 return SLAP_SCHERR_OUTOFMEM; 275 } 276 } 277 attrs1++; 278 } 279 /* Now delete duplicates from the allowed list */ 280 for ( satp = soc->soc_required; *satp; satp++ ) { 281 i = at_find_in_list(*satp, soc->soc_allowed); 282 if ( i >= 0 ) { 283 at_delete_from_list(i, &soc->soc_allowed); 284 } 285 } 286 } 287 return 0; 288 } 289 290 static int 291 oc_create_allowed( 292 ObjectClass *soc, 293 char **attrs, 294 int *op, 295 const char **err ) 296 { 297 char **attrs1; 298 AttributeType *sat; 299 300 if ( attrs ) { 301 attrs1 = attrs; 302 while ( *attrs1 ) { 303 sat = at_find(*attrs1); 304 if ( !sat ) { 305 *err = *attrs1; 306 return SLAP_SCHERR_ATTR_NOT_FOUND; 307 } 308 309 if( is_at_operational( sat )) (*op)++; 310 311 if ( at_find_in_list(sat, soc->soc_required) < 0 && 312 at_find_in_list(sat, soc->soc_allowed) < 0 ) { 313 if ( at_append_to_list(sat, &soc->soc_allowed) ) { 314 *err = *attrs1; 315 return SLAP_SCHERR_OUTOFMEM; 316 } 317 } 318 attrs1++; 319 } 320 } 321 return 0; 322 } 323 324 static int 325 oc_add_sups( 326 ObjectClass *soc, 327 char **sups, 328 int *op, 329 const char **err ) 330 { 331 int code; 332 ObjectClass *soc1; 333 int nsups; 334 char **sups1; 335 int add_sups = 0; 336 337 if ( sups ) { 338 if ( !soc->soc_sups ) { 339 /* We are at the first recursive level */ 340 add_sups = 1; 341 nsups = 1; 342 sups1 = sups; 343 while ( *sups1 ) { 344 nsups++; 345 sups1++; 346 } 347 soc->soc_sups = (ObjectClass **)ch_calloc(nsups, 348 sizeof(ObjectClass *)); 349 } 350 351 nsups = 0; 352 sups1 = sups; 353 while ( *sups1 ) { 354 soc1 = oc_find(*sups1); 355 if ( !soc1 ) { 356 *err = *sups1; 357 return SLAP_SCHERR_CLASS_NOT_FOUND; 358 } 359 360 /* check object class usage 361 * abstract classes can only sup abstract classes 362 * structural classes can not sup auxiliary classes 363 * auxiliary classes can not sup structural classes 364 */ 365 if( soc->soc_kind != soc1->soc_kind 366 && soc1->soc_kind != LDAP_SCHEMA_ABSTRACT ) 367 { 368 *err = *sups1; 369 return SLAP_SCHERR_CLASS_BAD_SUP; 370 } 371 372 if( soc1->soc_obsolete && !soc->soc_obsolete ) { 373 *err = *sups1; 374 return SLAP_SCHERR_CLASS_BAD_SUP; 375 } 376 377 if( soc->soc_flags & SLAP_OC_OPERATIONAL ) (*op)++; 378 379 if ( add_sups ) { 380 soc->soc_sups[nsups] = soc1; 381 } 382 383 code = oc_add_sups( soc, soc1->soc_sup_oids, op, err ); 384 if ( code ) return code; 385 386 code = oc_create_required( soc, soc1->soc_at_oids_must, op, err ); 387 if ( code ) return code; 388 389 code = oc_create_allowed( soc, soc1->soc_at_oids_may, op, err ); 390 if ( code ) return code; 391 392 nsups++; 393 sups1++; 394 } 395 } 396 397 return 0; 398 } 399 400 static void 401 oc_delete_names( ObjectClass *oc ) 402 { 403 char **names = oc->soc_names; 404 405 if (!names) return; 406 407 while (*names) { 408 struct oindexrec tmpoir, *oir; 409 410 ber_str2bv( *names, 0, 0, &tmpoir.oir_name ); 411 tmpoir.oir_oc = oc; 412 oir = (struct oindexrec *)avl_delete( &oc_index, 413 (caddr_t)&tmpoir, oc_index_cmp ); 414 assert( oir != NULL ); 415 ldap_memfree( oir ); 416 names++; 417 } 418 } 419 420 /* Mark the ObjectClass as deleted, remove from list, and remove all its 421 * names from the AVL tree. Leave the OID in the tree. 422 */ 423 void 424 oc_delete( ObjectClass *oc ) 425 { 426 oc->soc_flags |= SLAP_OC_DELETED; 427 428 LDAP_STAILQ_REMOVE(&oc_list, oc, ObjectClass, soc_next); 429 430 oc_delete_names( oc ); 431 } 432 433 static void 434 oc_clean( ObjectClass *o ) 435 { 436 if (o->soc_sups) { 437 ldap_memfree(o->soc_sups); 438 o->soc_sups = NULL; 439 } 440 if (o->soc_required) { 441 ldap_memfree(o->soc_required); 442 o->soc_required = NULL; 443 } 444 if (o->soc_allowed) { 445 ldap_memfree(o->soc_allowed); 446 o->soc_allowed = NULL; 447 } 448 if (o->soc_oidmacro) { 449 ldap_memfree(o->soc_oidmacro); 450 o->soc_oidmacro = NULL; 451 } 452 } 453 454 static void 455 oc_destroy_one( void *v ) 456 { 457 struct oindexrec *oir = v; 458 ObjectClass *o = oir->oir_oc; 459 460 oc_clean( o ); 461 ldap_objectclass_free((LDAPObjectClass *)o); 462 ldap_memfree(oir); 463 } 464 465 void 466 oc_destroy( void ) 467 { 468 ObjectClass *o; 469 470 while( !LDAP_STAILQ_EMPTY(&oc_list) ) { 471 o = LDAP_STAILQ_FIRST(&oc_list); 472 LDAP_STAILQ_REMOVE_HEAD(&oc_list, soc_next); 473 474 oc_delete_names( o ); 475 } 476 477 avl_free( oc_index, oc_destroy_one ); 478 479 while( !LDAP_STAILQ_EMPTY(&oc_undef_list) ) { 480 o = LDAP_STAILQ_FIRST(&oc_undef_list); 481 LDAP_STAILQ_REMOVE_HEAD(&oc_undef_list, soc_next); 482 483 ch_free( (ObjectClass *)o ); 484 } 485 } 486 487 int 488 oc_start( ObjectClass **oc ) 489 { 490 assert( oc != NULL ); 491 492 *oc = LDAP_STAILQ_FIRST(&oc_list); 493 494 return (*oc != NULL); 495 } 496 497 int 498 oc_next( ObjectClass **oc ) 499 { 500 assert( oc != NULL ); 501 502 #if 0 /* pedantic check: breaks when deleting an oc, don't use it. */ 503 { 504 ObjectClass *tmp = NULL; 505 506 LDAP_STAILQ_FOREACH(tmp,&oc_list,soc_next) { 507 if ( tmp == *oc ) { 508 break; 509 } 510 } 511 512 assert( tmp != NULL ); 513 } 514 #endif 515 516 if ( *oc == NULL ) { 517 return 0; 518 } 519 520 *oc = LDAP_STAILQ_NEXT(*oc,soc_next); 521 522 return (*oc != NULL); 523 } 524 525 /* 526 * check whether the two ObjectClasses actually __are__ identical, 527 * or rather inconsistent 528 */ 529 static int 530 oc_check_dup( 531 ObjectClass *soc, 532 ObjectClass *new_soc ) 533 { 534 if ( new_soc->soc_oid != NULL ) { 535 if ( soc->soc_oid == NULL ) { 536 return SLAP_SCHERR_CLASS_INCONSISTENT; 537 } 538 539 if ( strcmp( soc->soc_oid, new_soc->soc_oid ) != 0 ) { 540 return SLAP_SCHERR_CLASS_INCONSISTENT; 541 } 542 543 } else { 544 if ( soc->soc_oid != NULL ) { 545 return SLAP_SCHERR_CLASS_INCONSISTENT; 546 } 547 } 548 549 if ( new_soc->soc_names ) { 550 int i; 551 552 if ( soc->soc_names == NULL ) { 553 return SLAP_SCHERR_CLASS_INCONSISTENT; 554 } 555 556 for ( i = 0; new_soc->soc_names[ i ]; i++ ) { 557 if ( soc->soc_names[ i ] == NULL ) { 558 return SLAP_SCHERR_CLASS_INCONSISTENT; 559 } 560 561 if ( strcasecmp( soc->soc_names[ i ], 562 new_soc->soc_names[ i ] ) != 0 ) 563 { 564 return SLAP_SCHERR_CLASS_INCONSISTENT; 565 } 566 } 567 } else { 568 if ( soc->soc_names != NULL ) { 569 return SLAP_SCHERR_CLASS_INCONSISTENT; 570 } 571 } 572 573 return SLAP_SCHERR_CLASS_DUP; 574 } 575 576 static struct oindexrec *oir_old; 577 578 static int 579 oc_dup_error( void *left, void *right ) 580 { 581 oir_old = left; 582 return -1; 583 } 584 585 static int 586 oc_insert( 587 ObjectClass **roc, 588 ObjectClass *prev, 589 const char **err ) 590 { 591 struct oindexrec *oir; 592 char **names; 593 ObjectClass *soc = *roc; 594 595 if ( soc->soc_oid ) { 596 oir = (struct oindexrec *) 597 ch_calloc( 1, sizeof(struct oindexrec) ); 598 ber_str2bv( soc->soc_oid, 0, 0, &oir->oir_name ); 599 oir->oir_oc = soc; 600 oir_old = NULL; 601 602 if ( avl_insert( &oc_index, (caddr_t) oir, 603 oc_index_cmp, oc_dup_error ) ) 604 { 605 ObjectClass *old_soc; 606 int rc; 607 608 *err = soc->soc_oid; 609 610 assert( oir_old != NULL ); 611 old_soc = oir_old->oir_oc; 612 613 /* replacing a deleted definition? */ 614 if ( old_soc->soc_flags & SLAP_OC_DELETED ) { 615 ObjectClass tmp; 616 617 /* Keep old oid, free new oid; 618 * Keep new everything else, free old 619 */ 620 tmp = *old_soc; 621 *old_soc = *soc; 622 old_soc->soc_oid = tmp.soc_oid; 623 tmp.soc_oid = soc->soc_oid; 624 *soc = tmp; 625 626 oc_clean( soc ); 627 oc_destroy_one( oir ); 628 629 oir = oir_old; 630 soc = old_soc; 631 *roc = soc; 632 } else { 633 rc = oc_check_dup( old_soc, soc ); 634 635 ldap_memfree( oir ); 636 return rc; 637 } 638 } 639 640 /* FIX: temporal consistency check */ 641 assert( oc_bvfind( &oir->oir_name ) != NULL ); 642 } 643 644 assert( soc != NULL ); 645 646 if ( (names = soc->soc_names) ) { 647 while ( *names ) { 648 oir = (struct oindexrec *) 649 ch_calloc( 1, sizeof(struct oindexrec) ); 650 oir->oir_name.bv_val = *names; 651 oir->oir_name.bv_len = strlen( *names ); 652 oir->oir_oc = soc; 653 654 if ( avl_insert( &oc_index, (caddr_t) oir, 655 oc_index_cmp, avl_dup_error ) ) 656 { 657 ObjectClass *old_soc; 658 int rc; 659 660 *err = *names; 661 662 old_soc = oc_bvfind( &oir->oir_name ); 663 assert( old_soc != NULL ); 664 rc = oc_check_dup( old_soc, soc ); 665 666 ldap_memfree( oir ); 667 668 while ( names > soc->soc_names ) { 669 struct oindexrec tmpoir; 670 671 names--; 672 ber_str2bv( *names, 0, 0, &tmpoir.oir_name ); 673 tmpoir.oir_oc = soc; 674 oir = (struct oindexrec *)avl_delete( &oc_index, 675 (caddr_t)&tmpoir, oc_index_cmp ); 676 assert( oir != NULL ); 677 ldap_memfree( oir ); 678 } 679 680 if ( soc->soc_oid ) { 681 struct oindexrec tmpoir; 682 683 ber_str2bv( soc->soc_oid, 0, 0, &tmpoir.oir_name ); 684 tmpoir.oir_oc = soc; 685 oir = (struct oindexrec *)avl_delete( &oc_index, 686 (caddr_t)&tmpoir, oc_index_cmp ); 687 assert( oir != NULL ); 688 ldap_memfree( oir ); 689 } 690 691 return rc; 692 } 693 694 /* FIX: temporal consistency check */ 695 assert( oc_bvfind(&oir->oir_name) != NULL ); 696 697 names++; 698 } 699 } 700 if ( soc->soc_flags & SLAP_OC_HARDCODE ) { 701 prev = oc_sys_tail; 702 oc_sys_tail = soc; 703 } 704 if ( prev ) { 705 LDAP_STAILQ_INSERT_AFTER( &oc_list, prev, soc, soc_next ); 706 } else { 707 LDAP_STAILQ_INSERT_TAIL( &oc_list, soc, soc_next ); 708 } 709 710 return 0; 711 } 712 713 int 714 oc_add( 715 LDAPObjectClass *oc, 716 int user, 717 ObjectClass **rsoc, 718 ObjectClass *prev, 719 const char **err ) 720 { 721 ObjectClass *soc; 722 int code; 723 int op = 0; 724 char *oidm = NULL; 725 726 if ( oc->oc_names != NULL ) { 727 int i; 728 729 for( i=0; oc->oc_names[i]; i++ ) { 730 if( !slap_valid_descr( oc->oc_names[i] ) ) { 731 return SLAP_SCHERR_BAD_DESCR; 732 } 733 } 734 } 735 736 if ( !OID_LEADCHAR( oc->oc_oid[0] )) { 737 /* Expand OID macros */ 738 char *oid = oidm_find( oc->oc_oid ); 739 if ( !oid ) { 740 *err = oc->oc_oid; 741 return SLAP_SCHERR_OIDM; 742 } 743 if ( oid != oc->oc_oid ) { 744 oidm = oc->oc_oid; 745 oc->oc_oid = oid; 746 } 747 } 748 749 soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) ); 750 AC_MEMCPY( &soc->soc_oclass, oc, sizeof(LDAPObjectClass) ); 751 752 soc->soc_oidmacro = oidm; 753 if( oc->oc_names != NULL ) { 754 soc->soc_cname.bv_val = soc->soc_names[0]; 755 } else { 756 soc->soc_cname.bv_val = soc->soc_oid; 757 } 758 soc->soc_cname.bv_len = strlen( soc->soc_cname.bv_val ); 759 760 if( soc->soc_sup_oids == NULL && 761 soc->soc_kind == LDAP_SCHEMA_STRUCTURAL ) 762 { 763 /* structural object classes implicitly inherit from 'top' */ 764 static char *top_oids[] = { SLAPD_TOP_OID, NULL }; 765 code = oc_add_sups( soc, top_oids, &op, err ); 766 } else { 767 code = oc_add_sups( soc, soc->soc_sup_oids, &op, err ); 768 } 769 770 if ( code != 0 ) { 771 goto done; 772 } 773 774 if ( user && op ) { 775 code = SLAP_SCHERR_CLASS_BAD_SUP; 776 goto done; 777 } 778 779 code = oc_create_required( soc, soc->soc_at_oids_must, &op, err ); 780 if ( code != 0 ) { 781 goto done; 782 } 783 784 code = oc_create_allowed( soc, soc->soc_at_oids_may, &op, err ); 785 if ( code != 0 ) { 786 goto done; 787 } 788 789 if ( user && op ) { 790 code = SLAP_SCHERR_CLASS_BAD_USAGE; 791 goto done; 792 } 793 794 if ( !user ) { 795 soc->soc_flags |= SLAP_OC_HARDCODE; 796 } 797 798 code = oc_insert(&soc,prev,err); 799 done:; 800 if ( code != 0 ) { 801 if ( soc->soc_sups ) { 802 ch_free( soc->soc_sups ); 803 } 804 805 if ( soc->soc_required ) { 806 ch_free( soc->soc_required ); 807 } 808 809 if ( soc->soc_allowed ) { 810 ch_free( soc->soc_allowed ); 811 } 812 813 if ( soc->soc_oidmacro ) { 814 ch_free( soc->soc_oidmacro ); 815 } 816 817 ch_free( soc ); 818 819 } else if ( rsoc ) { 820 *rsoc = soc; 821 } 822 return code; 823 } 824 825 void 826 oc_unparse( BerVarray *res, ObjectClass *start, ObjectClass *end, int sys ) 827 { 828 ObjectClass *oc; 829 int i, num; 830 struct berval bv, *bva = NULL, idx; 831 char ibuf[32]; 832 833 if ( !start ) 834 start = LDAP_STAILQ_FIRST( &oc_list ); 835 836 /* count the result size */ 837 i = 0; 838 for ( oc=start; oc; oc=LDAP_STAILQ_NEXT(oc, soc_next)) { 839 if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) break; 840 i++; 841 if ( oc == end ) break; 842 } 843 if (!i) return; 844 845 num = i; 846 bva = ch_malloc( (num+1) * sizeof(struct berval) ); 847 BER_BVZERO( bva ); 848 idx.bv_val = ibuf; 849 if ( sys ) { 850 idx.bv_len = 0; 851 ibuf[0] = '\0'; 852 } 853 i = 0; 854 for ( oc=start; oc; oc=LDAP_STAILQ_NEXT(oc, soc_next)) { 855 LDAPObjectClass loc, *locp; 856 if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) break; 857 if ( oc->soc_oidmacro ) { 858 loc = oc->soc_oclass; 859 loc.oc_oid = oc->soc_oidmacro; 860 locp = &loc; 861 } else { 862 locp = &oc->soc_oclass; 863 } 864 if ( ldap_objectclass2bv( locp, &bv ) == NULL ) { 865 ber_bvarray_free( bva ); 866 } 867 if ( !sys ) { 868 idx.bv_len = sprintf(idx.bv_val, "{%d}", i); 869 } 870 bva[i].bv_len = idx.bv_len + bv.bv_len; 871 bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 ); 872 strcpy( bva[i].bv_val, ibuf ); 873 strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val ); 874 i++; 875 bva[i].bv_val = NULL; 876 ldap_memfree( bv.bv_val ); 877 if ( oc == end ) break; 878 } 879 *res = bva; 880 } 881 882 int 883 oc_schema_info( Entry *e ) 884 { 885 AttributeDescription *ad_objectClasses = slap_schema.si_ad_objectClasses; 886 ObjectClass *oc; 887 struct berval val; 888 struct berval nval; 889 890 LDAP_STAILQ_FOREACH( oc, &oc_list, soc_next ) { 891 if( oc->soc_flags & SLAP_OC_HIDE ) continue; 892 893 if ( ldap_objectclass2bv( &oc->soc_oclass, &val ) == NULL ) { 894 return -1; 895 } 896 897 nval = oc->soc_cname; 898 899 #if 0 900 Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s (%s)\n", 901 (long) val.bv_len, val.bv_val, nval.bv_val ); 902 #endif 903 904 if( attr_merge_one( e, ad_objectClasses, &val, &nval ) ) { 905 return -1; 906 } 907 ldap_memfree( val.bv_val ); 908 } 909 return 0; 910 } 911 912 int 913 register_oc( const char *def, ObjectClass **soc, int dupok ) 914 { 915 LDAPObjectClass *oc; 916 int code; 917 const char *err; 918 919 oc = ldap_str2objectclass( def, &code, &err, LDAP_SCHEMA_ALLOW_ALL ); 920 if ( !oc ) { 921 Debug( LDAP_DEBUG_ANY, 922 "register_oc: objectclass \"%s\": %s, %s\n", 923 def, ldap_scherr2str(code), err ); 924 return code; 925 } 926 code = oc_add(oc,0,NULL,NULL,&err); 927 if ( code && ( code != SLAP_SCHERR_CLASS_DUP || !dupok )) { 928 Debug( LDAP_DEBUG_ANY, 929 "register_oc: objectclass \"%s\": %s, %s\n", 930 def, scherr2str(code), err ); 931 ldap_objectclass_free(oc); 932 return code; 933 } 934 if ( soc ) 935 *soc = oc_find(oc->oc_names[0]); 936 if ( code ) { 937 ldap_objectclass_free(oc); 938 } else { 939 ldap_memfree(oc); 940 } 941 return 0; 942 } 943