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